Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

643 lines
16 KiB

  1. title "Opcode 0f Instruction Emulation"
  2. ;++
  3. ;
  4. ;Copyright (c) 1991 Microsoft Corporation
  5. ;
  6. ;Module Name:
  7. ;
  8. ; vdmop0f.asm
  9. ;
  10. ;Abstract:
  11. ;
  12. ; This module contains the support for the 0f opcodes that are emulated
  13. ; (such as LMSW, mov to/from CR0, mov to/from DR?).
  14. ;
  15. ;
  16. ;Author:
  17. ;
  18. ; Dave Hastings (daveh) 23-Feb-1992
  19. ;
  20. ;Notes:
  21. ;
  22. ; This file needs to be modified for Kenr's NPX changes, i.e. what to
  23. ; do with CR0 values
  24. ;
  25. ;
  26. ;Revision History:
  27. ;
  28. ;--
  29. .386p
  30. .xlist
  31. include ks386.inc
  32. include callconv.inc ; calling convention macros
  33. include mi386.inc
  34. include vdm.inc
  35. page ,132
  36. ; Force assume into place
  37. _PAGE SEGMENT DWORD PUBLIC 'CODE'
  38. ASSUME DS:NOTHING, ES:NOTHING, SS:NOTHING, FS:NOTHING, GS:NOTHING
  39. _PAGE ENDS
  40. _PAGE SEGMENT DWORD USE32 PUBLIC 'CODE'
  41. ASSUME DS:NOTHING, ES:NOTHING, SS:NOTHING, FS:NOTHING, GS:NOTHING
  42. extrn OpcodeInvalid:proc
  43. VdmOpcodeInvalid equ OpcodeInvalid
  44. extrn CheckEip:proc
  45. extrn VdmDecodeOperand:proc
  46. extrn RegTab:dword
  47. EXTRNP ___KeGetCurrentThread,0
  48. extrn KiVdmSetUserCR0:proc
  49. extrn _VdmUserCr0MapOut:byte
  50. ;
  51. ; This table is used to dispatch the special register moves
  52. ;
  53. ; WARNING Trx not implemented.
  54. SpecialRegTab dd offset VdmOpcodeGetCrx
  55. dd offset VdmOpcodeGetDrx
  56. dd offset VdmOpcodeSetCrx
  57. dd offset VdmOpcodeSetDrx
  58. ; dd offset VdmOpcodeGetTrx
  59. dd offset VdmOpcodeInvalid
  60. dd offset VdmOpcodeInvalid
  61. ; dd offset VdmOpcodeSetTrx
  62. dd offset VdmOpcodeInvalid
  63. ;
  64. ; This table is used to locate the debug register contents in the trap frame
  65. ; The values for DR4, DR5 should never be used, since these registers are
  66. ; reserved by intel
  67. ;
  68. DrTab dd TsDr0
  69. dd TsDr1
  70. dd TsDr2
  71. dd TsDr3
  72. dd 0BADF00Dh ; hopefully this will fault if used (dr4)
  73. dd 0BADF00Dh ; hopefully this will fault if used (dr5)
  74. dd TsDr6
  75. dd TsDr7
  76. _PAGE ENDS
  77. _PAGE SEGMENT DWORD USE32 PUBLIC 'CODE'
  78. ASSUME DS:FLAT, ES:NOTHING, SS:FLAT, FS:NOTHING, GS:NOTHING
  79. page ,132
  80. subttl "Emulate 0f opcodes"
  81. ;++
  82. ;
  83. ; Routine Description:
  84. ;
  85. ; This routine dispatches for the opcode 0f emulation. Currently,
  86. ; only LMSW, MOV to/from CR0, and MOV to /from DRx are emulated.
  87. ; The others cause access violations in user mode.
  88. ;
  89. ; Interrupts are disabled upon entry, and enabled upon exit
  90. ;
  91. ; Arguments:
  92. ;
  93. ; esi = address of reg info
  94. ;
  95. ; Returns:
  96. ;
  97. ; EAX = true if the opcode was emulated.
  98. ; reginfo updated
  99. ; EAX = false if the opcode was not emulated
  100. ;
  101. ;
  102. public VdmOpcode0f
  103. VdmOpcode0f proc
  104. push ebp
  105. mov ebp,esp
  106. push edi
  107. ;
  108. ; Construct address of next opcode byte, and check for gp fault
  109. ;
  110. inc [esi].RiEip
  111. call CheckEip
  112. test al,0fh
  113. jz of40 ; Gp fault, report error
  114. mov edi,[esi].RiCsBase
  115. add edi,[esi].RiEip
  116. movzx edx,byte ptr [edi]
  117. cmp edx,MI_LMSW_OPCODE
  118. jne of10
  119. call VdmOpcodeLmsw
  120. jmp of30 ; return
  121. of10: cmp edx,MI_CLTS_OPCODE
  122. jne of20
  123. call VdmOpcodeClts
  124. jmp of30 ; return
  125. of20: cmp edx,MI_GET_CRx_OPCODE
  126. jb of40 ; return error
  127. cmp edx,MI_SET_TRx_OPCODE
  128. ja of40 ; return error
  129. sub edx,MI_GET_CRx_OPCODE
  130. call SpecialRegTab[edx * 4]
  131. of30:
  132. pop edi
  133. mov esp,ebp
  134. pop ebp
  135. ret
  136. of40: xor eax,eax
  137. jmp of30
  138. VdmOpcode0f endp
  139. page ,132
  140. subttl "Emulate LMSW"
  141. ;++
  142. ;
  143. ; Routine Desription:
  144. ;
  145. ; This routine emulates the LMSW instruction. It allows the dos
  146. ; application to set or clear EM and MP. It forces MP to be set
  147. ; when EM is clear. It ignores to change any of the other bits.
  148. ;
  149. ; Arguments:
  150. ;
  151. ; esi = pointer to reg info
  152. ;
  153. ; Returns:
  154. ;
  155. ; EAX = true if the opcode was emulated.
  156. ; reginfo updated
  157. ; EAX = false if the opcode was not emulated.
  158. ;
  159. public VdmOpcodeLmsw
  160. VdmOpcodeLmsw proc
  161. push ebp
  162. mov ebp,esp
  163. push edi
  164. push esi
  165. push ebx
  166. ;
  167. ; Check reg field of mod r/m byte to see if this is really an Lmsw
  168. ;
  169. inc [esi].RiEip
  170. call CheckEip
  171. test al,0fh
  172. jz ol30 ; gp fault
  173. mov edi,[esi].RiEip
  174. add edi,[esi].RiCsBase
  175. movzx edx,byte ptr [edi]
  176. and edx,MI_REGMASK
  177. cmp edx,MI_REGLMSW ; check for the additional opcode bits
  178. jne ol40 ; not lmsw, return error.
  179. ;
  180. ; Turn off the 32 bit operand prefix (lmsw always uses 16 bit operands)
  181. ;
  182. and [esi].RiPrefixFlags,NOT PREFIX_OPER32
  183. ;
  184. ; Get the linear address of the value to put into the MSW.
  185. ;
  186. mov eax,1 ; read operand
  187. call VdmDecodeOperand
  188. test al,0fh
  189. jz ol30 ; error reading operand
  190. mov edi,[esi].RiOperand
  191. mov eax,[edi]
  192. call KiVdmSetUserCR0
  193. mov eax,1 ; indicate success
  194. ol30: pop ebx
  195. pop esi
  196. pop edi
  197. mov esp,ebp
  198. pop ebp
  199. ret
  200. ol40: xor eax,eax
  201. jmp ol30
  202. VdmOpcodeLmsw endp
  203. page ,132
  204. subttl "Emulate CLTS"
  205. ;++
  206. ;
  207. ; Routine Description:
  208. ;
  209. ; This routine emulates CLTS by ignoring it.
  210. ;
  211. ; Arguments:
  212. ;
  213. ; esi = pointer to reg info
  214. ;
  215. ; Returns:
  216. ;
  217. ; eax = 1
  218. ;
  219. public VdmOpcodeClts
  220. VdmOpcodeClts proc
  221. inc [esi].RiEip ; skip second byte
  222. mov eax,1
  223. ret
  224. VdmOpcodeClts endp
  225. page ,132
  226. subttl "Emulate GetCRx"
  227. ;++
  228. ;
  229. ; Routine Description:
  230. ;
  231. ; This routine emulates the GetCRx opcodes. For now, it returns the
  232. ; contents of CR0 unmodified, and 0 for all other CR?
  233. ;
  234. ; Arguments:
  235. ;
  236. ; esi = pointer to reg info
  237. ;
  238. ; Returns:
  239. ;
  240. ; eax = true if the opcode was emulated
  241. ; reginfo updated.
  242. ; eax = false if the opcode was not emulated.
  243. ;
  244. public VdmOpcodeGetCrx
  245. VdmOpcodeGetCrx proc
  246. push ebp
  247. mov ebp,esp
  248. push edi
  249. inc [esi].RiEip
  250. call CheckEip
  251. test al,0fh
  252. jz ogc40 ; Gp fault, report error
  253. mov edi,[esi].RiEip
  254. add edi,[esi].RiCsBase
  255. inc [esi].RiEip
  256. movzx edx,byte ptr [edi]
  257. ;
  258. ; Verify the Mod field for mov special
  259. ;
  260. and edx,MI_MODMASK
  261. cmp edx,MI_MODMOVSPEC ; require for mov to/from special
  262. jne short ogc50 ; return error
  263. movzx edx,byte ptr [edi]
  264. test edx,MI_REGMASK ; mov from CR0?
  265. mov eax,0 ; assume 0
  266. jne short ogc30
  267. mov edi, PCR[PcPrcbData+PbCurrentThread]
  268. mov edi,[edi].ThInitialStack ; (edi) = fp save area
  269. sub edi, NPX_FRAME_LENGTH
  270. mov edi,[edi].FpCr0NpxState ; get users bits
  271. and edi, CR0_MP+CR0_EM+CR0_PE ; mask
  272. movzx edi,_VdmUserCr0MapOut[edi] ; map to real settings
  273. mov eax, cr0 ; read CR0
  274. and eax, not (CR0_MP+CR0_EM+CR0_TS) ; clear npx bits
  275. or eax, edi ; set npx bits
  276. ;
  277. ; Pull the destination register from the R/M field
  278. ;
  279. ogc30: and edx,MI_RMMASK
  280. mov edi,[esi].RiTrapFrame
  281. mov edx,RegTab[edx * 4] ; get register offset
  282. mov [edx + edi],eax ; store CR? contents into register
  283. mov eax,1
  284. ogc40: pop edi
  285. mov esp,ebp
  286. pop ebp
  287. ret
  288. ogc50: xor eax,eax
  289. jmp ogc40
  290. VdmOpcodeGetCrx endp
  291. page ,132
  292. subttl "Emulate SetCRx"
  293. ;++
  294. ;
  295. ; Routine Description:
  296. ;
  297. ; This routine emulates the SetCRx opcodes. For now, it only emulates
  298. ; set CR0, and only for the same conditions as LMSW. It causes a fault
  299. ; for all other CR?
  300. ;
  301. ; Arguments:
  302. ;
  303. ; esi = pointer to reg info
  304. ;
  305. ; Returns:
  306. ;
  307. ; eax = true if the opcode was emulated
  308. ; reginfo updated.
  309. ; eax = false if the opcode was not emulated.
  310. ;
  311. public VdmOpcodeSetCrx
  312. VdmOpcodeSetCrx proc
  313. push ebp
  314. mov ebp,esp
  315. push edi
  316. push esi
  317. push ebx
  318. inc [esi].RiEip
  319. call CheckEip
  320. test al,0fh
  321. jz osc40 ; Gp fault, report error
  322. mov edi,[esi].RiEip
  323. add edi,[esi].RiCsBase
  324. inc [esi].RiEip
  325. movzx edx,byte ptr [edi]
  326. ;
  327. ; Verify the Mod field for mov special
  328. ;
  329. and edx,MI_MODMASK
  330. cmp edx,MI_MODMOVSPEC ; require for mov to/from special
  331. jne osc50 ; return error
  332. movzx edx,byte ptr [edi]
  333. test edx,MI_REGMASK ; mov to CR0?
  334. jne osc50 ; no, return error
  335. ;
  336. ; Get the source register from the R/M field
  337. ;
  338. and edx,MI_RMMASK
  339. mov edi,[esi].RiTrapFrame
  340. mov edx,RegTab[edx * 4] ; get register offset
  341. mov eax,[edx + edi] ; get CR? contents from register
  342. call KiVdmSetUserCR0
  343. mov eax,1
  344. osc40: pop ebx
  345. pop esi
  346. pop edi
  347. mov esp,ebp
  348. pop ebp
  349. ret
  350. osc50: xor eax,eax
  351. jmp osc40
  352. VdmOpcodeSetCrx endp
  353. page ,132
  354. subttl "Emulate GetDRx"
  355. ;++
  356. ;
  357. ; Routine Description:
  358. ;
  359. ; This routine emulates the GetDRx opcodes. For DR0-DR3, it returns the
  360. ; values from the user mode trap frame. For DR4-DR5, it returns 0. For
  361. ; DR6 and DR7, it returns the bits from the user mode trap frame that are
  362. ; settable from user mode.
  363. ;
  364. ; Arguments:
  365. ;
  366. ; esi = pointer to reg info
  367. ;
  368. ; Returns:
  369. ;
  370. ; eax = true if the opcode was emulated
  371. ; reginfo updated.
  372. ; eax = false if the opcode was not emulated.
  373. ;
  374. public VdmOpcodeGetDrx
  375. VdmOpcodeGetDrx proc
  376. ModRm equ [ebp - 4]
  377. push ebp
  378. mov ebp,esp
  379. sub esp,4
  380. push edi
  381. push ecx
  382. inc [esi].RiEip
  383. call CheckEip
  384. test al,0fh
  385. jz ogd50 ; Gp fault, report error
  386. mov edi,[esi].RiEip
  387. add edi,[esi].RiCsBase
  388. inc [esi].RiEip
  389. movzx edx,byte ptr [edi]
  390. mov ModRm,edx
  391. ;
  392. ; Verify the Mod field
  393. ;
  394. and edx,MI_MODMASK
  395. cmp edx,MI_MODMOVSPEC ; require for mov special
  396. jne ogd60 ; return error
  397. mov edi,[esi].RiTrapFrame
  398. ;
  399. ; Get the Dr number
  400. ;
  401. mov edx,ModRm
  402. and edx,MI_REGMASK
  403. shr edx,MI_REGSHIFT
  404. ;
  405. ; If it is DR4 or DR5, set the destination register to zero
  406. ;
  407. cmp edx,4
  408. jb ogd20
  409. cmp edx,5
  410. ja ogd20
  411. mov eax,0 ; set the destination to zero
  412. jmp ogd40
  413. ;
  414. ; Otherwise, use the actual user mode register contents
  415. ;
  416. ogd20: mov ecx,DrTab[edx * 4]
  417. mov eax,[edi + ecx] ; get register value
  418. cmp edx,6 ; do we need to sanitize?
  419. jb ogd40 ; no.
  420. cmp edx,7
  421. je ogd30
  422. and eax,DR6_LEGAL
  423. jmp ogd40
  424. ogd30: and eax,DR7_LEGAL
  425. ;
  426. ; Get destination register from opcode, and store Dr contents
  427. ;
  428. ogd40: mov edx,ModRm
  429. and edx,MI_RMMASK
  430. mov ecx,RegTab[edx * 4]
  431. mov [ecx + edi],eax ; set user mode register
  432. mov eax,1 ; indicate success
  433. ogd50: pop ecx
  434. pop edi
  435. mov esp,ebp
  436. pop ebp
  437. ret
  438. ogd60: xor eax,eax ; indicate error
  439. jmp ogd50
  440. VdmOpcodeGetDrx endp
  441. page ,132
  442. subttl "Emulate SetDRx"
  443. ;++
  444. ;
  445. ; Routine Description:
  446. ;
  447. ; This routine emulates the SetDRx opcodes. For DR0-DR3, it will set
  448. ; the user mode register to any linear address up to 16MB. For DR4-DR5,
  449. ; it will ignore the instruction. For DR6 and DR7, it will set the bits
  450. ; that are user mode setable. For DR7, it also translates the global
  451. ; bits to local bits.
  452. ;
  453. ; Arguments:
  454. ;
  455. ; esi = pointer to reg info
  456. ;
  457. ; Returns:
  458. ;
  459. ; eax = true if the opcode was emulated
  460. ; reginfo updated.
  461. ; eax = false if the opcode was not emulated.
  462. ;
  463. public VdmOpcodeSetDrx
  464. VdmOpcodeSetDrx proc
  465. ModRm equ [ebp - 4]
  466. push ebp
  467. mov ebp,esp
  468. sub esp,4
  469. push edi
  470. push ecx
  471. inc [esi].RiEip
  472. call CheckEip
  473. test al,0fh
  474. jz osd80 ; Gp fault, report error
  475. mov edi,[esi].RiEip
  476. add edi,[esi].RiCsBase
  477. inc [esi].RiEip
  478. movzx edx,byte ptr [edi]
  479. mov ModRm,edx
  480. ;
  481. ; Verify the Mod field
  482. ;
  483. and edx,MI_MODMASK
  484. cmp edx,MI_MODMOVSPEC ; require for mov special
  485. jne osd90 ; return error
  486. ;
  487. ; Get value to put into debug register
  488. ;
  489. mov edi,[esi].RiTrapFrame
  490. mov edx,ModRm
  491. and edx,MI_RMMASK
  492. mov edx,RegTab[edx * 4]
  493. mov eax,[edi + edx]
  494. ;
  495. ; Determine which debug register it goes into, and sanitize appropriately
  496. ;
  497. mov edx,ModRm
  498. and edx,MI_REGMASK
  499. shr edx,MI_REGSHIFT
  500. cmp edx,4
  501. jnb osd20
  502. ;
  503. ; DR0-DR4, make linear address < 16MB
  504. ;
  505. and eax,MAX_VDM_ADDR
  506. jmp osd60
  507. osd20: cmp edx,6
  508. jnb osd30
  509. ;
  510. ; DR4-DR5, just return
  511. ;
  512. jmp osd70 ; return success
  513. osd30: cmp edx,6
  514. jne osd40
  515. ;
  516. ; DR6, mask for legal bits
  517. ;
  518. and eax,DR6_LEGAL
  519. jmp osd60
  520. ;
  521. ; DR7, mask for legal bits, and translate g to l, and activate debug
  522. ;
  523. osd40: mov ecx,eax
  524. and ecx,DR7_GLOBAL
  525. shr ecx,1 ; translate the G to L by shifting
  526. or eax,ecx ; put in any new bits
  527. and eax,DR7_LEGAL ; sanitize the value
  528. ;
  529. ; Put the value into the user mode register
  530. ;
  531. osd60: mov ecx,DrTab[edx * 4]
  532. mov [edi + ecx],eax
  533. cmp edx,7
  534. jne osd70
  535. mov ecx,eax
  536. stdCall ___KeGetCurrentThread
  537. test ecx,DR7_ACTIVE
  538. jz osd65
  539. mov byte ptr [eax].ThDebugActive,1 ; set debugging active for this thread
  540. jmp osd70
  541. osd65: mov byte ptr [eax].ThDebugActive,0
  542. osd70: mov eax,1
  543. osd80: pop ecx
  544. pop edi
  545. mov esp,ebp
  546. pop ebp
  547. ret
  548. osd90: xor eax,eax
  549. jmp osd80
  550. VdmOpcodeSetDrx endp
  551. _PAGE ends
  552. end