SmiException.nasm 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705
  1. ;------------------------------------------------------------------------------ ;
  2. ; Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
  3. ; SPDX-License-Identifier: BSD-2-Clause-Patent
  4. ;
  5. ; Module Name:
  6. ;
  7. ; SmiException.nasm
  8. ;
  9. ; Abstract:
  10. ;
  11. ; Exception handlers used in SM mode
  12. ;
  13. ;-------------------------------------------------------------------------------
  14. extern ASM_PFX(FeaturePcdGet (PcdCpuSmmProfileEnable))
  15. extern ASM_PFX(SmiPFHandler)
  16. extern ASM_PFX(mSetupDebugTrap)
  17. global ASM_PFX(gcSmiIdtr)
  18. global ASM_PFX(gcSmiGdtr)
  19. global ASM_PFX(gTaskGateDescriptor)
  20. global ASM_PFX(gcPsd)
  21. SECTION .data
  22. NullSeg: DQ 0 ; reserved by architecture
  23. CodeSeg32:
  24. DW -1 ; LimitLow
  25. DW 0 ; BaseLow
  26. DB 0 ; BaseMid
  27. DB 0x9b
  28. DB 0xcf ; LimitHigh
  29. DB 0 ; BaseHigh
  30. ProtModeCodeSeg32:
  31. DW -1 ; LimitLow
  32. DW 0 ; BaseLow
  33. DB 0 ; BaseMid
  34. DB 0x9b
  35. DB 0xcf ; LimitHigh
  36. DB 0 ; BaseHigh
  37. ProtModeSsSeg32:
  38. DW -1 ; LimitLow
  39. DW 0 ; BaseLow
  40. DB 0 ; BaseMid
  41. DB 0x93
  42. DB 0xcf ; LimitHigh
  43. DB 0 ; BaseHigh
  44. DataSeg32:
  45. DW -1 ; LimitLow
  46. DW 0 ; BaseLow
  47. DB 0 ; BaseMid
  48. DB 0x93
  49. DB 0xcf ; LimitHigh
  50. DB 0 ; BaseHigh
  51. CodeSeg16:
  52. DW -1
  53. DW 0
  54. DB 0
  55. DB 0x9b
  56. DB 0x8f
  57. DB 0
  58. DataSeg16:
  59. DW -1
  60. DW 0
  61. DB 0
  62. DB 0x93
  63. DB 0x8f
  64. DB 0
  65. CodeSeg64:
  66. DW -1 ; LimitLow
  67. DW 0 ; BaseLow
  68. DB 0 ; BaseMid
  69. DB 0x9b
  70. DB 0xaf ; LimitHigh
  71. DB 0 ; BaseHigh
  72. GDT_SIZE equ $ - NullSeg
  73. TssSeg:
  74. DW TSS_DESC_SIZE ; LimitLow
  75. DW 0 ; BaseLow
  76. DB 0 ; BaseMid
  77. DB 0x89
  78. DB 0x80 ; LimitHigh
  79. DB 0 ; BaseHigh
  80. ExceptionTssSeg:
  81. DW EXCEPTION_TSS_DESC_SIZE ; LimitLow
  82. DW 0 ; BaseLow
  83. DB 0 ; BaseMid
  84. DB 0x89
  85. DB 0x80 ; LimitHigh
  86. DB 0 ; BaseHigh
  87. CODE_SEL equ CodeSeg32 - NullSeg
  88. DATA_SEL equ DataSeg32 - NullSeg
  89. TSS_SEL equ TssSeg - NullSeg
  90. EXCEPTION_TSS_SEL equ ExceptionTssSeg - NullSeg
  91. struc IA32_TSS
  92. resw 1
  93. resw 1
  94. .ESP0: resd 1
  95. .SS0: resw 1
  96. resw 1
  97. .ESP1: resd 1
  98. .SS1: resw 1
  99. resw 1
  100. .ESP2: resd 1
  101. .SS2: resw 1
  102. resw 1
  103. ._CR3: resd 1
  104. .EIP: resd 1
  105. .EFLAGS: resd 1
  106. ._EAX: resd 1
  107. ._ECX: resd 1
  108. ._EDX: resd 1
  109. ._EBX: resd 1
  110. ._ESP: resd 1
  111. ._EBP: resd 1
  112. ._ESI: resd 1
  113. ._EDI: resd 1
  114. ._ES: resw 1
  115. resw 1
  116. ._CS: resw 1
  117. resw 1
  118. ._SS: resw 1
  119. resw 1
  120. ._DS: resw 1
  121. resw 1
  122. ._FS: resw 1
  123. resw 1
  124. ._GS: resw 1
  125. resw 1
  126. .LDT: resw 1
  127. resw 1
  128. resw 1
  129. resw 1
  130. endstruc
  131. ; Create 2 TSS segments just after GDT
  132. TssDescriptor:
  133. DW 0 ; PreviousTaskLink
  134. DW 0 ; Reserved
  135. DD 0 ; ESP0
  136. DW 0 ; SS0
  137. DW 0 ; Reserved
  138. DD 0 ; ESP1
  139. DW 0 ; SS1
  140. DW 0 ; Reserved
  141. DD 0 ; ESP2
  142. DW 0 ; SS2
  143. DW 0 ; Reserved
  144. DD 0 ; CR3
  145. DD 0 ; EIP
  146. DD 0 ; EFLAGS
  147. DD 0 ; EAX
  148. DD 0 ; ECX
  149. DD 0 ; EDX
  150. DD 0 ; EBX
  151. DD 0 ; ESP
  152. DD 0 ; EBP
  153. DD 0 ; ESI
  154. DD 0 ; EDI
  155. DW 0 ; ES
  156. DW 0 ; Reserved
  157. DW 0 ; CS
  158. DW 0 ; Reserved
  159. DW 0 ; SS
  160. DW 0 ; Reserved
  161. DW 0 ; DS
  162. DW 0 ; Reserved
  163. DW 0 ; FS
  164. DW 0 ; Reserved
  165. DW 0 ; GS
  166. DW 0 ; Reserved
  167. DW 0 ; LDT Selector
  168. DW 0 ; Reserved
  169. DW 0 ; T
  170. DW 0 ; I/O Map Base
  171. TSS_DESC_SIZE equ $ - TssDescriptor
  172. ExceptionTssDescriptor:
  173. DW 0 ; PreviousTaskLink
  174. DW 0 ; Reserved
  175. DD 0 ; ESP0
  176. DW 0 ; SS0
  177. DW 0 ; Reserved
  178. DD 0 ; ESP1
  179. DW 0 ; SS1
  180. DW 0 ; Reserved
  181. DD 0 ; ESP2
  182. DW 0 ; SS2
  183. DW 0 ; Reserved
  184. DD 0 ; CR3
  185. DD PFHandlerEntry ; EIP
  186. DD 00000002 ; EFLAGS
  187. DD 0 ; EAX
  188. DD 0 ; ECX
  189. DD 0 ; EDX
  190. DD 0 ; EBX
  191. DD 0 ; ESP
  192. DD 0 ; EBP
  193. DD 0 ; ESI
  194. DD 0 ; EDI
  195. DW DATA_SEL ; ES
  196. DW 0 ; Reserved
  197. DW CODE_SEL ; CS
  198. DW 0 ; Reserved
  199. DW DATA_SEL ; SS
  200. DW 0 ; Reserved
  201. DW DATA_SEL ; DS
  202. DW 0 ; Reserved
  203. DW DATA_SEL ; FS
  204. DW 0 ; Reserved
  205. DW DATA_SEL ; GS
  206. DW 0 ; Reserved
  207. DW 0 ; LDT Selector
  208. DW 0 ; Reserved
  209. DW 0 ; T
  210. DW 0 ; I/O Map Base
  211. DD 0 ; SSP
  212. EXCEPTION_TSS_DESC_SIZE equ $ - ExceptionTssDescriptor
  213. ASM_PFX(gcPsd):
  214. DB 'PSDSIG '
  215. DW PSD_SIZE
  216. DW 2
  217. DW 1 << 2
  218. DW CODE_SEL
  219. DW DATA_SEL
  220. DW DATA_SEL
  221. DW DATA_SEL
  222. DW 0
  223. DQ 0
  224. DQ 0
  225. DQ 0
  226. DD 0
  227. DD NullSeg
  228. DD GDT_SIZE
  229. DD 0
  230. times 24 DB 0
  231. DD 0
  232. DD 0
  233. PSD_SIZE equ $ - ASM_PFX(gcPsd)
  234. ASM_PFX(gcSmiGdtr):
  235. DW GDT_SIZE - 1
  236. DD NullSeg
  237. ASM_PFX(gcSmiIdtr):
  238. DW 0
  239. DD 0
  240. ASM_PFX(gTaskGateDescriptor):
  241. DW 0 ; Reserved
  242. DW EXCEPTION_TSS_SEL ; TSS Segment selector
  243. DB 0 ; Reserved
  244. DB 0x85 ; Task Gate, present, DPL = 0
  245. DW 0 ; Reserved
  246. SECTION .text
  247. ;------------------------------------------------------------------------------
  248. ; PageFaultIdtHandlerSmmProfile is the entry point page fault only
  249. ;
  250. ;
  251. ; Stack:
  252. ; +---------------------+
  253. ; + EFlags +
  254. ; +---------------------+
  255. ; + CS +
  256. ; +---------------------+
  257. ; + EIP +
  258. ; +---------------------+
  259. ; + Error Code +
  260. ; +---------------------+
  261. ; + Vector Number +
  262. ; +---------------------+
  263. ; + EBP +
  264. ; +---------------------+ <-- EBP
  265. ;
  266. ;
  267. ;------------------------------------------------------------------------------
  268. global ASM_PFX(PageFaultIdtHandlerSmmProfile)
  269. ASM_PFX(PageFaultIdtHandlerSmmProfile):
  270. push 0xe ; Page Fault
  271. push ebp
  272. mov ebp, esp
  273. ;
  274. ; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
  275. ; is 16-byte aligned
  276. ;
  277. and esp, 0xfffffff0
  278. sub esp, 12
  279. ;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
  280. push eax
  281. push ecx
  282. push edx
  283. push ebx
  284. lea ecx, [ebp + 6 * 4]
  285. push ecx ; ESP
  286. push dword [ebp] ; EBP
  287. push esi
  288. push edi
  289. ;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
  290. mov eax, ss
  291. push eax
  292. movzx eax, word [ebp + 4 * 4]
  293. push eax
  294. mov eax, ds
  295. push eax
  296. mov eax, es
  297. push eax
  298. mov eax, fs
  299. push eax
  300. mov eax, gs
  301. push eax
  302. ;; UINT32 Eip;
  303. mov eax, [ebp + 3 * 4]
  304. push eax
  305. ;; UINT32 Gdtr[2], Idtr[2];
  306. sub esp, 8
  307. sidt [esp]
  308. mov eax, [esp + 2]
  309. xchg eax, [esp]
  310. and eax, 0xFFFF
  311. mov [esp+4], eax
  312. sub esp, 8
  313. sgdt [esp]
  314. mov eax, [esp + 2]
  315. xchg eax, [esp]
  316. and eax, 0xFFFF
  317. mov [esp+4], eax
  318. ;; UINT32 Ldtr, Tr;
  319. xor eax, eax
  320. str ax
  321. push eax
  322. sldt ax
  323. push eax
  324. ;; UINT32 EFlags;
  325. mov eax, [ebp + 5 * 4]
  326. push eax
  327. ;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
  328. mov eax, cr4
  329. or eax, 0x208
  330. mov cr4, eax
  331. push eax
  332. mov eax, cr3
  333. push eax
  334. mov eax, cr2
  335. push eax
  336. xor eax, eax
  337. push eax
  338. mov eax, cr0
  339. push eax
  340. ;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
  341. mov eax, dr7
  342. push eax
  343. mov eax, dr6
  344. push eax
  345. mov eax, dr3
  346. push eax
  347. mov eax, dr2
  348. push eax
  349. mov eax, dr1
  350. push eax
  351. mov eax, dr0
  352. push eax
  353. ;; FX_SAVE_STATE_IA32 FxSaveState;
  354. sub esp, 512
  355. mov edi, esp
  356. fxsave [edi]
  357. ; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
  358. cld
  359. ;; UINT32 ExceptionData;
  360. push dword [ebp + 2 * 4]
  361. ;; call into exception handler
  362. ;; Prepare parameter and call
  363. mov edx, esp
  364. push edx
  365. mov edx, dword [ebp + 1 * 4]
  366. push edx
  367. ;
  368. ; Call External Exception Handler
  369. ;
  370. mov eax, ASM_PFX(SmiPFHandler)
  371. call eax
  372. add esp, 8
  373. ;; UINT32 ExceptionData;
  374. add esp, 4
  375. ;; FX_SAVE_STATE_IA32 FxSaveState;
  376. mov esi, esp
  377. fxrstor [esi]
  378. add esp, 512
  379. ;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
  380. ;; Skip restoration of DRx registers to support debuggers
  381. ;; that set breakpoint in interrupt/exception context
  382. add esp, 4 * 6
  383. ;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
  384. pop eax
  385. mov cr0, eax
  386. add esp, 4 ; not for Cr1
  387. pop eax
  388. mov cr2, eax
  389. pop eax
  390. mov cr3, eax
  391. pop eax
  392. mov cr4, eax
  393. ;; UINT32 EFlags;
  394. pop dword [ebp + 5 * 4]
  395. ;; UINT32 Ldtr, Tr;
  396. ;; UINT32 Gdtr[2], Idtr[2];
  397. ;; Best not let anyone mess with these particular registers...
  398. add esp, 24
  399. ;; UINT32 Eip;
  400. pop dword [ebp + 3 * 4]
  401. ;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
  402. ;; NOTE - modified segment registers could hang the debugger... We
  403. ;; could attempt to insulate ourselves against this possibility,
  404. ;; but that poses risks as well.
  405. ;;
  406. pop gs
  407. pop fs
  408. pop es
  409. pop ds
  410. pop dword [ebp + 4 * 4]
  411. pop ss
  412. ;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
  413. pop edi
  414. pop esi
  415. add esp, 4 ; not for ebp
  416. add esp, 4 ; not for esp
  417. pop ebx
  418. pop edx
  419. pop ecx
  420. pop eax
  421. mov esp, ebp
  422. pop ebp
  423. ; Enable TF bit after page fault handler runs
  424. bts dword [esp + 16], 8 ; EFLAGS
  425. add esp, 8 ; skip INT# & ErrCode
  426. Return:
  427. iretd
  428. ;
  429. ; Page Fault Exception Handler entry when SMM Stack Guard is enabled
  430. ; Executiot starts here after a task switch
  431. ;
  432. PFHandlerEntry:
  433. ;
  434. ; Get this processor's TSS
  435. ;
  436. sub esp, 8
  437. sgdt [esp + 2]
  438. mov eax, [esp + 4] ; GDT base
  439. add esp, 8
  440. mov ecx, [eax + TSS_SEL + 2]
  441. shl ecx, 8
  442. mov cl, [eax + TSS_SEL + 7]
  443. ror ecx, 8 ; ecx = TSS base
  444. mov ebp, esp
  445. ;
  446. ; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
  447. ; is 16-byte aligned
  448. ;
  449. and esp, 0xfffffff0
  450. sub esp, 12
  451. ;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
  452. push dword [ecx + IA32_TSS._EAX]
  453. push dword [ecx + IA32_TSS._ECX]
  454. push dword [ecx + IA32_TSS._EDX]
  455. push dword [ecx + IA32_TSS._EBX]
  456. push dword [ecx + IA32_TSS._ESP]
  457. push dword [ecx + IA32_TSS._EBP]
  458. push dword [ecx + IA32_TSS._ESI]
  459. push dword [ecx + IA32_TSS._EDI]
  460. ;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
  461. movzx eax, word [ecx + IA32_TSS._SS]
  462. push eax
  463. movzx eax, word [ecx + IA32_TSS._CS]
  464. push eax
  465. movzx eax, word [ecx + IA32_TSS._DS]
  466. push eax
  467. movzx eax, word [ecx + IA32_TSS._ES]
  468. push eax
  469. movzx eax, word [ecx + IA32_TSS._FS]
  470. push eax
  471. movzx eax, word [ecx + IA32_TSS._GS]
  472. push eax
  473. ;; UINT32 Eip;
  474. push dword [ecx + IA32_TSS.EIP]
  475. ;; UINT32 Gdtr[2], Idtr[2];
  476. sub esp, 8
  477. sidt [esp]
  478. mov eax, [esp + 2]
  479. xchg eax, [esp]
  480. and eax, 0xFFFF
  481. mov [esp+4], eax
  482. sub esp, 8
  483. sgdt [esp]
  484. mov eax, [esp + 2]
  485. xchg eax, [esp]
  486. and eax, 0xFFFF
  487. mov [esp+4], eax
  488. ;; UINT32 Ldtr, Tr;
  489. mov eax, TSS_SEL
  490. push eax
  491. movzx eax, word [ecx + IA32_TSS.LDT]
  492. push eax
  493. ;; UINT32 EFlags;
  494. push dword [ecx + IA32_TSS.EFLAGS]
  495. ;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
  496. mov eax, cr4
  497. or eax, 0x208
  498. mov cr4, eax
  499. push eax
  500. mov eax, cr3
  501. push eax
  502. mov eax, cr2
  503. push eax
  504. xor eax, eax
  505. push eax
  506. mov eax, cr0
  507. push eax
  508. ;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
  509. mov eax, dr7
  510. push eax
  511. mov eax, dr6
  512. push eax
  513. mov eax, dr3
  514. push eax
  515. mov eax, dr2
  516. push eax
  517. mov eax, dr1
  518. push eax
  519. mov eax, dr0
  520. push eax
  521. ;; FX_SAVE_STATE_IA32 FxSaveState;
  522. ;; Clear TS bit in CR0 to avoid Device Not Available Exception (#NM)
  523. ;; when executing fxsave/fxrstor instruction
  524. clts
  525. sub esp, 512
  526. mov edi, esp
  527. fxsave [edi]
  528. ; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
  529. cld
  530. ;; UINT32 ExceptionData;
  531. push dword [ebp]
  532. ;; call into exception handler
  533. mov ebx, ecx
  534. mov eax, ASM_PFX(SmiPFHandler)
  535. ;; Prepare parameter and call
  536. mov edx, esp
  537. push edx
  538. mov edx, 14
  539. push edx
  540. ;
  541. ; Call External Exception Handler
  542. ;
  543. call eax
  544. add esp, 8
  545. mov ecx, ebx
  546. ;; UINT32 ExceptionData;
  547. add esp, 4
  548. ;; FX_SAVE_STATE_IA32 FxSaveState;
  549. mov esi, esp
  550. fxrstor [esi]
  551. add esp, 512
  552. ;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
  553. ;; Skip restoration of DRx registers to support debuggers
  554. ;; that set breakpoints in interrupt/exception context
  555. add esp, 4 * 6
  556. ;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
  557. pop eax
  558. mov cr0, eax
  559. add esp, 4 ; not for Cr1
  560. pop eax
  561. mov cr2, eax
  562. pop eax
  563. mov dword [ecx + IA32_TSS._CR3], eax
  564. pop eax
  565. mov cr4, eax
  566. ;; UINT32 EFlags;
  567. pop dword [ecx + IA32_TSS.EFLAGS]
  568. ;; UINT32 Ldtr, Tr;
  569. ;; UINT32 Gdtr[2], Idtr[2];
  570. ;; Best not let anyone mess with these particular registers...
  571. add esp, 24
  572. ;; UINT32 Eip;
  573. pop dword [ecx + IA32_TSS.EIP]
  574. ;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
  575. ;; NOTE - modified segment registers could hang the debugger... We
  576. ;; could attempt to insulate ourselves against this possibility,
  577. ;; but that poses risks as well.
  578. ;;
  579. pop eax
  580. o16 mov [ecx + IA32_TSS._GS], ax
  581. pop eax
  582. o16 mov [ecx + IA32_TSS._FS], ax
  583. pop eax
  584. o16 mov [ecx + IA32_TSS._ES], ax
  585. pop eax
  586. o16 mov [ecx + IA32_TSS._DS], ax
  587. pop eax
  588. o16 mov [ecx + IA32_TSS._CS], ax
  589. pop eax
  590. o16 mov [ecx + IA32_TSS._SS], ax
  591. ;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
  592. pop dword [ecx + IA32_TSS._EDI]
  593. pop dword [ecx + IA32_TSS._ESI]
  594. add esp, 4 ; not for ebp
  595. add esp, 4 ; not for esp
  596. pop dword [ecx + IA32_TSS._EBX]
  597. pop dword [ecx + IA32_TSS._EDX]
  598. pop dword [ecx + IA32_TSS._ECX]
  599. pop dword [ecx + IA32_TSS._EAX]
  600. mov esp, ebp
  601. ; Set single step DB# if SMM profile is enabled and page fault exception happens
  602. cmp byte [dword ASM_PFX(mSetupDebugTrap)], 0
  603. jz @Done2
  604. ; Create return context for iretd in stub function
  605. mov eax, dword [ecx + IA32_TSS._ESP] ; Get old stack pointer
  606. mov ebx, dword [ecx + IA32_TSS.EIP]
  607. mov [eax - 0xc], ebx ; create EIP in old stack
  608. movzx ebx, word [ecx + IA32_TSS._CS]
  609. mov [eax - 0x8], ebx ; create CS in old stack
  610. mov ebx, dword [ecx + IA32_TSS.EFLAGS]
  611. bts ebx, 8
  612. mov [eax - 0x4], ebx ; create eflags in old stack
  613. mov eax, dword [ecx + IA32_TSS._ESP] ; Get old stack pointer
  614. sub eax, 0xc ; minus 12 byte
  615. mov dword [ecx + IA32_TSS._ESP], eax ; Set new stack pointer
  616. ; Replace the EIP of interrupted task with stub function
  617. mov eax, ASM_PFX(PageFaultStubFunction)
  618. mov dword [ecx + IA32_TSS.EIP], eax
  619. ; Jump to the iretd so next page fault handler as a task will start again after iretd.
  620. @Done2:
  621. add esp, 4 ; skip ErrCode
  622. jmp Return
  623. global ASM_PFX(PageFaultStubFunction)
  624. ASM_PFX(PageFaultStubFunction):
  625. ;
  626. ; we need clean TS bit in CR0 to execute
  627. ; x87 FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 instructions.
  628. ;
  629. clts
  630. iretd