archsup.S 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315
  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. archsup.S
  9. Abstract:
  10. This module implements assembly-based architecture support routines for the
  11. AMD64 platform.
  12. Author:
  13. Evan Green 6-Jun-2017
  14. Environment:
  15. Boot
  16. --*/
  17. //
  18. // ------------------------------------------------------------------- Includes
  19. //
  20. #include <minoca/kernel/x64.inc>
  21. //
  22. // -------------------------------------------------------------------- Macros
  23. //
  24. //
  25. // ---------------------------------------------------------------- Definitions
  26. //
  27. //
  28. // -------------------------------------------------------------------- Globals
  29. //
  30. //
  31. // ----------------------------------------------------------------------- Code
  32. //
  33. ASSEMBLY_FILE_HEADER
  34. //
  35. // VOID
  36. // BoBreakExceptionHandlerAsm (
  37. // VOID
  38. // )
  39. //
  40. /*++
  41. Routine Description:
  42. This routine is called directly when an debug exception occurs. It sets up
  43. the parameters and calls a C routine to handle the break. It then restores
  44. machine state to return from the exception. The arguments to this function
  45. are pushed by the hardware.
  46. Arguments:
  47. None. RIP, CS, RFLAGS, RSP, and SS have been pushed onto the stack by the
  48. processor, and the stack was 16-byte aligned before the pushes.
  49. Return Value:
  50. None.
  51. --*/
  52. FUNCTION(BoBreakExceptionHandlerAsm)
  53. pushq $0 # Push a dummy error code.
  54. call BoGenerateTrapFrame # Create a local trap frame.
  55. movq %rsp, %rdx # 3rd parameter is trap frame pointer.
  56. xorq %rsi, %rsi # 2nd parameter is NULL.
  57. movq $EXCEPTION_BREAK, %rdi # 1st parameter is the exception.
  58. call KdDebugExceptionHandler # Call the main exception handler.
  59. call BoRestoreTrapFrame # Restore the trap frame
  60. iretq # Return from the exception.
  61. END_FUNCTION(BoBreakExceptionHandlerAsm)
  62. //
  63. // VOID
  64. // BoSingleStepExceptionHandlerAsm (
  65. // VOID
  66. // )
  67. //
  68. /*++
  69. Routine Description:
  70. This routine is called directly when an debug exception occurs. It sets up
  71. the parameters and calls the executive to dispatch the trap.
  72. Arguments:
  73. None. RIP, CS, RFLAGS, RSP, and SS have been pushed onto the stack by the
  74. processor, and the stack was 16-byte aligned before the pushes.
  75. Return Value:
  76. None.
  77. --*/
  78. FUNCTION(BoSingleStepExceptionHandlerAsm)
  79. pushq $0 # Push a dummy error code.
  80. call BoGenerateTrapFrame # Create a local trap frame.
  81. movq %rsp, %rdx # 3rd parameter is trap frame pointer.
  82. xorq %rsi, %rsi # 2nd parameter is NULL.
  83. movq $EXCEPTION_SINGLE_STEP, %rdi # 1st parameter is the exception.
  84. call KdDebugExceptionHandler # Call the main exception handler.
  85. call BoRestoreTrapFrame # Restore the trap frame
  86. iretq # Return from the exception.
  87. END_FUNCTION(BoSingleStepExceptionHandlerAsm)
  88. //
  89. // VOID
  90. // BoDebugServiceHandlerAsm (
  91. // VOID
  92. // )
  93. //
  94. /*++
  95. Routine Description:
  96. This routine is entered via an IDT entry to request debug service. It sets
  97. up the parameters and calls KdDebugExceptionHandler, and then restores
  98. machine state to return from the exception. The arguments to this function
  99. are pushed by the hardware. Upon Entry, the first argument is the debug
  100. service request, and the second argument is the parameter to the request.
  101. Arguments:
  102. None. RIP, CS, RFLAGS, RSP, and SS have been pushed onto the stack by the
  103. processor, and the stack was 16-byte aligned before the pushes.
  104. Return Value:
  105. None.
  106. --*/
  107. FUNCTION(BoDebugServiceHandlerAsm)
  108. pushq $0 # Push a dummy error code.
  109. call BoGenerateTrapFrame # Create a local trap frame.
  110. movq %rsp, %rdx # 3rd parameter is trap frame pointer.
  111. movq TRAP_RSI(%rsp), %rsi # Move 2nd parameter (parameter) into place.
  112. movq TRAP_RDI(%rsp), %rdi # Move 1st parameter (exception) into place.
  113. call KdDebugExceptionHandler # Call the main exception handler.
  114. call BoRestoreTrapFrame # Restore the trap frame
  115. iretq # Return from the exception.
  116. END_FUNCTION(BoDebugServiceHandlerAsm)
  117. //
  118. // VOID
  119. // BoDivideByZeroExceptionHandlerAsm (
  120. // VOID
  121. // )
  122. //
  123. /*++
  124. Routine Description:
  125. This routine is called directly when a divide by zero exception occurs.
  126. Arguments:
  127. None. RIP, CS, RFLAGS, RSP, and SS have been pushed onto the stack by the
  128. processor, and the stack was 16-byte aligned before the pushes.
  129. Return Value:
  130. None.
  131. --*/
  132. FUNCTION(BoDivideByZeroExceptionHandlerAsm)
  133. pushq $0 # Push a dummy error code.
  134. call BoGenerateTrapFrame # Create a local trap frame.
  135. movq %rsp, %rdi # 1st parameter is trap frame pointer.
  136. call BoDivideByZeroHandler # Call the main exception handler.
  137. call BoRestoreTrapFrame # Restore the trap frame
  138. iretq # Return from the exception.
  139. END_FUNCTION(BoDivideByZeroExceptionHandlerAsm)
  140. //
  141. // VOID
  142. // BoProtectionFaultHandlerAsm (
  143. // VOID
  144. // )
  145. //
  146. /*++
  147. Routine Description:
  148. This routine is called directly when a general protection fault occurs.
  149. It's job is to prepare the trap frame, call the appropriate handler, and
  150. then restore the trap frame.
  151. Arguments:
  152. None. RIP, CS, RFLAGS, RSP, and SS have been pushed onto the stack by the
  153. processor, and the stack was 16-byte aligned before the pushes.
  154. Return Value:
  155. None.
  156. --*/
  157. FUNCTION(BoProtectionFaultHandlerAsm)
  158. call BoGenerateTrapFrame # Create a local trap frame.
  159. movq %rsp, %rdx # 3rd parameter is trap frame pointer.
  160. xorq %rsi, %rsi # 2nd parameter is NULL.
  161. movq $EXCEPTION_ACCESS_VIOLATION, %rdi # 1st parameter is the exception.
  162. call KdDebugExceptionHandler # Call the main exception handler.
  163. call BoRestoreTrapFrame # Restore the trap frame
  164. iretq # Return from the exception.
  165. END_FUNCTION(BoProtectionFaultHandlerAsm)
  166. //
  167. // VOID
  168. // BoPageFaultHandlerAsm (
  169. // VOID
  170. // )
  171. //
  172. /*++
  173. Routine Description:
  174. This routine is called directly when a page fault occurs.
  175. Arguments:
  176. None. RIP, CS, RFLAGS, RSP, and SS have been pushed onto the stack by the
  177. processor, and the stack was 16-byte aligned before the pushes.
  178. Return Value:
  179. None.
  180. --*/
  181. FUNCTION(BoPageFaultHandlerAsm)
  182. call BoGenerateTrapFrame # Create a local trap frame.
  183. movq %rsp, %rsi # 2nd parameter is trap frame pointer.
  184. movq %cr2, %rdi # 1st parameter is faulting address.
  185. xorq %rax, %rax # Create a zero register.
  186. movq %rax, %cr2 # Clear cr2.
  187. call BoPageFaultHandler # Call the main exception handler.
  188. call BoRestoreTrapFrame # Restore the trap frame
  189. iretq # Return from the exception.
  190. END_FUNCTION(BoPageFaultHandlerAsm)
  191. //
  192. // VOID
  193. // BoLoadBootDataSegments (
  194. // VOID
  195. // )
  196. //
  197. /*++
  198. Routine Description:
  199. This routine switches the data segments DS and ES to the boot data
  200. segment selectors.
  201. Arguments:
  202. None.
  203. Return Value:
  204. None.
  205. --*/
  206. FUNCTION(BoLoadBootDataSegments)
  207. LOAD_KERNEL_DATA_SEGMENTS # Load up kernel data segments.
  208. ret #
  209. END_FUNCTION(BoLoadBootDataSegments)
  210. //
  211. // VOID
  212. // ArLoadTr (
  213. // USHORT TssSegment
  214. // )
  215. //
  216. /*++
  217. Routine Description:
  218. This routine loads a TSS (Task Selector State).
  219. Arguments:
  220. TssSegment - Supplies the segment selector in the GDT that describes the
  221. TSS.
  222. Return Value:
  223. None.
  224. --*/
  225. FUNCTION(ArLoadTr)
  226. ltr %di # Load the Task Register.
  227. ret # That's it!
  228. END_FUNCTION(ArLoadTr)
  229. //
  230. // VOID
  231. // ArStoreTr (
  232. // PULONG TssSegment
  233. // )
  234. //
  235. /*++
  236. Routine Description:
  237. This routine retrieves the current TSS (Task Selector State) register.
  238. Arguments:
  239. TssSegment - Supplies a pointer where the current TSS segment register will
  240. be returned.
  241. Return Value:
  242. None.
  243. --*/
  244. FUNCTION(ArStoreTr)
  245. str (%rdi) # Store the TR register.
  246. ret # Return
  247. END_FUNCTION(ArStoreTr)
  248. //
  249. // VOID
  250. // ArLoadIdtr (
  251. // PVOID IdtBase
  252. // )
  253. //
  254. /*++
  255. Routine Description:
  256. This routine loads the given Interrupt Descriptor Table.
  257. Arguments:
  258. IdtBase - Supplies a pointer to the base of the IDT.
  259. Return Value:
  260. None.
  261. --*/
  262. FUNCTION(ArLoadIdtr)
  263. lidt (%rdi) # Load the IDT register.
  264. ret # That's it!
  265. END_FUNCTION(ArLoadIdtr)
  266. //
  267. // VOID
  268. // ArStoreIdtr (
  269. // PTABLE_REGISTER IdtRegister
  270. // )
  271. //
  272. /*++
  273. Routine Description:
  274. This routine stores the interrupt descriptor table register into the given
  275. value.
  276. Arguments:
  277. IdtRegister - Supplies a pointer that will receive the value.
  278. Return Value:
  279. None.
  280. --*/
  281. FUNCTION(ArStoreIdtr)
  282. sidt (%rdi) # Store the IDT register.
  283. ret # Return politely.
  284. END_FUNCTION(ArStoreIdtr)
  285. //
  286. // VOID
  287. // ArLoadGdtr (
  288. // PTABLE_REGISTER Gdt
  289. // )
  290. //
  291. /*++
  292. Routine Description:
  293. This routine loads a global descriptor table.
  294. Arguments:
  295. Gdt - Supplies a pointer to the Gdt pointer, which contains the base and
  296. limit for the GDT.
  297. Return Value:
  298. None.
  299. --*/
  300. FUNCTION(ArLoadGdtr)
  301. lgdt (%rdi) # Load the GDT.
  302. //
  303. // In order to load the new GDT, a long jump of some kind is needed. Use a
  304. // far return for this purpose, returning from this routine in the process.
  305. //
  306. popq %rax # Pop the return address into a register.
  307. pushq $KERNEL_CS # Push the return segemnt.
  308. pushq %rax # Push the return address.
  309. retfq # Do a 64-bit far return, loading the GDT.
  310. END_FUNCTION(ArLoadGdtr)
  311. //
  312. // VOID
  313. // ArStoreGdtr (
  314. // PTABLE_REGISTER GdtRegister
  315. // )
  316. //
  317. /*++
  318. Routine Description:
  319. This routine stores the GDT register into the given value.
  320. Arguments:
  321. GdtRegister - Supplies a pointer that will receive the value.
  322. Return Value:
  323. None.
  324. --*/
  325. FUNCTION(ArStoreGdtr)
  326. sgdt (%rdi) # Store the GDT register.
  327. ret # Return politely.
  328. END_FUNCTION(ArStoreGdtr)
  329. //
  330. // PVOID
  331. // ArGetFaultingAddress (
  332. // VOID
  333. // )
  334. //
  335. /*++
  336. Routine Description:
  337. This routine determines which address caused a page fault.
  338. Arguments:
  339. None.
  340. Return Value:
  341. Returns the faulting address.
  342. --*/
  343. FUNCTION(ArGetFaultingAddress)
  344. movq %cr2, %rax # Return CR2.
  345. ret #
  346. END_FUNCTION(ArGetFaultingAddress)
  347. //
  348. // VOID
  349. // ArSetFaultingAddress (
  350. // PVOID Value
  351. // )
  352. //
  353. /*++
  354. Routine Description:
  355. This routine sets the CR2 register.
  356. Arguments:
  357. Value - Supplies the value to set.
  358. Return Value:
  359. None.
  360. --*/
  361. FUNCTION(ArSetFaultingAddress)
  362. movq %rdi, %cr2
  363. ret
  364. END_FUNCTION(ArSetFaultingAddress)
  365. //
  366. // UINTN
  367. // ArGetCurrentPageDirectory (
  368. // VOID
  369. // )
  370. //
  371. /*++
  372. Routine Description:
  373. This routine returns the active page directory.
  374. Arguments:
  375. None.
  376. Return Value:
  377. Returns the page directory currently in use by the system.
  378. --*/
  379. FUNCTION(ArGetCurrentPageDirectory)
  380. movq %cr3, %rax # Return CR3.
  381. ret #
  382. END_FUNCTION(ArGetCurrentPageDirectory)
  383. //
  384. // VOID
  385. // ArSetCurrentPageDirectory (
  386. // UINTN Value
  387. // )
  388. //
  389. /*++
  390. Routine Description:
  391. This routine sets the CR3 register.
  392. Arguments:
  393. Value - Supplies the value to set.
  394. Return Value:
  395. None.
  396. --*/
  397. FUNCTION(ArSetCurrentPageDirectory)
  398. movq %rdi, %cr3
  399. ret
  400. END_FUNCTION(ArSetCurrentPageDirectory)
  401. //
  402. // VOID
  403. // ArCpuid (
  404. // PULONG Eax,
  405. // PULONG Ebx,
  406. // PULONG Ecx,
  407. // PULONG Edx
  408. // )
  409. //
  410. /*++
  411. Routine Description:
  412. This routine executes the CPUID instruction to get processor architecture
  413. information.
  414. Arguments:
  415. Eax - Supplies a pointer to the value that EAX should be set to when the
  416. CPUID instruction is executed. On output, contains the contents of
  417. EAX immediately after the CPUID instruction.
  418. Ebx - Supplies a pointer to the value that EBX should be set to when the
  419. CPUID instruction is executed. On output, contains the contents of
  420. EAX immediately after the CPUID instruction.
  421. Ecx - Supplies a pointer to the value that ECX should be set to when the
  422. CPUID instruction is executed. On output, contains the contents of
  423. EAX immediately after the CPUID instruction.
  424. Edx - Supplies a pointer to the value that EDX should be set to when the
  425. CPUID instruction is executed. On output, contains the contents of
  426. EAX immediately after the CPUID instruction.
  427. Return Value:
  428. None.
  429. --*/
  430. FUNCTION(ArCpuid)
  431. pushq %rbx # Save the only non-volatile involved.
  432. movq %rdx, %r8 # Save rcx into R8
  433. movq %rcx, %r9 # Save rdx into R9.
  434. movl (%rdi), %eax # Dereference to get eax.
  435. movl (%rsi), %ebx # Dereference to get ebx.
  436. movl (%r8), %ecx # Dereference to get ecx.
  437. movl (%r9), %edx # Dereference to get edx.
  438. cpuid # Fire off the CPUID instruction.
  439. movl %edx, (%r9) # Save the resulting edx.
  440. movl %ecx, (%r8) # Save the resulting ecx.
  441. movl %ebx, (%rsi) # Save the resulting ebx.
  442. movl %eax, (%rdi) # Save the resulting eax.
  443. popq %rbx # Restore the non-volatile.
  444. ret
  445. END_FUNCTION(ArCpuid)
  446. //
  447. // UINTN
  448. // ArGetControlRegister0 (
  449. // VOID
  450. // )
  451. //
  452. /*++
  453. Routine Description:
  454. This routine returns the current value of CR0.
  455. Arguments:
  456. None.
  457. Return Value:
  458. Returns CR0.
  459. --*/
  460. FUNCTION(ArGetControlRegister0)
  461. movq %cr0, %rax
  462. ret
  463. END_FUNCTION(ArGetControlRegister0)
  464. //
  465. // VOID
  466. // ArSetControlRegister0 (
  467. // UINTN Value
  468. // )
  469. //
  470. /*++
  471. Routine Description:
  472. This routine sets the CR0 register.
  473. Arguments:
  474. Value - Supplies the value to set.
  475. Return Value:
  476. None.
  477. --*/
  478. FUNCTION(ArSetControlRegister0)
  479. movq %rdi, %cr0
  480. ret
  481. END_FUNCTION(ArSetControlRegister0)
  482. //
  483. // UINTN
  484. // ArGetControlRegister4 (
  485. // VOID
  486. // )
  487. //
  488. /*++
  489. Routine Description:
  490. This routine returns the current value of CR4.
  491. Arguments:
  492. None.
  493. Return Value:
  494. Returns CR4.
  495. --*/
  496. FUNCTION(ArGetControlRegister4)
  497. movq %cr4, %rax
  498. ret
  499. END_FUNCTION(ArGetControlRegister4)
  500. //
  501. // VOID
  502. // ArSetControlRegister4 (
  503. // UINTN Value
  504. // )
  505. //
  506. /*++
  507. Routine Description:
  508. This routine sets the CR4 register.
  509. Arguments:
  510. Value - Supplies the value to set.
  511. Return Value:
  512. None.
  513. --*/
  514. FUNCTION(ArSetControlRegister4)
  515. movq %rdi, %cr4
  516. ret
  517. END_FUNCTION(ArSetControlRegister4)
  518. //
  519. // UINTN
  520. // ArGetDebugRegister0 (
  521. // VOID
  522. // )
  523. //
  524. /*++
  525. Routine Description:
  526. This routine returns the current value of DR0.
  527. Arguments:
  528. None.
  529. Return Value:
  530. Returns DR0.
  531. --*/
  532. FUNCTION(ArGetDebugRegister0)
  533. movq %dr0, %rax
  534. ret
  535. END_FUNCTION(ArGetDebugRegister0)
  536. //
  537. // VOID
  538. // ArSetDebugRegister0 (
  539. // UINTN Value
  540. // )
  541. //
  542. /*++
  543. Routine Description:
  544. This routine sets the DR0 register.
  545. Arguments:
  546. Value - Supplies the value to set.
  547. Return Value:
  548. None.
  549. --*/
  550. FUNCTION(ArSetDebugRegister0)
  551. movq %rdi, %dr0
  552. ret
  553. END_FUNCTION(ArSetDebugRegister0)
  554. //
  555. // UINTN
  556. // ArGetDebugRegister1 (
  557. // VOID
  558. // )
  559. //
  560. /*++
  561. Routine Description:
  562. This routine returns the current value of DR1.
  563. Arguments:
  564. None.
  565. Return Value:
  566. Returns DR1.
  567. --*/
  568. FUNCTION(ArGetDebugRegister1)
  569. movq %dr1, %rax
  570. ret
  571. END_FUNCTION(ArGetDebugRegister1)
  572. //
  573. // VOID
  574. // ArSetDebugRegister1 (
  575. // UINTN Value
  576. // )
  577. //
  578. /*++
  579. Routine Description:
  580. This routine sets the DR1 register.
  581. Arguments:
  582. Value - Supplies the value to set.
  583. Return Value:
  584. None.
  585. --*/
  586. FUNCTION(ArSetDebugRegister1)
  587. movq %rdi, %dr1
  588. ret
  589. END_FUNCTION(ArSetDebugRegister1)
  590. //
  591. // UINTN
  592. // ArGetDebugRegister2 (
  593. // VOID
  594. // )
  595. //
  596. /*++
  597. Routine Description:
  598. This routine returns the current value of DR2.
  599. Arguments:
  600. None.
  601. Return Value:
  602. Returns DR2.
  603. --*/
  604. FUNCTION(ArGetDebugRegister2)
  605. movq %dr2, %rax
  606. ret
  607. END_FUNCTION(ArGetDebugRegister2)
  608. //
  609. // VOID
  610. // ArSetDebugRegister2 (
  611. // UINTN Value
  612. // )
  613. //
  614. /*++
  615. Routine Description:
  616. This routine sets the DR2 register.
  617. Arguments:
  618. Value - Supplies the value to set.
  619. Return Value:
  620. None.
  621. --*/
  622. FUNCTION(ArSetDebugRegister2)
  623. movq %rdi, %dr2
  624. ret
  625. END_FUNCTION(ArSetDebugRegister2)
  626. //
  627. // UINTN
  628. // ArGetDebugRegister3 (
  629. // VOID
  630. // )
  631. //
  632. /*++
  633. Routine Description:
  634. This routine returns the current value of DR3.
  635. Arguments:
  636. None.
  637. Return Value:
  638. Returns DR3.
  639. --*/
  640. FUNCTION(ArGetDebugRegister3)
  641. movq %dr3, %rax
  642. ret
  643. END_FUNCTION(ArGetDebugRegister3)
  644. //
  645. // VOID
  646. // ArSetDebugRegister3 (
  647. // UINTN Value
  648. // )
  649. //
  650. /*++
  651. Routine Description:
  652. This routine sets the DR3 register.
  653. Arguments:
  654. Value - Supplies the value to set.
  655. Return Value:
  656. None.
  657. --*/
  658. FUNCTION(ArSetDebugRegister3)
  659. movq %rdi, %dr3
  660. ret
  661. END_FUNCTION(ArSetDebugRegister3)
  662. //
  663. // UINTN
  664. // ArGetDebugRegister6 (
  665. // VOID
  666. // )
  667. //
  668. /*++
  669. Routine Description:
  670. This routine returns the current value of DR6.
  671. Arguments:
  672. None.
  673. Return Value:
  674. Returns DR6.
  675. --*/
  676. FUNCTION(ArGetDebugRegister6)
  677. movq %dr6, %rax
  678. ret
  679. END_FUNCTION(ArGetDebugRegister6)
  680. //
  681. // VOID
  682. // ArSetDebugRegister6 (
  683. // UINTN Value
  684. // )
  685. //
  686. /*++
  687. Routine Description:
  688. This routine sets the DR6 register.
  689. Arguments:
  690. Value - Supplies the value to set.
  691. Return Value:
  692. None.
  693. --*/
  694. FUNCTION(ArSetDebugRegister6)
  695. movq %rdi, %dr6
  696. ret
  697. END_FUNCTION(ArSetDebugRegister6)
  698. //
  699. // UINTN
  700. // ArGetDebugRegister7 (
  701. // VOID
  702. // )
  703. //
  704. /*++
  705. Routine Description:
  706. This routine returns the current value of DR7.
  707. Arguments:
  708. None.
  709. Return Value:
  710. Returns DR7.
  711. --*/
  712. FUNCTION(ArGetDebugRegister7)
  713. movq %dr7, %rax
  714. ret
  715. END_FUNCTION(ArGetDebugRegister7)
  716. //
  717. // VOID
  718. // ArSetDebugRegister7 (
  719. // UINTN Value
  720. // )
  721. //
  722. /*++
  723. Routine Description:
  724. This routine sets the DR7 register.
  725. Arguments:
  726. Value - Supplies the value to set.
  727. Return Value:
  728. None.
  729. --*/
  730. FUNCTION(ArSetDebugRegister7)
  731. movq %rdi, %dr7
  732. ret
  733. END_FUNCTION(ArSetDebugRegister7)
  734. //
  735. // ULONGLONG
  736. // ArReadTimeStampCounter (
  737. // VOID
  738. // )
  739. //
  740. /*++
  741. Routine Description:
  742. This routine reads the time stamp counter from the current processor. It
  743. is essential that callers of this function understand that this returns
  744. instruction cycles, which does not always translate directly into units
  745. of time. For example, some processors halt the timestamp counter during
  746. performance and CPU idle state transitions. In other cases, the timestamp
  747. counters of all processors are not in sync, so as execution of a thread
  748. bounces unpredictably from one core to another, different timelines may be
  749. observed. Additionally, one must understand that this intrinsic is not a
  750. serializing instruction to the hardware, so the processor may decide to
  751. execute any number of instructions after this one before actually snapping
  752. the timestamp counter. To all those who choose to continue to use this
  753. primitive to measure time, you have been warned.
  754. Arguments:
  755. None.
  756. Return Value:
  757. Returns the current instruction cycle count since the processor was started.
  758. --*/
  759. FUNCTION(ArReadTimeStampCounter)
  760. rdtsc # Store the timestamp counter in EDX:EAX.
  761. shlq $32, %rdx # Shift rdx into its high word.
  762. orq %rdx, %rax # OR rdx into rax.
  763. ret # And return!
  764. END_FUNCTION(ArReadTimeStampCounter)
  765. //
  766. // --------------------------------------------------------- Internal Functions
  767. //
  768. //
  769. // VOID
  770. // BoRestoreTrapFrame (
  771. // TRAP_FRAME TrapFrame
  772. // )
  773. //
  774. /*++
  775. Routine Description:
  776. This routine restores information contained in a trap frame to the
  777. processor and prepares the machine for an iretq back to the code that
  778. generated this trap frame. It's not really a function because it assumes
  779. a specific stack layout and modifies data that technically belongs to the
  780. caller. It should only be called immediately before returning from an
  781. exception or interrupt. This routine will pop up to and including the error
  782. code.
  783. Arguments:
  784. TrapFrame - Supplies the trap frame to restore.
  785. Return Value:
  786. Upon return, the trap frame will have been popped off the stack, and the
  787. machine will be in the same state as right after the exception happened.
  788. --*/
  789. BoRestoreTrapFrame:
  790. popq %rax # Pop return address.
  791. movq %rax, TRAP_ERRORCODE(%rsp) # Save into convenient return slot.
  792. movl TRAP_DS(%rsp), %ecx # Restore ds.
  793. movw %cx, %ds #
  794. movl TRAP_ES(%rsp), %ecx # Restore es.
  795. movw %cx, %es #
  796. movq TRAP_RAX(%rsp), %rax # Restore general registers.
  797. movq TRAP_RBX(%rsp), %rbx #
  798. movq TRAP_RCX(%rsp), %rcx #
  799. movq TRAP_RDX(%rsp), %rdx #
  800. movq TRAP_RSI(%rsp), %rsi #
  801. movq TRAP_RDI(%rsp), %rdi #
  802. movq TRAP_RBP(%rsp), %rbp #
  803. movq TRAP_R8(%rsp), %r8 #
  804. movq TRAP_R9(%rsp), %r9 #
  805. movq TRAP_R10(%rsp), %r10 #
  806. movq TRAP_R11(%rsp), %r11 #
  807. movq TRAP_R12(%rsp), %r12 #
  808. movq TRAP_R13(%rsp), %r13 #
  809. movq TRAP_R14(%rsp), %r14 #
  810. movq TRAP_R15(%rsp), %r15 #
  811. addq $TRAP_ERRORCODE, %rsp # Pop off non-hardware portion.
  812. ret # Pop error code to return.
  813. //
  814. // TRAP_FRAME
  815. // BoGenerateTrapFrame (
  816. // ULONGLONG ErrorCode,
  817. // ULONGLONG ReturnRip,
  818. // ULONGLONG ReturnCs,
  819. // ULONGLONG ReturnRflags,
  820. // ULONGLONG ReturnRsp,
  821. // ULONGLONG ReturnSs
  822. // )
  823. //
  824. /*++
  825. Routine Description:
  826. This routine generates a trap frame based on the data pushed onto the
  827. stack by the processor after an exception. It is not really a function
  828. in that it assumes a certain stack layout and will modify data that
  829. belongs to the caller. This function should only be called immediately
  830. after an interrupt/exception.
  831. Arguments:
  832. ErrorCode - Supplies the error code that generated the fault, or a dummy
  833. error code should be pushed if this was not an exception where the
  834. hardware would push it.
  835. ReturnRip - Supplies the instruction that generated the exception.
  836. ReturnCs - Supplies the code selector of the code that generated the
  837. exception.
  838. ReturnRflags - Supplies the flags of the code that generated the
  839. exception.
  840. ReturnRsp - Supplies the stack pointer of the code that generated the
  841. exception.
  842. ReturnSs - Supplies the stack segment of the code that generated the
  843. exception.
  844. Return Value:
  845. Upon return, a TRAP_FRAME will be on the top of the stack.
  846. --*/
  847. BoGenerateTrapFrame:
  848. //
  849. // Allocate room on the stack for the trap frame, minus the original
  850. // return address, minus the fields that have already been pushed by
  851. // hardware.
  852. //
  853. subq $TRAP_R15, %rsp # Allocate remaining trap frame space.
  854. movq %rax, TRAP_RAX(%rsp) # Save RAX to free it up.
  855. movq TRAP_R15(%rsp), %rax # Get the return address.
  856. movq %rbx, TRAP_RBX(%rsp) # Save the general registers.
  857. movq %rcx, TRAP_RCX(%rsp) #
  858. movq %rdx, TRAP_RDX(%rsp) #
  859. movq %rsi, TRAP_RSI(%rsp) #
  860. movq %rdi, TRAP_RDI(%rsp) #
  861. movq %rbp, TRAP_RBP(%rsp) #
  862. movq %r8, TRAP_R8(%rsp) #
  863. movq %r9, TRAP_R9(%rsp) #
  864. movq %r10, TRAP_R10(%rsp) #
  865. movq %r11, TRAP_R11(%rsp) #
  866. movq %r12, TRAP_R12(%rsp) #
  867. movq %r13, TRAP_R13(%rsp) #
  868. movq %r14, TRAP_R14(%rsp) #
  869. movq %r15, TRAP_R15(%rsp) #
  870. movq %ds, %rcx #
  871. movl %ecx, TRAP_DS(%rsp) # Save DS.
  872. movq %es, %rcx #
  873. movl %ecx, TRAP_ES(%rsp) # Save ES.
  874. movq %fs, %rcx #
  875. movl %ecx, TRAP_FS(%rsp) # Save FS.
  876. movq %gs, %rcx #
  877. movl %ecx, TRAP_GS(%rsp) # Save GS.
  878. jmp *%rax # Return