Source code of Windows XP (NT5)
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.

636 lines
15 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 ebx
  165. ;
  166. ; Check reg field of mod r/m byte to see if this is really an Lmsw
  167. ;
  168. inc [esi].RiEip
  169. call CheckEip
  170. test al,0fh
  171. jz ol30 ; gp fault
  172. mov edi,[esi].RiEip
  173. add edi,[esi].RiCsBase
  174. movzx edx,byte ptr [edi]
  175. and edx,MI_REGMASK
  176. cmp edx,MI_REGLMSW ; check for the additional opcode bits
  177. jne ol40 ; not lmsw, return error.
  178. ;
  179. ; Turn off the 32 bit operand prefix (lmsw always uses 16 bit operands)
  180. ;
  181. and [esi].RiPrefixFlags,NOT PREFIX_OPER32
  182. ;
  183. ; Get the linear address of the value to put into the MSW.
  184. ;
  185. mov eax,1 ; read operand
  186. call VdmDecodeOperand
  187. test al,0fh
  188. jz ol30 ; error reading operand
  189. mov edi,[esi].RiOperand
  190. mov eax,[edi]
  191. call KiVdmSetUserCR0
  192. mov eax,1 ; indicate success
  193. ol30: pop ebx
  194. pop edi
  195. mov esp,ebp
  196. pop ebp
  197. ret
  198. ol40: xor eax,eax
  199. jmp ol30
  200. VdmOpcodeLmsw endp
  201. page ,132
  202. subttl "Emulate CLTS"
  203. ;++
  204. ;
  205. ; Routine Description:
  206. ;
  207. ; This routine emulates CLTS by ignoring it.
  208. ;
  209. ; Arguments:
  210. ;
  211. ; esi = pointer to reg info
  212. ;
  213. ; Returns:
  214. ;
  215. ; eax = 1
  216. ;
  217. public VdmOpcodeClts
  218. VdmOpcodeClts proc
  219. inc [esi].RiEip ; skip second byte
  220. mov eax,1
  221. ret
  222. VdmOpcodeClts endp
  223. page ,132
  224. subttl "Emulate GetCRx"
  225. ;++
  226. ;
  227. ; Routine Description:
  228. ;
  229. ; This routine emulates the GetCRx opcodes. For now, it returns the
  230. ; contents of CR0 unmodified, and 0 for all other CR?
  231. ;
  232. ; Arguments:
  233. ;
  234. ; esi = pointer to reg info
  235. ;
  236. ; Returns:
  237. ;
  238. ; eax = true if the opcode was emulated
  239. ; reginfo updated.
  240. ; eax = false if the opcode was not emulated.
  241. ;
  242. public VdmOpcodeGetCrx
  243. VdmOpcodeGetCrx proc
  244. push ebp
  245. mov ebp,esp
  246. push edi
  247. inc [esi].RiEip
  248. call CheckEip
  249. test al,0fh
  250. jz ogc40 ; Gp fault, report error
  251. mov edi,[esi].RiEip
  252. add edi,[esi].RiCsBase
  253. inc [esi].RiEip
  254. movzx edx,byte ptr [edi]
  255. ;
  256. ; Verify the Mod field for mov special
  257. ;
  258. and edx,MI_MODMASK
  259. cmp edx,MI_MODMOVSPEC ; require for mov to/from special
  260. jne short ogc50 ; return error
  261. movzx edx,byte ptr [edi]
  262. test edx,MI_REGMASK ; mov from CR0?
  263. mov eax,0 ; assume 0
  264. jne short ogc30
  265. mov edi,PCR[PcInitialStack] ; (edi) = fp save area
  266. mov edi,[edi].FpCr0NpxState ; get users bits
  267. and edi, CR0_MP+CR0_EM+CR0_PE ; mask
  268. movzx edi,_VdmUserCr0MapOut[edi] ; map to real settings
  269. mov eax, cr0 ; read CR0
  270. and eax, not (CR0_MP+CR0_EM+CR0_TS) ; clear npx bits
  271. or eax, edi ; set npx bits
  272. ;
  273. ; Pull the destination register from the R/M field
  274. ;
  275. ogc30: and edx,MI_RMMASK
  276. mov edi,[esi].RiTrapFrame
  277. mov edx,RegTab[edx * 4] ; get register offset
  278. mov [edx + edi],eax ; store CR? contents into register
  279. mov eax,1
  280. ogc40: pop edi
  281. mov esp,ebp
  282. pop ebp
  283. ret
  284. ogc50: xor eax,eax
  285. jmp ogc40
  286. VdmOpcodeGetCrx endp
  287. page ,132
  288. subttl "Emulate SetCRx"
  289. ;++
  290. ;
  291. ; Routine Description:
  292. ;
  293. ; This routine emulates the SetCRx opcodes. For now, it only emulates
  294. ; set CR0, and only for the same conditions as LMSW. It causes a fault
  295. ; for all other CR?
  296. ;
  297. ; Arguments:
  298. ;
  299. ; esi = pointer to reg info
  300. ;
  301. ; Returns:
  302. ;
  303. ; eax = true if the opcode was emulated
  304. ; reginfo updated.
  305. ; eax = false if the opcode was not emulated.
  306. ;
  307. public VdmOpcodeSetCrx
  308. VdmOpcodeSetCrx proc
  309. push ebp
  310. mov ebp,esp
  311. push edi
  312. push ebx
  313. inc [esi].RiEip
  314. call CheckEip
  315. test al,0fh
  316. jz osc40 ; Gp fault, report error
  317. mov edi,[esi].RiEip
  318. add edi,[esi].RiCsBase
  319. inc [esi].RiEip
  320. movzx edx,byte ptr [edi]
  321. ;
  322. ; Verify the Mod field for mov special
  323. ;
  324. and edx,MI_MODMASK
  325. cmp edx,MI_MODMOVSPEC ; require for mov to/from special
  326. jne osc50 ; return error
  327. movzx edx,byte ptr [edi]
  328. test edx,MI_REGMASK ; mov to CR0?
  329. jne osc50 ; no, return error
  330. ;
  331. ; Get the source register from the R/M field
  332. ;
  333. and edx,MI_RMMASK
  334. mov edi,[esi].RiTrapFrame
  335. mov edx,RegTab[edx * 4] ; get register offset
  336. mov eax,[edx + edi] ; get CR? contents from register
  337. call KiVdmSetUserCR0
  338. mov eax,1
  339. osc40: pop edi
  340. mov esp,ebp
  341. pop ebp
  342. ret
  343. osc50: xor eax,eax
  344. jmp osc40
  345. VdmOpcodeSetCrx endp
  346. page ,132
  347. subttl "Emulate GetDRx"
  348. ;++
  349. ;
  350. ; Routine Description:
  351. ;
  352. ; This routine emulates the GetDRx opcodes. For DR0-DR3, it returns the
  353. ; values from the user mode trap frame. For DR4-DR5, it returns 0. For
  354. ; DR6 and DR7, it returns the bits from the user mode trap frame that are
  355. ; settable from user mode.
  356. ;
  357. ; Arguments:
  358. ;
  359. ; esi = pointer to reg info
  360. ;
  361. ; Returns:
  362. ;
  363. ; eax = true if the opcode was emulated
  364. ; reginfo updated.
  365. ; eax = false if the opcode was not emulated.
  366. ;
  367. public VdmOpcodeGetDrx
  368. VdmOpcodeGetDrx proc
  369. ModRm equ [ebp - 4]
  370. push ebp
  371. mov ebp,esp
  372. sub esp,4
  373. push edi
  374. push ecx
  375. inc [esi].RiEip
  376. call CheckEip
  377. test al,0fh
  378. jz ogd50 ; Gp fault, report error
  379. mov edi,[esi].RiEip
  380. add edi,[esi].RiCsBase
  381. inc [esi].RiEip
  382. movzx edx,byte ptr [edi]
  383. mov ModRm,edx
  384. ;
  385. ; Verify the Mod field
  386. ;
  387. and edx,MI_MODMASK
  388. cmp edx,MI_MODMOVSPEC ; require for mov special
  389. jne ogd60 ; return error
  390. mov edi,[esi].RiTrapFrame
  391. ;
  392. ; Get the Dr number
  393. ;
  394. mov edx,ModRm
  395. and edx,MI_REGMASK
  396. shr edx,MI_REGSHIFT
  397. ;
  398. ; If it is DR4 or DR5, set the destination register to zero
  399. ;
  400. cmp edx,4
  401. jb ogd20
  402. cmp edx,5
  403. ja ogd20
  404. mov eax,0 ; set the destination to zero
  405. jmp ogd40
  406. ;
  407. ; Otherwise, use the actual user mode register contents
  408. ;
  409. ogd20: mov ecx,DrTab[edx * 4]
  410. mov eax,[edi + ecx] ; get register value
  411. cmp edx,6 ; do we need to sanitize?
  412. jb ogd40 ; no.
  413. cmp edx,7
  414. je ogd30
  415. and eax,DR6_LEGAL
  416. jmp ogd40
  417. ogd30: and eax,DR7_LEGAL
  418. ;
  419. ; Get destination register from opcode, and store Dr contents
  420. ;
  421. ogd40: mov edx,ModRm
  422. and edx,MI_RMMASK
  423. mov ecx,RegTab[edx * 4]
  424. mov [ecx + edi],eax ; set user mode register
  425. mov eax,1 ; indicate success
  426. ogd50: pop ecx
  427. pop edi
  428. mov esp,ebp
  429. pop ebp
  430. ret
  431. ogd60: xor eax,eax ; indicate error
  432. jmp ogd50
  433. VdmOpcodeGetDrx endp
  434. page ,132
  435. subttl "Emulate SetDRx"
  436. ;++
  437. ;
  438. ; Routine Description:
  439. ;
  440. ; This routine emulates the SetDRx opcodes. For DR0-DR3, it will set
  441. ; the user mode register to any linear address up to 16MB. For DR4-DR5,
  442. ; it will ignore the instruction. For DR6 and DR7, it will set the bits
  443. ; that are user mode setable. For DR7, it also translates the global
  444. ; bits to local bits.
  445. ;
  446. ; Arguments:
  447. ;
  448. ; esi = pointer to reg info
  449. ;
  450. ; Returns:
  451. ;
  452. ; eax = true if the opcode was emulated
  453. ; reginfo updated.
  454. ; eax = false if the opcode was not emulated.
  455. ;
  456. public VdmOpcodeSetDrx
  457. VdmOpcodeSetDrx proc
  458. ModRm equ [ebp - 4]
  459. push ebp
  460. mov ebp,esp
  461. sub esp,4
  462. push edi
  463. push ecx
  464. inc [esi].RiEip
  465. call CheckEip
  466. test al,0fh
  467. jz osd80 ; Gp fault, report error
  468. mov edi,[esi].RiEip
  469. add edi,[esi].RiCsBase
  470. inc [esi].RiEip
  471. movzx edx,byte ptr [edi]
  472. mov ModRm,edx
  473. ;
  474. ; Verify the Mod field
  475. ;
  476. and edx,MI_MODMASK
  477. cmp edx,MI_MODMOVSPEC ; require for mov special
  478. jne osd90 ; return error
  479. ;
  480. ; Get value to put into debug register
  481. ;
  482. mov edi,[esi].RiTrapFrame
  483. mov edx,ModRm
  484. and edx,MI_RMMASK
  485. mov edx,RegTab[edx * 4]
  486. mov eax,[edi + edx]
  487. ;
  488. ; Determine which debug register it goes into, and sanitize appropriately
  489. ;
  490. mov edx,ModRm
  491. and edx,MI_REGMASK
  492. shr edx,MI_REGSHIFT
  493. cmp edx,4
  494. jnb osd20
  495. ;
  496. ; DR0-DR4, make linear address < 16MB
  497. ;
  498. and eax,MAX_VDM_ADDR
  499. jmp osd60
  500. osd20: cmp edx,6
  501. jnb osd30
  502. ;
  503. ; DR4-DR5, just return
  504. ;
  505. jmp osd70 ; return success
  506. osd30: cmp edx,6
  507. jne osd40
  508. ;
  509. ; DR6, mask for legal bits
  510. ;
  511. and eax,DR6_LEGAL
  512. jmp osd60
  513. ;
  514. ; DR7, mask for legal bits, and translate g to l, and activate debug
  515. ;
  516. osd40: mov ecx,eax
  517. and ecx,DR7_GLOBAL
  518. shr ecx,1 ; translate the G to L by shifting
  519. or eax,ecx ; put in any new bits
  520. and eax,DR7_LEGAL ; sanitize the value
  521. ;
  522. ; Put the value into the user mode register
  523. ;
  524. osd60: mov ecx,DrTab[edx * 4]
  525. mov [edi + ecx],eax
  526. cmp edx,7
  527. jne osd70
  528. mov ecx,eax
  529. stdCall ___KeGetCurrentThread
  530. test ecx,DR7_ACTIVE
  531. jz osd65
  532. mov byte ptr [eax].ThDebugActive,1 ; set debugging active for this thread
  533. jmp osd70
  534. osd65: mov byte ptr [eax].ThDebugActive,0
  535. osd70: mov eax,1
  536. osd80: pop ecx
  537. pop edi
  538. mov esp,ebp
  539. pop ebp
  540. ret
  541. osd90: xor eax,eax
  542. jmp osd80
  543. VdmOpcodeSetDrx endp
  544. _PAGE ends
  545. end