archsup.S 27 KB

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