VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMAll/EMAll.cpp@ 19602

Last change on this file since 19602 was 19141, checked in by vboxsync, 16 years ago

Action flags breakup.
Fixed PGM saved state loading of 2.2.2 images.
Reduced hacks in PATM state loading (fixups).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 112.9 KB
Line 
1/* $Id: EMAll.cpp 19141 2009-04-23 13:52:18Z vboxsync $ */
2/** @file
3 * EM - Execution Monitor(/Manager) - All contexts
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22/*******************************************************************************
23* Header Files *
24*******************************************************************************/
25#define LOG_GROUP LOG_GROUP_EM
26#include <VBox/em.h>
27#include <VBox/mm.h>
28#include <VBox/selm.h>
29#include <VBox/patm.h>
30#include <VBox/csam.h>
31#include <VBox/pgm.h>
32#include <VBox/iom.h>
33#include <VBox/stam.h>
34#include "EMInternal.h"
35#include <VBox/vm.h>
36#include <VBox/vmm.h>
37#include <VBox/hwaccm.h>
38#include <VBox/tm.h>
39#include <VBox/pdmapi.h>
40
41#include <VBox/param.h>
42#include <VBox/err.h>
43#include <VBox/dis.h>
44#include <VBox/disopcode.h>
45#include <VBox/log.h>
46#include <iprt/assert.h>
47#include <iprt/asm.h>
48#include <iprt/string.h>
49
50
51/*******************************************************************************
52* Defined Constants And Macros *
53*******************************************************************************/
54/** @def EM_ASSERT_FAULT_RETURN
55 * Safety check.
56 *
57 * Could in theory misfire on a cross page boundary access...
58 *
59 * Currently disabled because the CSAM (+ PATM) patch monitoring occasionally
60 * turns up an alias page instead of the original faulting one and annoying the
61 * heck out of anyone running a debug build. See @bugref{2609} and @bugref{1931}.
62 */
63#if 0
64# define EM_ASSERT_FAULT_RETURN(expr, rc) AssertReturn(expr, rc)
65#else
66# define EM_ASSERT_FAULT_RETURN(expr, rc) do { } while (0)
67#endif
68
69/* Used to pass information during instruction disassembly. */
70typedef struct
71{
72 PVM pVM;
73 PVMCPU pVCpu;
74} EMDISSTATE, *PEMDISSTATE;
75
76/*******************************************************************************
77* Internal Functions *
78*******************************************************************************/
79DECLINLINE(int) emInterpretInstructionCPU(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize);
80
81
82
83/**
84 * Get the current execution manager status.
85 *
86 * @returns Current status.
87 */
88VMMDECL(EMSTATE) EMGetState(PVMCPU pVCpu)
89{
90 return pVCpu->em.s.enmState;
91}
92
93#ifndef IN_RC
94
95/**
96 * Read callback for disassembly function; supports reading bytes that cross a page boundary
97 *
98 * @returns VBox status code.
99 * @param pSrc GC source pointer
100 * @param pDest HC destination pointer
101 * @param cb Number of bytes to read
102 * @param dwUserdata Callback specific user data (pDISState)
103 *
104 */
105DECLCALLBACK(int) EMReadBytes(RTUINTPTR pSrc, uint8_t *pDest, unsigned cb, void *pvUserdata)
106{
107 DISCPUSTATE *pDISState = (DISCPUSTATE *)pvUserdata;
108 PEMDISSTATE pState = (PEMDISSTATE)pDISState->apvUserData[0];
109 PVM pVM = pState->pVM;
110 PVMCPU pVCpu = pState->pVCpu;
111
112# ifdef IN_RING0
113 int rc = PGMPhysSimpleReadGCPtr(pVCpu, pDest, pSrc, cb);
114 AssertMsgRC(rc, ("PGMPhysSimpleReadGCPtr failed for pSrc=%RGv cb=%x\n", pSrc, cb));
115# else /* IN_RING3 */
116 if (!PATMIsPatchGCAddr(pVM, pSrc))
117 {
118 int rc = PGMPhysSimpleReadGCPtr(pVCpu, pDest, pSrc, cb);
119 AssertRC(rc);
120 }
121 else
122 {
123 for (uint32_t i = 0; i < cb; i++)
124 {
125 uint8_t opcode;
126 if (RT_SUCCESS(PATMR3QueryOpcode(pVM, (RTGCPTR)pSrc + i, &opcode)))
127 *(pDest+i) = opcode;
128
129 }
130 }
131# endif /* IN_RING3 */
132 return VINF_SUCCESS;
133}
134
135DECLINLINE(int) emDisCoreOne(PVM pVM, PVMCPU pVCpu, DISCPUSTATE *pDISState, RTGCUINTPTR InstrGC, uint32_t *pOpsize)
136{
137 EMDISSTATE State;
138
139 State.pVM = pVM;
140 State.pVCpu = pVCpu;
141
142 return DISCoreOneEx(InstrGC, pDISState->mode, EMReadBytes, &State, pDISState, pOpsize);
143}
144
145#else /* IN_RC */
146
147DECLINLINE(int) emDisCoreOne(PVM pVM, PVMCPU pVCpu, DISCPUSTATE *pDISState, RTGCUINTPTR InstrGC, uint32_t *pOpsize)
148{
149 NOREF(pVCpu);
150 NOREF(pVM);
151 return DISCoreOne(pDISState, InstrGC, pOpsize);
152}
153
154#endif /* IN_RC */
155
156
157/**
158 * Disassembles one instruction.
159 *
160 * @returns VBox status code, see SELMToFlatEx and EMInterpretDisasOneEx for
161 * details.
162 * @retval VERR_INTERNAL_ERROR on DISCoreOneEx failure.
163 *
164 * @param pVM The VM handle.
165 * @param pVCpu The VMCPU handle.
166 * @param pCtxCore The context core (used for both the mode and instruction).
167 * @param pDISState Where to return the parsed instruction info.
168 * @param pcbInstr Where to return the instruction size. (optional)
169 */
170VMMDECL(int) EMInterpretDisasOne(PVM pVM, PVMCPU pVCpu, PCCPUMCTXCORE pCtxCore, PDISCPUSTATE pDISState, unsigned *pcbInstr)
171{
172 RTGCPTR GCPtrInstr;
173 int rc = SELMToFlatEx(pVM, DIS_SELREG_CS, pCtxCore, pCtxCore->rip, 0, &GCPtrInstr);
174 if (RT_FAILURE(rc))
175 {
176 Log(("EMInterpretDisasOne: Failed to convert %RTsel:%RGv (cpl=%d) - rc=%Rrc !!\n",
177 pCtxCore->cs, (RTGCPTR)pCtxCore->rip, pCtxCore->ss & X86_SEL_RPL, rc));
178 return rc;
179 }
180 return EMInterpretDisasOneEx(pVM, pVCpu, (RTGCUINTPTR)GCPtrInstr, pCtxCore, pDISState, pcbInstr);
181}
182
183
184/**
185 * Disassembles one instruction.
186 *
187 * This is used by internally by the interpreter and by trap/access handlers.
188 *
189 * @returns VBox status code.
190 * @retval VERR_INTERNAL_ERROR on DISCoreOneEx failure.
191 *
192 * @param pVM The VM handle.
193 * @param pVCpu The VMCPU handle.
194 * @param GCPtrInstr The flat address of the instruction.
195 * @param pCtxCore The context core (used to determine the cpu mode).
196 * @param pDISState Where to return the parsed instruction info.
197 * @param pcbInstr Where to return the instruction size. (optional)
198 */
199VMMDECL(int) EMInterpretDisasOneEx(PVM pVM, PVMCPU pVCpu, RTGCUINTPTR GCPtrInstr, PCCPUMCTXCORE pCtxCore, PDISCPUSTATE pDISState, unsigned *pcbInstr)
200{
201#ifndef IN_RC
202 EMDISSTATE State;
203
204 State.pVM = pVM;
205 State.pVCpu = pVCpu;
206#endif
207
208 int rc = DISCoreOneEx(GCPtrInstr, SELMGetCpuModeFromSelector(pVM, pCtxCore->eflags, pCtxCore->cs, (PCPUMSELREGHID)&pCtxCore->csHid),
209#ifdef IN_RC
210 NULL, NULL,
211#else
212 EMReadBytes, &State,
213#endif
214 pDISState, pcbInstr);
215 if (RT_SUCCESS(rc))
216 return VINF_SUCCESS;
217 AssertMsgFailed(("DISCoreOne failed to GCPtrInstr=%RGv rc=%Rrc\n", GCPtrInstr, rc));
218 return VERR_INTERNAL_ERROR;
219}
220
221
222/**
223 * Interprets the current instruction.
224 *
225 * @returns VBox status code.
226 * @retval VINF_* Scheduling instructions.
227 * @retval VERR_EM_INTERPRETER Something we can't cope with.
228 * @retval VERR_* Fatal errors.
229 *
230 * @param pVM The VM handle.
231 * @param pVCpu The VMCPU handle.
232 * @param pRegFrame The register frame.
233 * Updates the EIP if an instruction was executed successfully.
234 * @param pvFault The fault address (CR2).
235 * @param pcbSize Size of the write (if applicable).
236 *
237 * @remark Invalid opcode exceptions have a higher priority than GP (see Intel
238 * Architecture System Developers Manual, Vol 3, 5.5) so we don't need
239 * to worry about e.g. invalid modrm combinations (!)
240 */
241VMMDECL(int) EMInterpretInstruction(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
242{
243 RTGCPTR pbCode;
244
245 LogFlow(("EMInterpretInstruction %RGv fault %RGv\n", (RTGCPTR)pRegFrame->rip, pvFault));
246 int rc = SELMToFlatEx(pVM, DIS_SELREG_CS, pRegFrame, pRegFrame->rip, 0, &pbCode);
247 if (RT_SUCCESS(rc))
248 {
249 uint32_t cbOp;
250 DISCPUSTATE Cpu;
251 Cpu.mode = SELMGetCpuModeFromSelector(pVM, pRegFrame->eflags, pRegFrame->cs, &pRegFrame->csHid);
252 rc = emDisCoreOne(pVM, pVCpu, &Cpu, (RTGCUINTPTR)pbCode, &cbOp);
253 if (RT_SUCCESS(rc))
254 {
255 Assert(cbOp == Cpu.opsize);
256 rc = EMInterpretInstructionCPU(pVM, pVCpu, &Cpu, pRegFrame, pvFault, pcbSize);
257 if (RT_SUCCESS(rc))
258 pRegFrame->rip += cbOp; /* Move on to the next instruction. */
259
260 return rc;
261 }
262 }
263 return VERR_EM_INTERPRETER;
264}
265
266
267/**
268 * Interprets the current instruction using the supplied DISCPUSTATE structure.
269 *
270 * EIP is *NOT* updated!
271 *
272 * @returns VBox status code.
273 * @retval VINF_* Scheduling instructions. When these are returned, it
274 * starts to get a bit tricky to know whether code was
275 * executed or not... We'll address this when it becomes a problem.
276 * @retval VERR_EM_INTERPRETER Something we can't cope with.
277 * @retval VERR_* Fatal errors.
278 *
279 * @param pVM The VM handle.
280 * @param pVCpu The VMCPU handle.
281 * @param pDISState The disassembler cpu state for the instruction to be interpreted.
282 * @param pRegFrame The register frame. EIP is *NOT* changed!
283 * @param pvFault The fault address (CR2).
284 * @param pcbSize Size of the write (if applicable).
285 *
286 * @remark Invalid opcode exceptions have a higher priority than GP (see Intel
287 * Architecture System Developers Manual, Vol 3, 5.5) so we don't need
288 * to worry about e.g. invalid modrm combinations (!)
289 *
290 * @todo At this time we do NOT check if the instruction overwrites vital information.
291 * Make sure this can't happen!! (will add some assertions/checks later)
292 */
293VMMDECL(int) EMInterpretInstructionCPU(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
294{
295 STAM_PROFILE_START(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,Emulate), a);
296 int rc = emInterpretInstructionCPU(pVM, pVCpu, pDISState, pRegFrame, pvFault, pcbSize);
297 STAM_PROFILE_STOP(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,Emulate), a);
298 if (RT_SUCCESS(rc))
299 STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,InterpretSucceeded));
300 else
301 STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,InterpretFailed));
302 return rc;
303}
304
305
306/**
307 * Interpret a port I/O instruction.
308 *
309 * @returns VBox status code suitable for scheduling.
310 * @param pVM The VM handle.
311 * @param pVCpu The VMCPU handle.
312 * @param pCtxCore The context core. This will be updated on successful return.
313 * @param pDISState The instruction to interpret.
314 * @param cbOp The size of the instruction.
315 * @remark This may raise exceptions.
316 */
317VMMDECL(int) EMInterpretPortIO(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, PDISCPUSTATE pDISState, uint32_t cbOp)
318{
319 /*
320 * Hand it on to IOM.
321 */
322#ifdef IN_RC
323 int rc = IOMGCIOPortHandler(pVM, pCtxCore, pDISState);
324 if (IOM_SUCCESS(rc))
325 pCtxCore->rip += cbOp;
326 return rc;
327#else
328 AssertReleaseMsgFailed(("not implemented\n"));
329 return VERR_NOT_IMPLEMENTED;
330#endif
331}
332
333
334DECLINLINE(int) emRamRead(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, void *pvDst, RTGCPTR GCPtrSrc, uint32_t cb)
335{
336#ifdef IN_RC
337 int rc = MMGCRamRead(pVM, pvDst, (void *)GCPtrSrc, cb);
338 if (RT_LIKELY(rc != VERR_ACCESS_DENIED))
339 return rc;
340 /*
341 * The page pool cache may end up here in some cases because it
342 * flushed one of the shadow mappings used by the trapping
343 * instruction and it either flushed the TLB or the CPU reused it.
344 */
345#endif
346 return PGMPhysInterpretedReadNoHandlers(pVCpu, pCtxCore, pvDst, GCPtrSrc, cb, /*fMayTrap*/ false);
347}
348
349
350DECLINLINE(int) emRamWrite(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, RTGCPTR GCPtrDst, const void *pvSrc, uint32_t cb)
351{
352#ifdef IN_RC
353 int rc = MMGCRamWrite(pVM, (void *)(uintptr_t)GCPtrDst, (void *)pvSrc, cb);
354 if (RT_LIKELY(rc != VERR_ACCESS_DENIED))
355 return rc;
356 /*
357 * The page pool cache may end up here in some cases because it
358 * flushed one of the shadow mappings used by the trapping
359 * instruction and it either flushed the TLB or the CPU reused it.
360 * We want to play safe here, verifying that we've got write
361 * access doesn't cost us much (see PGMPhysGCPtr2GCPhys()).
362 */
363#endif
364 return PGMPhysInterpretedWriteNoHandlers(pVCpu, pCtxCore, GCPtrDst, pvSrc, cb, /*fMayTrap*/ false);
365}
366
367
368/** Convert sel:addr to a flat GC address. */
369DECLINLINE(RTGCPTR) emConvertToFlatAddr(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pDISState, POP_PARAMETER pParam, RTGCPTR pvAddr)
370{
371 DIS_SELREG enmPrefixSeg = DISDetectSegReg(pDISState, pParam);
372 return SELMToFlat(pVM, enmPrefixSeg, pRegFrame, pvAddr);
373}
374
375
376#if defined(VBOX_STRICT) || defined(LOG_ENABLED)
377/**
378 * Get the mnemonic for the disassembled instruction.
379 *
380 * GC/R0 doesn't include the strings in the DIS tables because
381 * of limited space.
382 */
383static const char *emGetMnemonic(PDISCPUSTATE pDISState)
384{
385 switch (pDISState->pCurInstr->opcode)
386 {
387 case OP_XCHG: return "Xchg";
388 case OP_DEC: return "Dec";
389 case OP_INC: return "Inc";
390 case OP_POP: return "Pop";
391 case OP_OR: return "Or";
392 case OP_AND: return "And";
393 case OP_MOV: return "Mov";
394 case OP_INVLPG: return "InvlPg";
395 case OP_CPUID: return "CpuId";
396 case OP_MOV_CR: return "MovCRx";
397 case OP_MOV_DR: return "MovDRx";
398 case OP_LLDT: return "LLdt";
399 case OP_LGDT: return "LGdt";
400 case OP_LIDT: return "LGdt";
401 case OP_CLTS: return "Clts";
402 case OP_MONITOR: return "Monitor";
403 case OP_MWAIT: return "MWait";
404 case OP_RDMSR: return "Rdmsr";
405 case OP_WRMSR: return "Wrmsr";
406 case OP_ADD: return "Add";
407 case OP_ADC: return "Adc";
408 case OP_SUB: return "Sub";
409 case OP_SBB: return "Sbb";
410 case OP_RDTSC: return "Rdtsc";
411 case OP_STI: return "Sti";
412 case OP_CLI: return "Cli";
413 case OP_XADD: return "XAdd";
414 case OP_HLT: return "Hlt";
415 case OP_IRET: return "Iret";
416 case OP_MOVNTPS: return "MovNTPS";
417 case OP_STOSWD: return "StosWD";
418 case OP_WBINVD: return "WbInvd";
419 case OP_XOR: return "Xor";
420 case OP_BTR: return "Btr";
421 case OP_BTS: return "Bts";
422 case OP_BTC: return "Btc";
423 case OP_LMSW: return "Lmsw";
424 case OP_SMSW: return "Smsw";
425 case OP_CMPXCHG: return pDISState->prefix & PREFIX_LOCK ? "Lock CmpXchg" : "CmpXchg";
426 case OP_CMPXCHG8B: return pDISState->prefix & PREFIX_LOCK ? "Lock CmpXchg8b" : "CmpXchg8b";
427
428 default:
429 Log(("Unknown opcode %d\n", pDISState->pCurInstr->opcode));
430 return "???";
431 }
432}
433#endif /* VBOX_STRICT || LOG_ENABLED */
434
435
436/**
437 * XCHG instruction emulation.
438 */
439static int emInterpretXchg(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
440{
441 OP_PARAMVAL param1, param2;
442
443 /* Source to make DISQueryParamVal read the register value - ugly hack */
444 int rc = DISQueryParamVal(pRegFrame, pDISState, &pDISState->param1, &param1, PARAM_SOURCE);
445 if(RT_FAILURE(rc))
446 return VERR_EM_INTERPRETER;
447
448 rc = DISQueryParamVal(pRegFrame, pDISState, &pDISState->param2, &param2, PARAM_SOURCE);
449 if(RT_FAILURE(rc))
450 return VERR_EM_INTERPRETER;
451
452#ifdef IN_RC
453 if (TRPMHasTrap(pVCpu))
454 {
455 if (TRPMGetErrorCode(pVCpu) & X86_TRAP_PF_RW)
456 {
457#endif
458 RTGCPTR pParam1 = 0, pParam2 = 0;
459 uint64_t valpar1, valpar2;
460
461 AssertReturn(pDISState->param1.size == pDISState->param2.size, VERR_EM_INTERPRETER);
462 switch(param1.type)
463 {
464 case PARMTYPE_IMMEDIATE: /* register type is translated to this one too */
465 valpar1 = param1.val.val64;
466 break;
467
468 case PARMTYPE_ADDRESS:
469 pParam1 = (RTGCPTR)param1.val.val64;
470 pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pDISState, &pDISState->param1, pParam1);
471 EM_ASSERT_FAULT_RETURN(pParam1 == pvFault, VERR_EM_INTERPRETER);
472 rc = emRamRead(pVM, pVCpu, pRegFrame, &valpar1, pParam1, param1.size);
473 if (RT_FAILURE(rc))
474 {
475 AssertMsgFailed(("MMGCRamRead %RGv size=%d failed with %Rrc\n", pParam1, param1.size, rc));
476 return VERR_EM_INTERPRETER;
477 }
478 break;
479
480 default:
481 AssertFailed();
482 return VERR_EM_INTERPRETER;
483 }
484
485 switch(param2.type)
486 {
487 case PARMTYPE_ADDRESS:
488 pParam2 = (RTGCPTR)param2.val.val64;
489 pParam2 = emConvertToFlatAddr(pVM, pRegFrame, pDISState, &pDISState->param2, pParam2);
490 EM_ASSERT_FAULT_RETURN(pParam2 == pvFault, VERR_EM_INTERPRETER);
491 rc = emRamRead(pVM, pVCpu, pRegFrame, &valpar2, pParam2, param2.size);
492 if (RT_FAILURE(rc))
493 {
494 AssertMsgFailed(("MMGCRamRead %RGv size=%d failed with %Rrc\n", pParam1, param1.size, rc));
495 }
496 break;
497
498 case PARMTYPE_IMMEDIATE:
499 valpar2 = param2.val.val64;
500 break;
501
502 default:
503 AssertFailed();
504 return VERR_EM_INTERPRETER;
505 }
506
507 /* Write value of parameter 2 to parameter 1 (reg or memory address) */
508 if (pParam1 == 0)
509 {
510 Assert(param1.type == PARMTYPE_IMMEDIATE); /* register actually */
511 switch(param1.size)
512 {
513 case 1: //special case for AH etc
514 rc = DISWriteReg8(pRegFrame, pDISState->param1.base.reg_gen, (uint8_t )valpar2); break;
515 case 2: rc = DISWriteReg16(pRegFrame, pDISState->param1.base.reg_gen, (uint16_t)valpar2); break;
516 case 4: rc = DISWriteReg32(pRegFrame, pDISState->param1.base.reg_gen, (uint32_t)valpar2); break;
517 case 8: rc = DISWriteReg64(pRegFrame, pDISState->param1.base.reg_gen, valpar2); break;
518 default: AssertFailedReturn(VERR_EM_INTERPRETER);
519 }
520 if (RT_FAILURE(rc))
521 return VERR_EM_INTERPRETER;
522 }
523 else
524 {
525 rc = emRamWrite(pVM, pVCpu, pRegFrame, pParam1, &valpar2, param1.size);
526 if (RT_FAILURE(rc))
527 {
528 AssertMsgFailed(("emRamWrite %RGv size=%d failed with %Rrc\n", pParam1, param1.size, rc));
529 return VERR_EM_INTERPRETER;
530 }
531 }
532
533 /* Write value of parameter 1 to parameter 2 (reg or memory address) */
534 if (pParam2 == 0)
535 {
536 Assert(param2.type == PARMTYPE_IMMEDIATE); /* register actually */
537 switch(param2.size)
538 {
539 case 1: //special case for AH etc
540 rc = DISWriteReg8(pRegFrame, pDISState->param2.base.reg_gen, (uint8_t )valpar1); break;
541 case 2: rc = DISWriteReg16(pRegFrame, pDISState->param2.base.reg_gen, (uint16_t)valpar1); break;
542 case 4: rc = DISWriteReg32(pRegFrame, pDISState->param2.base.reg_gen, (uint32_t)valpar1); break;
543 case 8: rc = DISWriteReg64(pRegFrame, pDISState->param2.base.reg_gen, valpar1); break;
544 default: AssertFailedReturn(VERR_EM_INTERPRETER);
545 }
546 if (RT_FAILURE(rc))
547 return VERR_EM_INTERPRETER;
548 }
549 else
550 {
551 rc = emRamWrite(pVM, pVCpu, pRegFrame, pParam2, &valpar1, param2.size);
552 if (RT_FAILURE(rc))
553 {
554 AssertMsgFailed(("emRamWrite %RGv size=%d failed with %Rrc\n", pParam1, param1.size, rc));
555 return VERR_EM_INTERPRETER;
556 }
557 }
558
559 *pcbSize = param2.size;
560 return VINF_SUCCESS;
561#ifdef IN_RC
562 }
563 }
564#endif
565 return VERR_EM_INTERPRETER;
566}
567
568
569/**
570 * INC and DEC emulation.
571 */
572static int emInterpretIncDec(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize,
573 PFNEMULATEPARAM2 pfnEmulate)
574{
575 OP_PARAMVAL param1;
576
577 int rc = DISQueryParamVal(pRegFrame, pDISState, &pDISState->param1, &param1, PARAM_DEST);
578 if(RT_FAILURE(rc))
579 return VERR_EM_INTERPRETER;
580
581#ifdef IN_RC
582 if (TRPMHasTrap(pVCpu))
583 {
584 if (TRPMGetErrorCode(pVCpu) & X86_TRAP_PF_RW)
585 {
586#endif
587 RTGCPTR pParam1 = 0;
588 uint64_t valpar1;
589
590 if (param1.type == PARMTYPE_ADDRESS)
591 {
592 pParam1 = (RTGCPTR)param1.val.val64;
593 pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pDISState, &pDISState->param1, pParam1);
594#ifdef IN_RC
595 /* Safety check (in theory it could cross a page boundary and fault there though) */
596 AssertReturn(pParam1 == pvFault, VERR_EM_INTERPRETER);
597#endif
598 rc = emRamRead(pVM, pVCpu, pRegFrame, &valpar1, pParam1, param1.size);
599 if (RT_FAILURE(rc))
600 {
601 AssertMsgFailed(("emRamRead %RGv size=%d failed with %Rrc\n", pParam1, param1.size, rc));
602 return VERR_EM_INTERPRETER;
603 }
604 }
605 else
606 {
607 AssertFailed();
608 return VERR_EM_INTERPRETER;
609 }
610
611 uint32_t eflags;
612
613 eflags = pfnEmulate(&valpar1, param1.size);
614
615 /* Write result back */
616 rc = emRamWrite(pVM, pVCpu, pRegFrame, pParam1, &valpar1, param1.size);
617 if (RT_FAILURE(rc))
618 {
619 AssertMsgFailed(("emRamWrite %RGv size=%d failed with %Rrc\n", pParam1, param1.size, rc));
620 return VERR_EM_INTERPRETER;
621 }
622
623 /* Update guest's eflags and finish. */
624 pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
625 | (eflags & (X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF));
626
627 /* All done! */
628 *pcbSize = param1.size;
629 return VINF_SUCCESS;
630#ifdef IN_RC
631 }
632 }
633#endif
634 return VERR_EM_INTERPRETER;
635}
636
637
638/**
639 * POP Emulation.
640 */
641static int emInterpretPop(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
642{
643 Assert(pDISState->mode != CPUMODE_64BIT); /** @todo check */
644 OP_PARAMVAL param1;
645 int rc = DISQueryParamVal(pRegFrame, pDISState, &pDISState->param1, &param1, PARAM_DEST);
646 if(RT_FAILURE(rc))
647 return VERR_EM_INTERPRETER;
648
649#ifdef IN_RC
650 if (TRPMHasTrap(pVCpu))
651 {
652 if (TRPMGetErrorCode(pVCpu) & X86_TRAP_PF_RW)
653 {
654#endif
655 RTGCPTR pParam1 = 0;
656 uint32_t valpar1;
657 RTGCPTR pStackVal;
658
659 /* Read stack value first */
660 if (SELMGetCpuModeFromSelector(pVM, pRegFrame->eflags, pRegFrame->ss, &pRegFrame->ssHid) == CPUMODE_16BIT)
661 return VERR_EM_INTERPRETER; /* No legacy 16 bits stuff here, please. */
662
663 /* Convert address; don't bother checking limits etc, as we only read here */
664 pStackVal = SELMToFlat(pVM, DIS_SELREG_SS, pRegFrame, (RTGCPTR)pRegFrame->esp);
665 if (pStackVal == 0)
666 return VERR_EM_INTERPRETER;
667
668 rc = emRamRead(pVM, pVCpu, pRegFrame, &valpar1, pStackVal, param1.size);
669 if (RT_FAILURE(rc))
670 {
671 AssertMsgFailed(("emRamRead %RGv size=%d failed with %Rrc\n", pParam1, param1.size, rc));
672 return VERR_EM_INTERPRETER;
673 }
674
675 if (param1.type == PARMTYPE_ADDRESS)
676 {
677 pParam1 = (RTGCPTR)param1.val.val64;
678
679 /* pop [esp+xx] uses esp after the actual pop! */
680 AssertCompile(USE_REG_ESP == USE_REG_SP);
681 if ( (pDISState->param1.flags & USE_BASE)
682 && (pDISState->param1.flags & (USE_REG_GEN16|USE_REG_GEN32))
683 && pDISState->param1.base.reg_gen == USE_REG_ESP
684 )
685 pParam1 = (RTGCPTR)((RTGCUINTPTR)pParam1 + param1.size);
686
687 pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pDISState, &pDISState->param1, pParam1);
688 EM_ASSERT_FAULT_RETURN(pParam1 == pvFault || (RTGCPTR)pRegFrame->esp == pvFault, VERR_EM_INTERPRETER);
689 rc = emRamWrite(pVM, pVCpu, pRegFrame, pParam1, &valpar1, param1.size);
690 if (RT_FAILURE(rc))
691 {
692 AssertMsgFailed(("emRamWrite %RGv size=%d failed with %Rrc\n", pParam1, param1.size, rc));
693 return VERR_EM_INTERPRETER;
694 }
695
696 /* Update ESP as the last step */
697 pRegFrame->esp += param1.size;
698 }
699 else
700 {
701#ifndef DEBUG_bird // annoying assertion.
702 AssertFailed();
703#endif
704 return VERR_EM_INTERPRETER;
705 }
706
707 /* All done! */
708 *pcbSize = param1.size;
709 return VINF_SUCCESS;
710#ifdef IN_RC
711 }
712 }
713#endif
714 return VERR_EM_INTERPRETER;
715}
716
717
718/**
719 * XOR/OR/AND Emulation.
720 */
721static int emInterpretOrXorAnd(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize,
722 PFNEMULATEPARAM3 pfnEmulate)
723{
724 OP_PARAMVAL param1, param2;
725
726 int rc = DISQueryParamVal(pRegFrame, pDISState, &pDISState->param1, &param1, PARAM_DEST);
727 if(RT_FAILURE(rc))
728 return VERR_EM_INTERPRETER;
729
730 rc = DISQueryParamVal(pRegFrame, pDISState, &pDISState->param2, &param2, PARAM_SOURCE);
731 if(RT_FAILURE(rc))
732 return VERR_EM_INTERPRETER;
733
734#ifdef IN_RC
735 if (TRPMHasTrap(pVCpu))
736 {
737 if (TRPMGetErrorCode(pVCpu) & X86_TRAP_PF_RW)
738 {
739#endif
740 RTGCPTR pParam1;
741 uint64_t valpar1, valpar2;
742
743 if (pDISState->param1.size != pDISState->param2.size)
744 {
745 if (pDISState->param1.size < pDISState->param2.size)
746 {
747 AssertMsgFailed(("%s at %RGv parameter mismatch %d vs %d!!\n", emGetMnemonic(pDISState), (RTGCPTR)pRegFrame->rip, pDISState->param1.size, pDISState->param2.size)); /* should never happen! */
748 return VERR_EM_INTERPRETER;
749 }
750 /* Or %Ev, Ib -> just a hack to save some space; the data width of the 1st parameter determines the real width */
751 pDISState->param2.size = pDISState->param1.size;
752 param2.size = param1.size;
753 }
754
755 /* The destination is always a virtual address */
756 if (param1.type == PARMTYPE_ADDRESS)
757 {
758 pParam1 = (RTGCPTR)param1.val.val64;
759 pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pDISState, &pDISState->param1, pParam1);
760 EM_ASSERT_FAULT_RETURN(pParam1 == pvFault, VERR_EM_INTERPRETER);
761 rc = emRamRead(pVM, pVCpu, pRegFrame, &valpar1, pParam1, param1.size);
762 if (RT_FAILURE(rc))
763 {
764 AssertMsgFailed(("emRamRead %RGv size=%d failed with %Rrc\n", pParam1, param1.size, rc));
765 return VERR_EM_INTERPRETER;
766 }
767 }
768 else
769 {
770 AssertFailed();
771 return VERR_EM_INTERPRETER;
772 }
773
774 /* Register or immediate data */
775 switch(param2.type)
776 {
777 case PARMTYPE_IMMEDIATE: /* both immediate data and register (ugly) */
778 valpar2 = param2.val.val64;
779 break;
780
781 default:
782 AssertFailed();
783 return VERR_EM_INTERPRETER;
784 }
785
786 LogFlow(("emInterpretOrXorAnd %s %RGv %RX64 - %RX64 size %d (%d)\n", emGetMnemonic(pDISState), pParam1, valpar1, valpar2, param2.size, param1.size));
787
788 /* Data read, emulate instruction. */
789 uint32_t eflags = pfnEmulate(&valpar1, valpar2, param2.size);
790
791 LogFlow(("emInterpretOrXorAnd %s result %RX64\n", emGetMnemonic(pDISState), valpar1));
792
793 /* Update guest's eflags and finish. */
794 pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
795 | (eflags & (X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF));
796
797 /* And write it back */
798 rc = emRamWrite(pVM, pVCpu, pRegFrame, pParam1, &valpar1, param1.size);
799 if (RT_SUCCESS(rc))
800 {
801 /* All done! */
802 *pcbSize = param2.size;
803 return VINF_SUCCESS;
804 }
805#ifdef IN_RC
806 }
807 }
808#endif
809 return VERR_EM_INTERPRETER;
810}
811
812
813/**
814 * LOCK XOR/OR/AND Emulation.
815 */
816static int emInterpretLockOrXorAnd(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault,
817 uint32_t *pcbSize, PFNEMULATELOCKPARAM3 pfnEmulate)
818{
819 void *pvParam1;
820 OP_PARAMVAL param1, param2;
821
822#if HC_ARCH_BITS == 32
823 Assert(pDISState->param1.size <= 4);
824#endif
825
826 int rc = DISQueryParamVal(pRegFrame, pDISState, &pDISState->param1, &param1, PARAM_DEST);
827 if(RT_FAILURE(rc))
828 return VERR_EM_INTERPRETER;
829
830 rc = DISQueryParamVal(pRegFrame, pDISState, &pDISState->param2, &param2, PARAM_SOURCE);
831 if(RT_FAILURE(rc))
832 return VERR_EM_INTERPRETER;
833
834 if (pDISState->param1.size != pDISState->param2.size)
835 {
836 AssertMsgReturn(pDISState->param1.size >= pDISState->param2.size, /* should never happen! */
837 ("%s at %RGv parameter mismatch %d vs %d!!\n", emGetMnemonic(pDISState), (RTGCPTR)pRegFrame->rip, pDISState->param1.size, pDISState->param2.size),
838 VERR_EM_INTERPRETER);
839
840 /* Or %Ev, Ib -> just a hack to save some space; the data width of the 1st parameter determines the real width */
841 pDISState->param2.size = pDISState->param1.size;
842 param2.size = param1.size;
843 }
844
845#ifdef IN_RC
846 /* Safety check (in theory it could cross a page boundary and fault there though) */
847 Assert( TRPMHasTrap(pVCpu)
848 && (TRPMGetErrorCode(pVCpu) & X86_TRAP_PF_RW));
849 EM_ASSERT_FAULT_RETURN(GCPtrPar1 == pvFault, VERR_EM_INTERPRETER);
850#endif
851
852 /* Register and immediate data == PARMTYPE_IMMEDIATE */
853 AssertReturn(param2.type == PARMTYPE_IMMEDIATE, VERR_EM_INTERPRETER);
854 RTGCUINTREG ValPar2 = param2.val.val64;
855
856 /* The destination is always a virtual address */
857 AssertReturn(param1.type == PARMTYPE_ADDRESS, VERR_EM_INTERPRETER);
858
859 RTGCPTR GCPtrPar1 = param1.val.val64;
860 GCPtrPar1 = emConvertToFlatAddr(pVM, pRegFrame, pDISState, &pDISState->param1, GCPtrPar1);
861#ifdef IN_RC
862 pvParam1 = (void *)GCPtrPar1;
863#else
864 PGMPAGEMAPLOCK Lock;
865 rc = PGMPhysGCPtr2CCPtr(pVCpu, GCPtrPar1, &pvParam1, &Lock);
866 AssertRCReturn(rc, VERR_EM_INTERPRETER);
867#endif
868
869 /* Try emulate it with a one-shot #PF handler in place. (RC) */
870 Log2(("%s %RGv imm%d=%RX64\n", emGetMnemonic(pDISState), GCPtrPar1, pDISState->param2.size*8, ValPar2));
871
872 RTGCUINTREG32 eflags = 0;
873#ifdef IN_RC
874 MMGCRamRegisterTrapHandler(pVM);
875#endif
876 rc = pfnEmulate(pvParam1, ValPar2, pDISState->param2.size, &eflags);
877#ifdef IN_RC
878 MMGCRamDeregisterTrapHandler(pVM);
879#else
880 PGMPhysReleasePageMappingLock(pVM, &Lock);
881#endif
882 if (RT_FAILURE(rc))
883 {
884 Log(("%s %RGv imm%d=%RX64-> emulation failed due to page fault!\n", emGetMnemonic(pDISState), GCPtrPar1, pDISState->param2.size*8, ValPar2));
885 return VERR_EM_INTERPRETER;
886 }
887
888 /* Update guest's eflags and finish. */
889 pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
890 | (eflags & (X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF));
891
892 *pcbSize = param2.size;
893 return VINF_SUCCESS;
894}
895
896
897/**
898 * ADD, ADC & SUB Emulation.
899 */
900static int emInterpretAddSub(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize,
901 PFNEMULATEPARAM3 pfnEmulate)
902{
903 OP_PARAMVAL param1, param2;
904 int rc = DISQueryParamVal(pRegFrame, pDISState, &pDISState->param1, &param1, PARAM_DEST);
905 if(RT_FAILURE(rc))
906 return VERR_EM_INTERPRETER;
907
908 rc = DISQueryParamVal(pRegFrame, pDISState, &pDISState->param2, &param2, PARAM_SOURCE);
909 if(RT_FAILURE(rc))
910 return VERR_EM_INTERPRETER;
911
912#ifdef IN_RC
913 if (TRPMHasTrap(pVCpu))
914 {
915 if (TRPMGetErrorCode(pVCpu) & X86_TRAP_PF_RW)
916 {
917#endif
918 RTGCPTR pParam1;
919 uint64_t valpar1, valpar2;
920
921 if (pDISState->param1.size != pDISState->param2.size)
922 {
923 if (pDISState->param1.size < pDISState->param2.size)
924 {
925 AssertMsgFailed(("%s at %RGv parameter mismatch %d vs %d!!\n", emGetMnemonic(pDISState), (RTGCPTR)pRegFrame->rip, pDISState->param1.size, pDISState->param2.size)); /* should never happen! */
926 return VERR_EM_INTERPRETER;
927 }
928 /* Or %Ev, Ib -> just a hack to save some space; the data width of the 1st parameter determines the real width */
929 pDISState->param2.size = pDISState->param1.size;
930 param2.size = param1.size;
931 }
932
933 /* The destination is always a virtual address */
934 if (param1.type == PARMTYPE_ADDRESS)
935 {
936 pParam1 = (RTGCPTR)param1.val.val64;
937 pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pDISState, &pDISState->param1, pParam1);
938 EM_ASSERT_FAULT_RETURN(pParam1 == pvFault, VERR_EM_INTERPRETER);
939 rc = emRamRead(pVM, pVCpu, pRegFrame, &valpar1, pParam1, param1.size);
940 if (RT_FAILURE(rc))
941 {
942 AssertMsgFailed(("emRamRead %RGv size=%d failed with %Rrc\n", pParam1, param1.size, rc));
943 return VERR_EM_INTERPRETER;
944 }
945 }
946 else
947 {
948#ifndef DEBUG_bird
949 AssertFailed();
950#endif
951 return VERR_EM_INTERPRETER;
952 }
953
954 /* Register or immediate data */
955 switch(param2.type)
956 {
957 case PARMTYPE_IMMEDIATE: /* both immediate data and register (ugly) */
958 valpar2 = param2.val.val64;
959 break;
960
961 default:
962 AssertFailed();
963 return VERR_EM_INTERPRETER;
964 }
965
966 /* Data read, emulate instruction. */
967 uint32_t eflags = pfnEmulate(&valpar1, valpar2, param2.size);
968
969 /* Update guest's eflags and finish. */
970 pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
971 | (eflags & (X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF));
972
973 /* And write it back */
974 rc = emRamWrite(pVM, pVCpu, pRegFrame, pParam1, &valpar1, param1.size);
975 if (RT_SUCCESS(rc))
976 {
977 /* All done! */
978 *pcbSize = param2.size;
979 return VINF_SUCCESS;
980 }
981#ifdef IN_RC
982 }
983 }
984#endif
985 return VERR_EM_INTERPRETER;
986}
987
988
989/**
990 * ADC Emulation.
991 */
992static int emInterpretAdc(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
993{
994 if (pRegFrame->eflags.Bits.u1CF)
995 return emInterpretAddSub(pVM, pVCpu, pDISState, pRegFrame, pvFault, pcbSize, EMEmulateAdcWithCarrySet);
996 else
997 return emInterpretAddSub(pVM, pVCpu, pDISState, pRegFrame, pvFault, pcbSize, EMEmulateAdd);
998}
999
1000
1001/**
1002 * BTR/C/S Emulation.
1003 */
1004static int emInterpretBitTest(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize,
1005 PFNEMULATEPARAM2UINT32 pfnEmulate)
1006{
1007 OP_PARAMVAL param1, param2;
1008 int rc = DISQueryParamVal(pRegFrame, pDISState, &pDISState->param1, &param1, PARAM_DEST);
1009 if(RT_FAILURE(rc))
1010 return VERR_EM_INTERPRETER;
1011
1012 rc = DISQueryParamVal(pRegFrame, pDISState, &pDISState->param2, &param2, PARAM_SOURCE);
1013 if(RT_FAILURE(rc))
1014 return VERR_EM_INTERPRETER;
1015
1016#ifdef IN_RC
1017 if (TRPMHasTrap(pVCpu))
1018 {
1019 if (TRPMGetErrorCode(pVCpu) & X86_TRAP_PF_RW)
1020 {
1021#endif
1022 RTGCPTR pParam1;
1023 uint64_t valpar1 = 0, valpar2;
1024 uint32_t eflags;
1025
1026 /* The destination is always a virtual address */
1027 if (param1.type != PARMTYPE_ADDRESS)
1028 return VERR_EM_INTERPRETER;
1029
1030 pParam1 = (RTGCPTR)param1.val.val64;
1031 pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pDISState, &pDISState->param1, pParam1);
1032
1033 /* Register or immediate data */
1034 switch(param2.type)
1035 {
1036 case PARMTYPE_IMMEDIATE: /* both immediate data and register (ugly) */
1037 valpar2 = param2.val.val64;
1038 break;
1039
1040 default:
1041 AssertFailed();
1042 return VERR_EM_INTERPRETER;
1043 }
1044
1045 Log2(("emInterpret%s: pvFault=%RGv pParam1=%RGv val2=%x\n", emGetMnemonic(pDISState), pvFault, pParam1, valpar2));
1046 pParam1 = (RTGCPTR)((RTGCUINTPTR)pParam1 + valpar2/8);
1047 EM_ASSERT_FAULT_RETURN((RTGCPTR)((RTGCUINTPTR)pParam1 & ~3) == pvFault, VERR_EM_INTERPRETER);
1048 rc = emRamRead(pVM, pVCpu, pRegFrame, &valpar1, pParam1, 1);
1049 if (RT_FAILURE(rc))
1050 {
1051 AssertMsgFailed(("emRamRead %RGv size=%d failed with %Rrc\n", pParam1, param1.size, rc));
1052 return VERR_EM_INTERPRETER;
1053 }
1054
1055 Log2(("emInterpretBtx: val=%x\n", valpar1));
1056 /* Data read, emulate bit test instruction. */
1057 eflags = pfnEmulate(&valpar1, valpar2 & 0x7);
1058
1059 Log2(("emInterpretBtx: val=%x CF=%d\n", valpar1, !!(eflags & X86_EFL_CF)));
1060
1061 /* Update guest's eflags and finish. */
1062 pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
1063 | (eflags & (X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF));
1064
1065 /* And write it back */
1066 rc = emRamWrite(pVM, pVCpu, pRegFrame, pParam1, &valpar1, 1);
1067 if (RT_SUCCESS(rc))
1068 {
1069 /* All done! */
1070 *pcbSize = 1;
1071 return VINF_SUCCESS;
1072 }
1073#ifdef IN_RC
1074 }
1075 }
1076#endif
1077 return VERR_EM_INTERPRETER;
1078}
1079
1080
1081/**
1082 * LOCK BTR/C/S Emulation.
1083 */
1084static int emInterpretLockBitTest(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault,
1085 uint32_t *pcbSize, PFNEMULATELOCKPARAM2 pfnEmulate)
1086{
1087 void *pvParam1;
1088
1089 OP_PARAMVAL param1, param2;
1090 int rc = DISQueryParamVal(pRegFrame, pDISState, &pDISState->param1, &param1, PARAM_DEST);
1091 if(RT_FAILURE(rc))
1092 return VERR_EM_INTERPRETER;
1093
1094 rc = DISQueryParamVal(pRegFrame, pDISState, &pDISState->param2, &param2, PARAM_SOURCE);
1095 if(RT_FAILURE(rc))
1096 return VERR_EM_INTERPRETER;
1097
1098 /* The destination is always a virtual address */
1099 if (param1.type != PARMTYPE_ADDRESS)
1100 return VERR_EM_INTERPRETER;
1101
1102 /* Register and immediate data == PARMTYPE_IMMEDIATE */
1103 AssertReturn(param2.type == PARMTYPE_IMMEDIATE, VERR_EM_INTERPRETER);
1104 uint64_t ValPar2 = param2.val.val64;
1105
1106 /* Adjust the parameters so what we're dealing with is a bit within the byte pointed to. */
1107 RTGCPTR GCPtrPar1 = param1.val.val64;
1108 GCPtrPar1 = (GCPtrPar1 + ValPar2 / 8);
1109 ValPar2 &= 7;
1110
1111 GCPtrPar1 = emConvertToFlatAddr(pVM, pRegFrame, pDISState, &pDISState->param1, GCPtrPar1);
1112#ifdef IN_RC
1113 Assert(TRPMHasTrap(pVCpu));
1114 EM_ASSERT_FAULT_RETURN((RTGCPTR)((RTGCUINTPTR)GCPtrPar1 & ~(RTGCUINTPTR)3) == pvFault, VERR_EM_INTERPRETER);
1115#endif
1116
1117#ifdef IN_RC
1118 pvParam1 = (void *)GCPtrPar1;
1119#else
1120 PGMPAGEMAPLOCK Lock;
1121 rc = PGMPhysGCPtr2CCPtr(pVCpu, GCPtrPar1, &pvParam1, &Lock);
1122 AssertRCReturn(rc, VERR_EM_INTERPRETER);
1123#endif
1124
1125 Log2(("emInterpretLockBitTest %s: pvFault=%RGv GCPtrPar1=%RGv imm=%RX64\n", emGetMnemonic(pDISState), pvFault, GCPtrPar1, ValPar2));
1126
1127 /* Try emulate it with a one-shot #PF handler in place. (RC) */
1128 RTGCUINTREG32 eflags = 0;
1129#ifdef IN_RC
1130 MMGCRamRegisterTrapHandler(pVM);
1131#endif
1132 rc = pfnEmulate(pvParam1, ValPar2, &eflags);
1133#ifdef IN_RC
1134 MMGCRamDeregisterTrapHandler(pVM);
1135#else
1136 PGMPhysReleasePageMappingLock(pVM, &Lock);
1137#endif
1138 if (RT_FAILURE(rc))
1139 {
1140 Log(("emInterpretLockBitTest %s: %RGv imm%d=%RX64 -> emulation failed due to page fault!\n",
1141 emGetMnemonic(pDISState), GCPtrPar1, pDISState->param2.size*8, ValPar2));
1142 return VERR_EM_INTERPRETER;
1143 }
1144
1145 Log2(("emInterpretLockBitTest %s: GCPtrPar1=%RGv imm=%RX64 CF=%d\n", emGetMnemonic(pDISState), GCPtrPar1, ValPar2, !!(eflags & X86_EFL_CF)));
1146
1147 /* Update guest's eflags and finish. */
1148 pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
1149 | (eflags & (X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF));
1150
1151 *pcbSize = 1;
1152 return VINF_SUCCESS;
1153}
1154
1155
1156/**
1157 * MOV emulation.
1158 */
1159static int emInterpretMov(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
1160{
1161 OP_PARAMVAL param1, param2;
1162 int rc = DISQueryParamVal(pRegFrame, pDISState, &pDISState->param1, &param1, PARAM_DEST);
1163 if(RT_FAILURE(rc))
1164 return VERR_EM_INTERPRETER;
1165
1166 rc = DISQueryParamVal(pRegFrame, pDISState, &pDISState->param2, &param2, PARAM_SOURCE);
1167 if(RT_FAILURE(rc))
1168 return VERR_EM_INTERPRETER;
1169
1170#ifdef IN_RC
1171 if (TRPMHasTrap(pVCpu))
1172 {
1173 if (TRPMGetErrorCode(pVCpu) & X86_TRAP_PF_RW)
1174 {
1175#else
1176 /** @todo Make this the default and don't rely on TRPM information. */
1177 if (param1.type == PARMTYPE_ADDRESS)
1178 {
1179#endif
1180 RTGCPTR pDest;
1181 uint64_t val64;
1182
1183 switch(param1.type)
1184 {
1185 case PARMTYPE_IMMEDIATE:
1186 if(!(param1.flags & (PARAM_VAL32|PARAM_VAL64)))
1187 return VERR_EM_INTERPRETER;
1188 /* fallthru */
1189
1190 case PARMTYPE_ADDRESS:
1191 pDest = (RTGCPTR)param1.val.val64;
1192 pDest = emConvertToFlatAddr(pVM, pRegFrame, pDISState, &pDISState->param1, pDest);
1193 break;
1194
1195 default:
1196 AssertFailed();
1197 return VERR_EM_INTERPRETER;
1198 }
1199
1200 switch(param2.type)
1201 {
1202 case PARMTYPE_IMMEDIATE: /* register type is translated to this one too */
1203 val64 = param2.val.val64;
1204 break;
1205
1206 default:
1207 Log(("emInterpretMov: unexpected type=%d rip=%RGv\n", param2.type, (RTGCPTR)pRegFrame->rip));
1208 return VERR_EM_INTERPRETER;
1209 }
1210#ifdef LOG_ENABLED
1211 if (pDISState->mode == CPUMODE_64BIT)
1212 LogFlow(("EMInterpretInstruction at %RGv: OP_MOV %RGv <- %RX64 (%d) &val64=%RHv\n", (RTGCPTR)pRegFrame->rip, pDest, val64, param2.size, &val64));
1213 else
1214 LogFlow(("EMInterpretInstruction at %08RX64: OP_MOV %RGv <- %08X (%d) &val64=%RHv\n", pRegFrame->rip, pDest, (uint32_t)val64, param2.size, &val64));
1215#endif
1216
1217 Assert(param2.size <= 8 && param2.size > 0);
1218 EM_ASSERT_FAULT_RETURN(pDest == pvFault, VERR_EM_INTERPRETER);
1219 rc = emRamWrite(pVM, pVCpu, pRegFrame, pDest, &val64, param2.size);
1220 if (RT_FAILURE(rc))
1221 return VERR_EM_INTERPRETER;
1222
1223 *pcbSize = param2.size;
1224 }
1225 else
1226 { /* read fault */
1227 RTGCPTR pSrc;
1228 uint64_t val64;
1229
1230 /* Source */
1231 switch(param2.type)
1232 {
1233 case PARMTYPE_IMMEDIATE:
1234 if(!(param2.flags & (PARAM_VAL32|PARAM_VAL64)))
1235 return VERR_EM_INTERPRETER;
1236 /* fallthru */
1237
1238 case PARMTYPE_ADDRESS:
1239 pSrc = (RTGCPTR)param2.val.val64;
1240 pSrc = emConvertToFlatAddr(pVM, pRegFrame, pDISState, &pDISState->param2, pSrc);
1241 break;
1242
1243 default:
1244 return VERR_EM_INTERPRETER;
1245 }
1246
1247 Assert(param1.size <= 8 && param1.size > 0);
1248 EM_ASSERT_FAULT_RETURN(pSrc == pvFault, VERR_EM_INTERPRETER);
1249 rc = emRamRead(pVM, pVCpu, pRegFrame, &val64, pSrc, param1.size);
1250 if (RT_FAILURE(rc))
1251 return VERR_EM_INTERPRETER;
1252
1253 /* Destination */
1254 switch(param1.type)
1255 {
1256 case PARMTYPE_REGISTER:
1257 switch(param1.size)
1258 {
1259 case 1: rc = DISWriteReg8(pRegFrame, pDISState->param1.base.reg_gen, (uint8_t) val64); break;
1260 case 2: rc = DISWriteReg16(pRegFrame, pDISState->param1.base.reg_gen, (uint16_t)val64); break;
1261 case 4: rc = DISWriteReg32(pRegFrame, pDISState->param1.base.reg_gen, (uint32_t)val64); break;
1262 case 8: rc = DISWriteReg64(pRegFrame, pDISState->param1.base.reg_gen, val64); break;
1263 default:
1264 return VERR_EM_INTERPRETER;
1265 }
1266 if (RT_FAILURE(rc))
1267 return rc;
1268 break;
1269
1270 default:
1271 return VERR_EM_INTERPRETER;
1272 }
1273#ifdef LOG_ENABLED
1274 if (pDISState->mode == CPUMODE_64BIT)
1275 LogFlow(("EMInterpretInstruction: OP_MOV %RGv -> %RX64 (%d)\n", pSrc, val64, param1.size));
1276 else
1277 LogFlow(("EMInterpretInstruction: OP_MOV %RGv -> %08X (%d)\n", pSrc, (uint32_t)val64, param1.size));
1278#endif
1279 }
1280 return VINF_SUCCESS;
1281#ifdef IN_RC
1282 }
1283#endif
1284 return VERR_EM_INTERPRETER;
1285}
1286
1287
1288#ifndef IN_RC
1289/**
1290 * [REP] STOSWD emulation
1291 */
1292static int emInterpretStosWD(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
1293{
1294 int rc;
1295 RTGCPTR GCDest, GCOffset;
1296 uint32_t cbSize;
1297 uint64_t cTransfers;
1298 int offIncrement;
1299
1300 /* Don't support any but these three prefix bytes. */
1301 if ((pDISState->prefix & ~(PREFIX_ADDRSIZE|PREFIX_OPSIZE|PREFIX_REP|PREFIX_REX)))
1302 return VERR_EM_INTERPRETER;
1303
1304 switch (pDISState->addrmode)
1305 {
1306 case CPUMODE_16BIT:
1307 GCOffset = pRegFrame->di;
1308 cTransfers = pRegFrame->cx;
1309 break;
1310 case CPUMODE_32BIT:
1311 GCOffset = pRegFrame->edi;
1312 cTransfers = pRegFrame->ecx;
1313 break;
1314 case CPUMODE_64BIT:
1315 GCOffset = pRegFrame->rdi;
1316 cTransfers = pRegFrame->rcx;
1317 break;
1318 default:
1319 AssertFailed();
1320 return VERR_EM_INTERPRETER;
1321 }
1322
1323 GCDest = SELMToFlat(pVM, DIS_SELREG_ES, pRegFrame, GCOffset);
1324 switch (pDISState->opmode)
1325 {
1326 case CPUMODE_16BIT:
1327 cbSize = 2;
1328 break;
1329 case CPUMODE_32BIT:
1330 cbSize = 4;
1331 break;
1332 case CPUMODE_64BIT:
1333 cbSize = 8;
1334 break;
1335 default:
1336 AssertFailed();
1337 return VERR_EM_INTERPRETER;
1338 }
1339
1340 offIncrement = pRegFrame->eflags.Bits.u1DF ? -(signed)cbSize : (signed)cbSize;
1341
1342 if (!(pDISState->prefix & PREFIX_REP))
1343 {
1344 LogFlow(("emInterpretStosWD dest=%04X:%RGv (%RGv) cbSize=%d\n", pRegFrame->es, GCOffset, GCDest, cbSize));
1345
1346 rc = emRamWrite(pVM, pVCpu, pRegFrame, GCDest, &pRegFrame->rax, cbSize);
1347 if (RT_FAILURE(rc))
1348 return VERR_EM_INTERPRETER;
1349 Assert(rc == VINF_SUCCESS);
1350
1351 /* Update (e/r)di. */
1352 switch (pDISState->addrmode)
1353 {
1354 case CPUMODE_16BIT:
1355 pRegFrame->di += offIncrement;
1356 break;
1357 case CPUMODE_32BIT:
1358 pRegFrame->edi += offIncrement;
1359 break;
1360 case CPUMODE_64BIT:
1361 pRegFrame->rdi += offIncrement;
1362 break;
1363 default:
1364 AssertFailed();
1365 return VERR_EM_INTERPRETER;
1366 }
1367
1368 }
1369 else
1370 {
1371 if (!cTransfers)
1372 return VINF_SUCCESS;
1373
1374 /*
1375 * Do *not* try emulate cross page stuff here because we don't know what might
1376 * be waiting for us on the subsequent pages. The caller has only asked us to
1377 * ignore access handlers fro the current page.
1378 * This also fends off big stores which would quickly kill PGMR0DynMap.
1379 */
1380 if ( cbSize > PAGE_SIZE
1381 || cTransfers > PAGE_SIZE
1382 || (GCDest >> PAGE_SHIFT) != ((GCDest + offIncrement * cTransfers) >> PAGE_SHIFT))
1383 {
1384 Log(("STOSWD is crosses pages, chicken out to the recompiler; GCDest=%RGv cbSize=%#x offIncrement=%d cTransfers=%#x\n",
1385 GCDest, cbSize, offIncrement, cTransfers));
1386 return VERR_EM_INTERPRETER;
1387 }
1388
1389 LogFlow(("emInterpretStosWD dest=%04X:%RGv (%RGv) cbSize=%d cTransfers=%x DF=%d\n", pRegFrame->es, GCOffset, GCDest, cbSize, cTransfers, pRegFrame->eflags.Bits.u1DF));
1390 /* Access verification first; we currently can't recover properly from traps inside this instruction */
1391 rc = PGMVerifyAccess(pVCpu, GCDest - ((offIncrement > 0) ? 0 : ((cTransfers-1) * cbSize)),
1392 cTransfers * cbSize,
1393 X86_PTE_RW | (CPUMGetGuestCPL(pVCpu, pRegFrame) == 3 ? X86_PTE_US : 0));
1394 if (rc != VINF_SUCCESS)
1395 {
1396 Log(("STOSWD will generate a trap -> recompiler, rc=%d\n", rc));
1397 return VERR_EM_INTERPRETER;
1398 }
1399
1400 /* REP case */
1401 while (cTransfers)
1402 {
1403 rc = emRamWrite(pVM, pVCpu, pRegFrame, GCDest, &pRegFrame->rax, cbSize);
1404 if (RT_FAILURE(rc))
1405 {
1406 rc = VERR_EM_INTERPRETER;
1407 break;
1408 }
1409
1410 Assert(rc == VINF_SUCCESS);
1411 GCOffset += offIncrement;
1412 GCDest += offIncrement;
1413 cTransfers--;
1414 }
1415
1416 /* Update the registers. */
1417 switch (pDISState->addrmode)
1418 {
1419 case CPUMODE_16BIT:
1420 pRegFrame->di = GCOffset;
1421 pRegFrame->cx = cTransfers;
1422 break;
1423 case CPUMODE_32BIT:
1424 pRegFrame->edi = GCOffset;
1425 pRegFrame->ecx = cTransfers;
1426 break;
1427 case CPUMODE_64BIT:
1428 pRegFrame->rdi = GCOffset;
1429 pRegFrame->rcx = cTransfers;
1430 break;
1431 default:
1432 AssertFailed();
1433 return VERR_EM_INTERPRETER;
1434 }
1435 }
1436
1437 *pcbSize = cbSize;
1438 return rc;
1439}
1440#endif /* !IN_RC */
1441
1442#ifndef IN_RC
1443
1444/**
1445 * [LOCK] CMPXCHG emulation.
1446 */
1447static int emInterpretCmpXchg(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
1448{
1449 OP_PARAMVAL param1, param2;
1450
1451#if HC_ARCH_BITS == 32 && !defined(VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0)
1452 Assert(pDISState->param1.size <= 4);
1453#endif
1454
1455 /* Source to make DISQueryParamVal read the register value - ugly hack */
1456 int rc = DISQueryParamVal(pRegFrame, pDISState, &pDISState->param1, &param1, PARAM_SOURCE);
1457 if(RT_FAILURE(rc))
1458 return VERR_EM_INTERPRETER;
1459
1460 rc = DISQueryParamVal(pRegFrame, pDISState, &pDISState->param2, &param2, PARAM_SOURCE);
1461 if(RT_FAILURE(rc))
1462 return VERR_EM_INTERPRETER;
1463
1464 uint64_t valpar;
1465 switch(param2.type)
1466 {
1467 case PARMTYPE_IMMEDIATE: /* register actually */
1468 valpar = param2.val.val64;
1469 break;
1470
1471 default:
1472 return VERR_EM_INTERPRETER;
1473 }
1474
1475 PGMPAGEMAPLOCK Lock;
1476 RTGCPTR GCPtrPar1;
1477 void *pvParam1;
1478 uint64_t eflags;
1479
1480 AssertReturn(pDISState->param1.size == pDISState->param2.size, VERR_EM_INTERPRETER);
1481 switch(param1.type)
1482 {
1483 case PARMTYPE_ADDRESS:
1484 GCPtrPar1 = param1.val.val64;
1485 GCPtrPar1 = emConvertToFlatAddr(pVM, pRegFrame, pDISState, &pDISState->param1, GCPtrPar1);
1486
1487 rc = PGMPhysGCPtr2CCPtr(pVCpu, GCPtrPar1, &pvParam1, &Lock);
1488 AssertRCReturn(rc, VERR_EM_INTERPRETER);
1489 break;
1490
1491 default:
1492 return VERR_EM_INTERPRETER;
1493 }
1494
1495 LogFlow(("%s %RGv rax=%RX64 %RX64\n", emGetMnemonic(pDISState), GCPtrPar1, pRegFrame->rax, valpar));
1496
1497 if (pDISState->prefix & PREFIX_LOCK)
1498 eflags = EMEmulateLockCmpXchg(pvParam1, &pRegFrame->rax, valpar, pDISState->param2.size);
1499 else
1500 eflags = EMEmulateCmpXchg(pvParam1, &pRegFrame->rax, valpar, pDISState->param2.size);
1501
1502 LogFlow(("%s %RGv rax=%RX64 %RX64 ZF=%d\n", emGetMnemonic(pDISState), GCPtrPar1, pRegFrame->rax, valpar, !!(eflags & X86_EFL_ZF)));
1503
1504 /* Update guest's eflags and finish. */
1505 pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
1506 | (eflags & (X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF));
1507
1508 *pcbSize = param2.size;
1509 PGMPhysReleasePageMappingLock(pVM, &Lock);
1510 return VINF_SUCCESS;
1511}
1512
1513
1514/**
1515 * [LOCK] CMPXCHG8B emulation.
1516 */
1517static int emInterpretCmpXchg8b(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
1518{
1519 Assert(pDISState->mode != CPUMODE_64BIT); /** @todo check */
1520 OP_PARAMVAL param1;
1521
1522 /* Source to make DISQueryParamVal read the register value - ugly hack */
1523 int rc = DISQueryParamVal(pRegFrame, pDISState, &pDISState->param1, &param1, PARAM_SOURCE);
1524 if(RT_FAILURE(rc))
1525 return VERR_EM_INTERPRETER;
1526
1527 RTGCPTR GCPtrPar1;
1528 void *pvParam1;
1529 uint64_t eflags;
1530 PGMPAGEMAPLOCK Lock;
1531
1532 AssertReturn(pDISState->param1.size == 8, VERR_EM_INTERPRETER);
1533 switch(param1.type)
1534 {
1535 case PARMTYPE_ADDRESS:
1536 GCPtrPar1 = param1.val.val64;
1537 GCPtrPar1 = emConvertToFlatAddr(pVM, pRegFrame, pDISState, &pDISState->param1, GCPtrPar1);
1538
1539 rc = PGMPhysGCPtr2CCPtr(pVCpu, GCPtrPar1, &pvParam1, &Lock);
1540 AssertRCReturn(rc, VERR_EM_INTERPRETER);
1541 break;
1542
1543 default:
1544 return VERR_EM_INTERPRETER;
1545 }
1546
1547 LogFlow(("%s %RGv=%08x eax=%08x\n", emGetMnemonic(pDISState), pvParam1, pRegFrame->eax));
1548
1549 if (pDISState->prefix & PREFIX_LOCK)
1550 eflags = EMEmulateLockCmpXchg8b(pvParam1, &pRegFrame->eax, &pRegFrame->edx, pRegFrame->ebx, pRegFrame->ecx);
1551 else
1552 eflags = EMEmulateCmpXchg8b(pvParam1, &pRegFrame->eax, &pRegFrame->edx, pRegFrame->ebx, pRegFrame->ecx);
1553
1554 LogFlow(("%s %RGv=%08x eax=%08x ZF=%d\n", emGetMnemonic(pDISState), pvParam1, pRegFrame->eax, !!(eflags & X86_EFL_ZF)));
1555
1556 /* Update guest's eflags and finish; note that *only* ZF is affected. */
1557 pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_ZF))
1558 | (eflags & (X86_EFL_ZF));
1559
1560 *pcbSize = 8;
1561 PGMPhysReleasePageMappingLock(pVM, &Lock);
1562 return VINF_SUCCESS;
1563}
1564
1565#else /* IN_RC */
1566
1567/**
1568 * [LOCK] CMPXCHG emulation.
1569 */
1570static int emInterpretCmpXchg(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
1571{
1572 Assert(pDISState->mode != CPUMODE_64BIT); /** @todo check */
1573 OP_PARAMVAL param1, param2;
1574
1575 /* Source to make DISQueryParamVal read the register value - ugly hack */
1576 int rc = DISQueryParamVal(pRegFrame, pDISState, &pDISState->param1, &param1, PARAM_SOURCE);
1577 if(RT_FAILURE(rc))
1578 return VERR_EM_INTERPRETER;
1579
1580 rc = DISQueryParamVal(pRegFrame, pDISState, &pDISState->param2, &param2, PARAM_SOURCE);
1581 if(RT_FAILURE(rc))
1582 return VERR_EM_INTERPRETER;
1583
1584 if (TRPMHasTrap(pVCpu))
1585 {
1586 if (TRPMGetErrorCode(pVCpu) & X86_TRAP_PF_RW)
1587 {
1588 RTRCPTR pParam1;
1589 uint32_t valpar, eflags;
1590
1591 AssertReturn(pDISState->param1.size == pDISState->param2.size, VERR_EM_INTERPRETER);
1592 switch(param1.type)
1593 {
1594 case PARMTYPE_ADDRESS:
1595 pParam1 = (RTRCPTR)param1.val.val64;
1596 pParam1 = (RTRCPTR)emConvertToFlatAddr(pVM, pRegFrame, pDISState, &pDISState->param1, (RTGCPTR)(RTRCUINTPTR)pParam1);
1597 EM_ASSERT_FAULT_RETURN(pParam1 == (RTRCPTR)pvFault, VERR_EM_INTERPRETER);
1598 break;
1599
1600 default:
1601 return VERR_EM_INTERPRETER;
1602 }
1603
1604 switch(param2.type)
1605 {
1606 case PARMTYPE_IMMEDIATE: /* register actually */
1607 valpar = param2.val.val32;
1608 break;
1609
1610 default:
1611 return VERR_EM_INTERPRETER;
1612 }
1613
1614 LogFlow(("%s %RRv eax=%08x %08x\n", emGetMnemonic(pDISState), pParam1, pRegFrame->eax, valpar));
1615
1616 MMGCRamRegisterTrapHandler(pVM);
1617 if (pDISState->prefix & PREFIX_LOCK)
1618 rc = EMGCEmulateLockCmpXchg(pParam1, &pRegFrame->eax, valpar, pDISState->param2.size, &eflags);
1619 else
1620 rc = EMGCEmulateCmpXchg(pParam1, &pRegFrame->eax, valpar, pDISState->param2.size, &eflags);
1621 MMGCRamDeregisterTrapHandler(pVM);
1622
1623 if (RT_FAILURE(rc))
1624 {
1625 Log(("%s %RGv eax=%08x %08x -> emulation failed due to page fault!\n", emGetMnemonic(pDISState), pParam1, pRegFrame->eax, valpar));
1626 return VERR_EM_INTERPRETER;
1627 }
1628
1629 LogFlow(("%s %RRv eax=%08x %08x ZF=%d\n", emGetMnemonic(pDISState), pParam1, pRegFrame->eax, valpar, !!(eflags & X86_EFL_ZF)));
1630
1631 /* Update guest's eflags and finish. */
1632 pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
1633 | (eflags & (X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF));
1634
1635 *pcbSize = param2.size;
1636 return VINF_SUCCESS;
1637 }
1638 }
1639 return VERR_EM_INTERPRETER;
1640}
1641
1642
1643/**
1644 * [LOCK] CMPXCHG8B emulation.
1645 */
1646static int emInterpretCmpXchg8b(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
1647{
1648 Assert(pDISState->mode != CPUMODE_64BIT); /** @todo check */
1649 OP_PARAMVAL param1;
1650
1651 /* Source to make DISQueryParamVal read the register value - ugly hack */
1652 int rc = DISQueryParamVal(pRegFrame, pDISState, &pDISState->param1, &param1, PARAM_SOURCE);
1653 if(RT_FAILURE(rc))
1654 return VERR_EM_INTERPRETER;
1655
1656 if (TRPMHasTrap(pVCpu))
1657 {
1658 if (TRPMGetErrorCode(pVCpu) & X86_TRAP_PF_RW)
1659 {
1660 RTRCPTR pParam1;
1661 uint32_t eflags;
1662
1663 AssertReturn(pDISState->param1.size == 8, VERR_EM_INTERPRETER);
1664 switch(param1.type)
1665 {
1666 case PARMTYPE_ADDRESS:
1667 pParam1 = (RTRCPTR)param1.val.val64;
1668 pParam1 = (RTRCPTR)emConvertToFlatAddr(pVM, pRegFrame, pDISState, &pDISState->param1, (RTGCPTR)(RTRCUINTPTR)pParam1);
1669 EM_ASSERT_FAULT_RETURN(pParam1 == (RTRCPTR)pvFault, VERR_EM_INTERPRETER);
1670 break;
1671
1672 default:
1673 return VERR_EM_INTERPRETER;
1674 }
1675
1676 LogFlow(("%s %RRv=%08x eax=%08x\n", emGetMnemonic(pDISState), pParam1, pRegFrame->eax));
1677
1678 MMGCRamRegisterTrapHandler(pVM);
1679 if (pDISState->prefix & PREFIX_LOCK)
1680 rc = EMGCEmulateLockCmpXchg8b(pParam1, &pRegFrame->eax, &pRegFrame->edx, pRegFrame->ebx, pRegFrame->ecx, &eflags);
1681 else
1682 rc = EMGCEmulateCmpXchg8b(pParam1, &pRegFrame->eax, &pRegFrame->edx, pRegFrame->ebx, pRegFrame->ecx, &eflags);
1683 MMGCRamDeregisterTrapHandler(pVM);
1684
1685 if (RT_FAILURE(rc))
1686 {
1687 Log(("%s %RGv=%08x eax=%08x -> emulation failed due to page fault!\n", emGetMnemonic(pDISState), pParam1, pRegFrame->eax));
1688 return VERR_EM_INTERPRETER;
1689 }
1690
1691 LogFlow(("%s %RGv=%08x eax=%08x ZF=%d\n", emGetMnemonic(pDISState), pParam1, pRegFrame->eax, !!(eflags & X86_EFL_ZF)));
1692
1693 /* Update guest's eflags and finish; note that *only* ZF is affected. */
1694 pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_ZF))
1695 | (eflags & (X86_EFL_ZF));
1696
1697 *pcbSize = 8;
1698 return VINF_SUCCESS;
1699 }
1700 }
1701 return VERR_EM_INTERPRETER;
1702}
1703
1704#endif /* IN_RC */
1705
1706#ifdef IN_RC
1707/**
1708 * [LOCK] XADD emulation.
1709 */
1710static int emInterpretXAdd(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
1711{
1712 Assert(pDISState->mode != CPUMODE_64BIT); /** @todo check */
1713 OP_PARAMVAL param1;
1714 uint32_t *pParamReg2;
1715 size_t cbSizeParamReg2;
1716
1717 /* Source to make DISQueryParamVal read the register value - ugly hack */
1718 int rc = DISQueryParamVal(pRegFrame, pDISState, &pDISState->param1, &param1, PARAM_SOURCE);
1719 if(RT_FAILURE(rc))
1720 return VERR_EM_INTERPRETER;
1721
1722 rc = DISQueryParamRegPtr(pRegFrame, pDISState, &pDISState->param2, (void **)&pParamReg2, &cbSizeParamReg2);
1723 Assert(cbSizeParamReg2 <= 4);
1724 if(RT_FAILURE(rc))
1725 return VERR_EM_INTERPRETER;
1726
1727 if (TRPMHasTrap(pVCpu))
1728 {
1729 if (TRPMGetErrorCode(pVCpu) & X86_TRAP_PF_RW)
1730 {
1731 RTRCPTR pParam1;
1732 uint32_t eflags;
1733
1734 AssertReturn(pDISState->param1.size == pDISState->param2.size, VERR_EM_INTERPRETER);
1735 switch(param1.type)
1736 {
1737 case PARMTYPE_ADDRESS:
1738 pParam1 = (RTRCPTR)param1.val.val64;
1739 pParam1 = (RTRCPTR)emConvertToFlatAddr(pVM, pRegFrame, pDISState, &pDISState->param1, (RTGCPTR)(RTRCUINTPTR)pParam1);
1740 EM_ASSERT_FAULT_RETURN(pParam1 == (RTRCPTR)pvFault, VERR_EM_INTERPRETER);
1741 break;
1742
1743 default:
1744 return VERR_EM_INTERPRETER;
1745 }
1746
1747 LogFlow(("XAdd %RRv=%08x reg=%08x\n", pParam1, *pParamReg2));
1748
1749 MMGCRamRegisterTrapHandler(pVM);
1750 if (pDISState->prefix & PREFIX_LOCK)
1751 rc = EMGCEmulateLockXAdd(pParam1, pParamReg2, cbSizeParamReg2, &eflags);
1752 else
1753 rc = EMGCEmulateXAdd(pParam1, pParamReg2, cbSizeParamReg2, &eflags);
1754 MMGCRamDeregisterTrapHandler(pVM);
1755
1756 if (RT_FAILURE(rc))
1757 {
1758 Log(("XAdd %RGv reg=%08x -> emulation failed due to page fault!\n", pParam1, *pParamReg2));
1759 return VERR_EM_INTERPRETER;
1760 }
1761
1762 LogFlow(("XAdd %RGv reg=%08x ZF=%d\n", pParam1, *pParamReg2, !!(eflags & X86_EFL_ZF)));
1763
1764 /* Update guest's eflags and finish. */
1765 pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
1766 | (eflags & (X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF));
1767
1768 *pcbSize = cbSizeParamReg2;
1769 return VINF_SUCCESS;
1770 }
1771 }
1772 return VERR_EM_INTERPRETER;
1773}
1774#endif /* IN_RC */
1775
1776
1777#ifdef IN_RC
1778/**
1779 * Interpret IRET (currently only to V86 code)
1780 *
1781 * @returns VBox status code.
1782 * @param pVM The VM handle.
1783 * @param pVCpu The VMCPU handle.
1784 * @param pRegFrame The register frame.
1785 *
1786 */
1787VMMDECL(int) EMInterpretIret(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame)
1788{
1789 RTGCUINTPTR pIretStack = (RTGCUINTPTR)pRegFrame->esp;
1790 RTGCUINTPTR eip, cs, esp, ss, eflags, ds, es, fs, gs, uMask;
1791 int rc;
1792
1793 Assert(!CPUMIsGuestIn64BitCode(pVCpu, pRegFrame));
1794
1795 rc = emRamRead(pVM, pVCpu, pRegFrame, &eip, (RTGCPTR)pIretStack , 4);
1796 rc |= emRamRead(pVM, pVCpu, pRegFrame, &cs, (RTGCPTR)(pIretStack + 4), 4);
1797 rc |= emRamRead(pVM, pVCpu, pRegFrame, &eflags, (RTGCPTR)(pIretStack + 8), 4);
1798 AssertRCReturn(rc, VERR_EM_INTERPRETER);
1799 AssertReturn(eflags & X86_EFL_VM, VERR_EM_INTERPRETER);
1800
1801 rc |= emRamRead(pVM, pVCpu, pRegFrame, &esp, (RTGCPTR)(pIretStack + 12), 4);
1802 rc |= emRamRead(pVM, pVCpu, pRegFrame, &ss, (RTGCPTR)(pIretStack + 16), 4);
1803 rc |= emRamRead(pVM, pVCpu, pRegFrame, &es, (RTGCPTR)(pIretStack + 20), 4);
1804 rc |= emRamRead(pVM, pVCpu, pRegFrame, &ds, (RTGCPTR)(pIretStack + 24), 4);
1805 rc |= emRamRead(pVM, pVCpu, pRegFrame, &fs, (RTGCPTR)(pIretStack + 28), 4);
1806 rc |= emRamRead(pVM, pVCpu, pRegFrame, &gs, (RTGCPTR)(pIretStack + 32), 4);
1807 AssertRCReturn(rc, VERR_EM_INTERPRETER);
1808
1809 pRegFrame->eip = eip & 0xffff;
1810 pRegFrame->cs = cs;
1811
1812 /* Mask away all reserved bits */
1813 uMask = X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_TF | X86_EFL_IF | X86_EFL_DF | X86_EFL_OF | X86_EFL_IOPL | X86_EFL_NT | X86_EFL_RF | X86_EFL_VM | X86_EFL_AC | X86_EFL_VIF | X86_EFL_VIP | X86_EFL_ID;
1814 eflags &= uMask;
1815
1816#ifndef IN_RING0
1817 CPUMRawSetEFlags(pVCpu, pRegFrame, eflags);
1818#endif
1819 Assert((pRegFrame->eflags.u32 & (X86_EFL_IF|X86_EFL_IOPL)) == X86_EFL_IF);
1820
1821 pRegFrame->esp = esp;
1822 pRegFrame->ss = ss;
1823 pRegFrame->ds = ds;
1824 pRegFrame->es = es;
1825 pRegFrame->fs = fs;
1826 pRegFrame->gs = gs;
1827
1828 return VINF_SUCCESS;
1829}
1830#endif /* IN_RC */
1831
1832
1833/**
1834 * IRET Emulation.
1835 */
1836static int emInterpretIret(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
1837{
1838 /* only allow direct calls to EMInterpretIret for now */
1839 return VERR_EM_INTERPRETER;
1840}
1841
1842/**
1843 * WBINVD Emulation.
1844 */
1845static int emInterpretWbInvd(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
1846{
1847 /* Nothing to do. */
1848 return VINF_SUCCESS;
1849}
1850
1851
1852/**
1853 * Interpret INVLPG
1854 *
1855 * @returns VBox status code.
1856 * @param pVM The VM handle.
1857 * @param pVCpu The VMCPU handle.
1858 * @param pRegFrame The register frame.
1859 * @param pAddrGC Operand address
1860 *
1861 */
1862VMMDECL(int) EMInterpretInvlpg(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pAddrGC)
1863{
1864 int rc;
1865
1866 /** @todo is addr always a flat linear address or ds based
1867 * (in absence of segment override prefixes)????
1868 */
1869#ifdef IN_RC
1870 LogFlow(("RC: EMULATE: invlpg %RGv\n", pAddrGC));
1871#endif
1872 rc = PGMInvalidatePage(pVCpu, pAddrGC);
1873 if ( rc == VINF_SUCCESS
1874 || rc == VINF_PGM_SYNC_CR3 /* we can rely on the FF */)
1875 return VINF_SUCCESS;
1876 AssertMsgReturn( rc == VERR_REM_FLUSHED_PAGES_OVERFLOW
1877 || rc == VINF_EM_RAW_EMULATE_INSTR,
1878 ("%Rrc addr=%RGv\n", rc, pAddrGC),
1879 VERR_EM_INTERPRETER);
1880 return rc;
1881}
1882
1883
1884/**
1885 * INVLPG Emulation.
1886 */
1887static int emInterpretInvlPg(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
1888{
1889 OP_PARAMVAL param1;
1890 RTGCPTR addr;
1891
1892 int rc = DISQueryParamVal(pRegFrame, pDISState, &pDISState->param1, &param1, PARAM_SOURCE);
1893 if(RT_FAILURE(rc))
1894 return VERR_EM_INTERPRETER;
1895
1896 switch(param1.type)
1897 {
1898 case PARMTYPE_IMMEDIATE:
1899 case PARMTYPE_ADDRESS:
1900 if(!(param1.flags & (PARAM_VAL32|PARAM_VAL64)))
1901 return VERR_EM_INTERPRETER;
1902 addr = (RTGCPTR)param1.val.val64;
1903 break;
1904
1905 default:
1906 return VERR_EM_INTERPRETER;
1907 }
1908
1909 /** @todo is addr always a flat linear address or ds based
1910 * (in absence of segment override prefixes)????
1911 */
1912#ifdef IN_RC
1913 LogFlow(("RC: EMULATE: invlpg %RGv\n", addr));
1914#endif
1915 rc = PGMInvalidatePage(pVCpu, addr);
1916 if ( rc == VINF_SUCCESS
1917 || rc == VINF_PGM_SYNC_CR3 /* we can rely on the FF */)
1918 return VINF_SUCCESS;
1919 AssertMsgReturn( rc == VERR_REM_FLUSHED_PAGES_OVERFLOW
1920 || rc == VINF_EM_RAW_EMULATE_INSTR,
1921 ("%Rrc addr=%RGv\n", rc, addr),
1922 VERR_EM_INTERPRETER);
1923 return rc;
1924}
1925
1926
1927/**
1928 * Interpret CPUID given the parameters in the CPU context
1929 *
1930 * @returns VBox status code.
1931 * @param pVM The VM handle.
1932 * @param pVCpu The VMCPU handle.
1933 * @param pRegFrame The register frame.
1934 *
1935 */
1936VMMDECL(int) EMInterpretCpuId(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame)
1937{
1938 uint32_t iLeaf = pRegFrame->eax;
1939
1940 /* cpuid clears the high dwords of the affected 64 bits registers. */
1941 pRegFrame->rax = 0;
1942 pRegFrame->rbx = 0;
1943 pRegFrame->rcx = 0;
1944 pRegFrame->rdx = 0;
1945
1946 /* Note: operates the same in 64 and non-64 bits mode. */
1947 CPUMGetGuestCpuId(pVCpu, iLeaf, &pRegFrame->eax, &pRegFrame->ebx, &pRegFrame->ecx, &pRegFrame->edx);
1948 Log(("Emulate: CPUID %x -> %08x %08x %08x %08x\n", iLeaf, pRegFrame->eax, pRegFrame->ebx, pRegFrame->ecx, pRegFrame->edx));
1949 return VINF_SUCCESS;
1950}
1951
1952
1953/**
1954 * CPUID Emulation.
1955 */
1956static int emInterpretCpuId(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
1957{
1958 int rc = EMInterpretCpuId(pVM, pVCpu, pRegFrame);
1959 return rc;
1960}
1961
1962
1963/**
1964 * Interpret CRx read
1965 *
1966 * @returns VBox status code.
1967 * @param pVM The VM handle.
1968 * @param pVCpu The VMCPU handle.
1969 * @param pRegFrame The register frame.
1970 * @param DestRegGen General purpose register index (USE_REG_E**))
1971 * @param SrcRegCRx CRx register index (USE_REG_CR*)
1972 *
1973 */
1974VMMDECL(int) EMInterpretCRxRead(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t DestRegGen, uint32_t SrcRegCrx)
1975{
1976 int rc;
1977 uint64_t val64;
1978
1979 if (SrcRegCrx == USE_REG_CR8)
1980 {
1981 val64 = 0;
1982 rc = PDMApicGetTPR(pVM, (uint8_t *)&val64, NULL);
1983 AssertMsgRCReturn(rc, ("PDMApicGetTPR failed\n"), VERR_EM_INTERPRETER);
1984 }
1985 else
1986 {
1987 rc = CPUMGetGuestCRx(pVCpu, SrcRegCrx, &val64);
1988 AssertMsgRCReturn(rc, ("CPUMGetGuestCRx %d failed\n", SrcRegCrx), VERR_EM_INTERPRETER);
1989 }
1990
1991 if (CPUMIsGuestIn64BitCode(pVCpu, pRegFrame))
1992 rc = DISWriteReg64(pRegFrame, DestRegGen, val64);
1993 else
1994 rc = DISWriteReg32(pRegFrame, DestRegGen, val64);
1995
1996 if(RT_SUCCESS(rc))
1997 {
1998 LogFlow(("MOV_CR: gen32=%d CR=%d val=%RX64\n", DestRegGen, SrcRegCrx, val64));
1999 return VINF_SUCCESS;
2000 }
2001 return VERR_EM_INTERPRETER;
2002}
2003
2004
2005
2006/**
2007 * Interpret CLTS
2008 *
2009 * @returns VBox status code.
2010 * @param pVM The VM handle.
2011 * @param pVCpu The VMCPU handle.
2012 *
2013 */
2014VMMDECL(int) EMInterpretCLTS(PVM pVM, PVMCPU pVCpu)
2015{
2016 uint64_t cr0 = CPUMGetGuestCR0(pVCpu);
2017 if (!(cr0 & X86_CR0_TS))
2018 return VINF_SUCCESS;
2019 return CPUMSetGuestCR0(pVCpu, cr0 & ~X86_CR0_TS);
2020}
2021
2022/**
2023 * CLTS Emulation.
2024 */
2025static int emInterpretClts(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
2026{
2027 return EMInterpretCLTS(pVM, pVCpu);
2028}
2029
2030
2031/**
2032 * Update CRx
2033 *
2034 * @returns VBox status code.
2035 * @param pVM The VM handle.
2036 * @param pVCpu The VMCPU handle.
2037 * @param pRegFrame The register frame.
2038 * @param DestRegCRx CRx register index (USE_REG_CR*)
2039 * @param val New CRx value
2040 *
2041 */
2042static int emUpdateCRx(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t DestRegCrx, uint64_t val)
2043{
2044 uint64_t oldval;
2045 uint64_t msrEFER;
2046 int rc, rc2;
2047
2048 /** @todo Clean up this mess. */
2049 LogFlow(("EMInterpretCRxWrite at %RGv CR%d <- %RX64\n", (RTGCPTR)pRegFrame->rip, DestRegCrx, val));
2050 switch (DestRegCrx)
2051 {
2052 case USE_REG_CR0:
2053 oldval = CPUMGetGuestCR0(pVCpu);
2054#ifdef IN_RC
2055 /* CR0.WP and CR0.AM changes require a reschedule run in ring 3. */
2056 if ( (val & (X86_CR0_WP | X86_CR0_AM))
2057 != (oldval & (X86_CR0_WP | X86_CR0_AM)))
2058 return VERR_EM_INTERPRETER;
2059#endif
2060 rc = VINF_SUCCESS;
2061 CPUMSetGuestCR0(pVCpu, val);
2062 val = CPUMGetGuestCR0(pVCpu);
2063 if ( (oldval & (X86_CR0_PG | X86_CR0_WP | X86_CR0_PE))
2064 != (val & (X86_CR0_PG | X86_CR0_WP | X86_CR0_PE)))
2065 {
2066 /* global flush */
2067 rc = PGMFlushTLB(pVCpu, CPUMGetGuestCR3(pVCpu), true /* global */);
2068 AssertRCReturn(rc, rc);
2069 }
2070
2071 /* Deal with long mode enabling/disabling. */
2072 msrEFER = CPUMGetGuestEFER(pVCpu);
2073 if (msrEFER & MSR_K6_EFER_LME)
2074 {
2075 if ( !(oldval & X86_CR0_PG)
2076 && (val & X86_CR0_PG))
2077 {
2078 /* Illegal to have an active 64 bits CS selector (AMD Arch. Programmer's Manual Volume 2: Table 14-5) */
2079 if (pRegFrame->csHid.Attr.n.u1Long)
2080 {
2081 AssertMsgFailed(("Illegal enabling of paging with CS.u1Long = 1!!\n"));
2082 return VERR_EM_INTERPRETER; /* @todo generate #GP(0) */
2083 }
2084
2085 /* Illegal to switch to long mode before activating PAE first (AMD Arch. Programmer's Manual Volume 2: Table 14-5) */
2086 if (!(CPUMGetGuestCR4(pVCpu) & X86_CR4_PAE))
2087 {
2088 AssertMsgFailed(("Illegal enabling of paging with PAE disabled!!\n"));
2089 return VERR_EM_INTERPRETER; /* @todo generate #GP(0) */
2090 }
2091 msrEFER |= MSR_K6_EFER_LMA;
2092 }
2093 else
2094 if ( (oldval & X86_CR0_PG)
2095 && !(val & X86_CR0_PG))
2096 {
2097 msrEFER &= ~MSR_K6_EFER_LMA;
2098 /* @todo Do we need to cut off rip here? High dword of rip is undefined, so it shouldn't really matter. */
2099 }
2100 CPUMSetGuestEFER(pVCpu, msrEFER);
2101 }
2102 rc2 = PGMChangeMode(pVCpu, CPUMGetGuestCR0(pVCpu), CPUMGetGuestCR4(pVCpu), CPUMGetGuestEFER(pVCpu));
2103 return rc2 == VINF_SUCCESS ? rc : rc2;
2104
2105 case USE_REG_CR2:
2106 rc = CPUMSetGuestCR2(pVCpu, val); AssertRC(rc);
2107 return VINF_SUCCESS;
2108
2109 case USE_REG_CR3:
2110 /* Reloading the current CR3 means the guest just wants to flush the TLBs */
2111 rc = CPUMSetGuestCR3(pVCpu, val); AssertRC(rc);
2112 if (CPUMGetGuestCR0(pVCpu) & X86_CR0_PG)
2113 {
2114 /* flush */
2115 rc = PGMFlushTLB(pVCpu, val, !(CPUMGetGuestCR4(pVCpu) & X86_CR4_PGE));
2116 AssertRCReturn(rc, rc);
2117 }
2118 return rc;
2119
2120 case USE_REG_CR4:
2121 oldval = CPUMGetGuestCR4(pVCpu);
2122 rc = CPUMSetGuestCR4(pVCpu, val); AssertRC(rc);
2123 val = CPUMGetGuestCR4(pVCpu);
2124
2125 /* Illegal to disable PAE when long mode is active. (AMD Arch. Programmer's Manual Volume 2: Table 14-5) */
2126 msrEFER = CPUMGetGuestEFER(pVCpu);
2127 if ( (msrEFER & MSR_K6_EFER_LMA)
2128 && (oldval & X86_CR4_PAE)
2129 && !(val & X86_CR4_PAE))
2130 {
2131 return VERR_EM_INTERPRETER; /** @todo generate #GP(0) */
2132 }
2133
2134 rc = VINF_SUCCESS;
2135 if ( (oldval & (X86_CR4_PGE|X86_CR4_PAE|X86_CR4_PSE))
2136 != (val & (X86_CR4_PGE|X86_CR4_PAE|X86_CR4_PSE)))
2137 {
2138 /* global flush */
2139 rc = PGMFlushTLB(pVCpu, CPUMGetGuestCR3(pVCpu), true /* global */);
2140 AssertRCReturn(rc, rc);
2141 }
2142
2143 /* Feeling extremely lazy. */
2144# ifdef IN_RC
2145 if ( (oldval & (X86_CR4_OSFSXR|X86_CR4_OSXMMEEXCPT|X86_CR4_PCE|X86_CR4_MCE|X86_CR4_PAE|X86_CR4_DE|X86_CR4_TSD|X86_CR4_PVI|X86_CR4_VME))
2146 != (val & (X86_CR4_OSFSXR|X86_CR4_OSXMMEEXCPT|X86_CR4_PCE|X86_CR4_MCE|X86_CR4_PAE|X86_CR4_DE|X86_CR4_TSD|X86_CR4_PVI|X86_CR4_VME)))
2147 {
2148 Log(("emInterpretMovCRx: CR4: %#RX64->%#RX64 => R3\n", oldval, val));
2149 VMCPU_FF_SET(pVCpu, VMCPU_FF_TO_R3);
2150 }
2151# endif
2152 if ((val ^ oldval) & X86_CR4_VME)
2153 VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_TSS);
2154
2155 rc2 = PGMChangeMode(pVCpu, CPUMGetGuestCR0(pVCpu), CPUMGetGuestCR4(pVCpu), CPUMGetGuestEFER(pVCpu));
2156 return rc2 == VINF_SUCCESS ? rc : rc2;
2157
2158 case USE_REG_CR8:
2159 return PDMApicSetTPR(pVM, val);
2160
2161 default:
2162 AssertFailed();
2163 case USE_REG_CR1: /* illegal op */
2164 break;
2165 }
2166 return VERR_EM_INTERPRETER;
2167}
2168
2169/**
2170 * Interpret CRx write
2171 *
2172 * @returns VBox status code.
2173 * @param pVM The VM handle.
2174 * @param pVCpu The VMCPU handle.
2175 * @param pRegFrame The register frame.
2176 * @param DestRegCRx CRx register index (USE_REG_CR*)
2177 * @param SrcRegGen General purpose register index (USE_REG_E**))
2178 *
2179 */
2180VMMDECL(int) EMInterpretCRxWrite(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t DestRegCrx, uint32_t SrcRegGen)
2181{
2182 uint64_t val;
2183 int rc;
2184
2185 if (CPUMIsGuestIn64BitCode(pVCpu, pRegFrame))
2186 {
2187 rc = DISFetchReg64(pRegFrame, SrcRegGen, &val);
2188 }
2189 else
2190 {
2191 uint32_t val32;
2192 rc = DISFetchReg32(pRegFrame, SrcRegGen, &val32);
2193 val = val32;
2194 }
2195
2196 if (RT_SUCCESS(rc))
2197 return emUpdateCRx(pVM, pVCpu, pRegFrame, DestRegCrx, val);
2198
2199 return VERR_EM_INTERPRETER;
2200}
2201
2202/**
2203 * Interpret LMSW
2204 *
2205 * @returns VBox status code.
2206 * @param pVM The VM handle.
2207 * @param pVCpu The VMCPU handle.
2208 * @param pRegFrame The register frame.
2209 * @param u16Data LMSW source data.
2210 *
2211 */
2212VMMDECL(int) EMInterpretLMSW(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint16_t u16Data)
2213{
2214 uint64_t OldCr0 = CPUMGetGuestCR0(pVCpu);
2215
2216 /* Only PE, MP, EM and TS can be changed; note that PE can't be cleared by this instruction. */
2217 uint64_t NewCr0 = ( OldCr0 & ~( X86_CR0_MP | X86_CR0_EM | X86_CR0_TS))
2218 | (u16Data & (X86_CR0_PE | X86_CR0_MP | X86_CR0_EM | X86_CR0_TS));
2219
2220 return emUpdateCRx(pVM, pVCpu, pRegFrame, USE_REG_CR0, NewCr0);
2221}
2222
2223/**
2224 * LMSW Emulation.
2225 */
2226static int emInterpretLmsw(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
2227{
2228 OP_PARAMVAL param1;
2229 uint32_t val;
2230
2231 int rc = DISQueryParamVal(pRegFrame, pDISState, &pDISState->param1, &param1, PARAM_SOURCE);
2232 if(RT_FAILURE(rc))
2233 return VERR_EM_INTERPRETER;
2234
2235 switch(param1.type)
2236 {
2237 case PARMTYPE_IMMEDIATE:
2238 case PARMTYPE_ADDRESS:
2239 if(!(param1.flags & PARAM_VAL16))
2240 return VERR_EM_INTERPRETER;
2241 val = param1.val.val32;
2242 break;
2243
2244 default:
2245 return VERR_EM_INTERPRETER;
2246 }
2247
2248 LogFlow(("emInterpretLmsw %x\n", val));
2249 return EMInterpretLMSW(pVM, pVCpu, pRegFrame, val);
2250}
2251
2252#ifdef EM_EMULATE_SMSW
2253/**
2254 * SMSW Emulation.
2255 */
2256static int emInterpretSmsw(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
2257{
2258 OP_PARAMVAL param1;
2259 uint64_t cr0 = CPUMGetGuestCR0(pVCpu);
2260
2261 int rc = DISQueryParamVal(pRegFrame, pDISState, &pDISState->param1, &param1, PARAM_SOURCE);
2262 if(RT_FAILURE(rc))
2263 return VERR_EM_INTERPRETER;
2264
2265 switch(param1.type)
2266 {
2267 case PARMTYPE_IMMEDIATE:
2268 if(param1.size != sizeof(uint16_t))
2269 return VERR_EM_INTERPRETER;
2270 LogFlow(("emInterpretSmsw %d <- cr0 (%x)\n", pDISState->param1.base.reg_gen, cr0));
2271 rc = DISWriteReg16(pRegFrame, pDISState->param1.base.reg_gen, cr0);
2272 break;
2273
2274 case PARMTYPE_ADDRESS:
2275 {
2276 RTGCPTR pParam1;
2277
2278 /* Actually forced to 16 bits regardless of the operand size. */
2279 if(param1.size != sizeof(uint16_t))
2280 return VERR_EM_INTERPRETER;
2281
2282 pParam1 = (RTGCPTR)param1.val.val64;
2283 pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pDISState, &pDISState->param1, pParam1);
2284 LogFlow(("emInterpretSmsw %VGv <- cr0 (%x)\n", pParam1, cr0));
2285
2286 rc = emRamWrite(pVM, pVCpu, pRegFrame, pParam1, &cr0, sizeof(uint16_t));
2287 if (RT_FAILURE(rc))
2288 {
2289 AssertMsgFailed(("emRamWrite %RGv size=%d failed with %Rrc\n", pParam1, param1.size, rc));
2290 return VERR_EM_INTERPRETER;
2291 }
2292 break;
2293 }
2294
2295 default:
2296 return VERR_EM_INTERPRETER;
2297 }
2298
2299 LogFlow(("emInterpretSmsw %x\n", cr0));
2300 return rc;
2301}
2302#endif
2303
2304/**
2305 * MOV CRx
2306 */
2307static int emInterpretMovCRx(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
2308{
2309 if ((pDISState->param1.flags == USE_REG_GEN32 || pDISState->param1.flags == USE_REG_GEN64) && pDISState->param2.flags == USE_REG_CR)
2310 return EMInterpretCRxRead(pVM, pVCpu, pRegFrame, pDISState->param1.base.reg_gen, pDISState->param2.base.reg_ctrl);
2311
2312 if (pDISState->param1.flags == USE_REG_CR && (pDISState->param2.flags == USE_REG_GEN32 || pDISState->param2.flags == USE_REG_GEN64))
2313 return EMInterpretCRxWrite(pVM, pVCpu, pRegFrame, pDISState->param1.base.reg_ctrl, pDISState->param2.base.reg_gen);
2314
2315 AssertMsgFailedReturn(("Unexpected control register move\n"), VERR_EM_INTERPRETER);
2316 return VERR_EM_INTERPRETER;
2317}
2318
2319
2320/**
2321 * Interpret DRx write
2322 *
2323 * @returns VBox status code.
2324 * @param pVM The VM handle.
2325 * @param pVCpu The VMCPU handle.
2326 * @param pRegFrame The register frame.
2327 * @param DestRegDRx DRx register index (USE_REG_DR*)
2328 * @param SrcRegGen General purpose register index (USE_REG_E**))
2329 *
2330 */
2331VMMDECL(int) EMInterpretDRxWrite(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t DestRegDrx, uint32_t SrcRegGen)
2332{
2333 uint64_t val;
2334 int rc;
2335
2336 if (CPUMIsGuestIn64BitCode(pVCpu, pRegFrame))
2337 {
2338 rc = DISFetchReg64(pRegFrame, SrcRegGen, &val);
2339 }
2340 else
2341 {
2342 uint32_t val32;
2343 rc = DISFetchReg32(pRegFrame, SrcRegGen, &val32);
2344 val = val32;
2345 }
2346
2347 if (RT_SUCCESS(rc))
2348 {
2349 /** @todo we don't fail if illegal bits are set/cleared for e.g. dr7 */
2350 rc = CPUMSetGuestDRx(pVCpu, DestRegDrx, val);
2351 if (RT_SUCCESS(rc))
2352 return rc;
2353 AssertMsgFailed(("CPUMSetGuestDRx %d failed\n", DestRegDrx));
2354 }
2355 return VERR_EM_INTERPRETER;
2356}
2357
2358
2359/**
2360 * Interpret DRx read
2361 *
2362 * @returns VBox status code.
2363 * @param pVM The VM handle.
2364 * @param pVCpu The VMCPU handle.
2365 * @param pRegFrame The register frame.
2366 * @param DestRegGen General purpose register index (USE_REG_E**))
2367 * @param SrcRegDRx DRx register index (USE_REG_DR*)
2368 *
2369 */
2370VMMDECL(int) EMInterpretDRxRead(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t DestRegGen, uint32_t SrcRegDrx)
2371{
2372 uint64_t val64;
2373
2374 int rc = CPUMGetGuestDRx(pVCpu, SrcRegDrx, &val64);
2375 AssertMsgRCReturn(rc, ("CPUMGetGuestDRx %d failed\n", SrcRegDrx), VERR_EM_INTERPRETER);
2376 if (CPUMIsGuestIn64BitCode(pVCpu, pRegFrame))
2377 {
2378 rc = DISWriteReg64(pRegFrame, DestRegGen, val64);
2379 }
2380 else
2381 rc = DISWriteReg32(pRegFrame, DestRegGen, (uint32_t)val64);
2382
2383 if (RT_SUCCESS(rc))
2384 return VINF_SUCCESS;
2385
2386 return VERR_EM_INTERPRETER;
2387}
2388
2389
2390/**
2391 * MOV DRx
2392 */
2393static int emInterpretMovDRx(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
2394{
2395 int rc = VERR_EM_INTERPRETER;
2396
2397 if((pDISState->param1.flags == USE_REG_GEN32 || pDISState->param1.flags == USE_REG_GEN64) && pDISState->param2.flags == USE_REG_DBG)
2398 {
2399 rc = EMInterpretDRxRead(pVM, pVCpu, pRegFrame, pDISState->param1.base.reg_gen, pDISState->param2.base.reg_dbg);
2400 }
2401 else
2402 if(pDISState->param1.flags == USE_REG_DBG && (pDISState->param2.flags == USE_REG_GEN32 || pDISState->param2.flags == USE_REG_GEN64))
2403 {
2404 rc = EMInterpretDRxWrite(pVM, pVCpu, pRegFrame, pDISState->param1.base.reg_dbg, pDISState->param2.base.reg_gen);
2405 }
2406 else
2407 AssertMsgFailed(("Unexpected debug register move\n"));
2408
2409 return rc;
2410}
2411
2412
2413/**
2414 * LLDT Emulation.
2415 */
2416static int emInterpretLLdt(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
2417{
2418 OP_PARAMVAL param1;
2419 RTSEL sel;
2420
2421 int rc = DISQueryParamVal(pRegFrame, pDISState, &pDISState->param1, &param1, PARAM_SOURCE);
2422 if(RT_FAILURE(rc))
2423 return VERR_EM_INTERPRETER;
2424
2425 switch(param1.type)
2426 {
2427 case PARMTYPE_ADDRESS:
2428 return VERR_EM_INTERPRETER; //feeling lazy right now
2429
2430 case PARMTYPE_IMMEDIATE:
2431 if(!(param1.flags & PARAM_VAL16))
2432 return VERR_EM_INTERPRETER;
2433 sel = (RTSEL)param1.val.val16;
2434 break;
2435
2436 default:
2437 return VERR_EM_INTERPRETER;
2438 }
2439
2440#ifdef IN_RING0
2441 /* Only for the VT-x real-mode emulation case. */
2442 AssertReturn(CPUMIsGuestInRealMode(pVCpu), VERR_EM_INTERPRETER);
2443 CPUMSetGuestLDTR(pVCpu, sel);
2444 return VINF_SUCCESS;
2445#else
2446 if (sel == 0)
2447 {
2448 if (CPUMGetHyperLDTR(pVCpu) == 0)
2449 {
2450 // this simple case is most frequent in Windows 2000 (31k - boot & shutdown)
2451 return VINF_SUCCESS;
2452 }
2453 }
2454 //still feeling lazy
2455 return VERR_EM_INTERPRETER;
2456#endif
2457}
2458
2459#ifdef IN_RING0
2460/**
2461 * LIDT/LGDT Emulation.
2462 */
2463static int emInterpretLIGdt(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
2464{
2465 OP_PARAMVAL param1;
2466 RTGCPTR pParam1;
2467 X86XDTR32 dtr32;
2468
2469 Log(("Emulate %s at %RGv\n", emGetMnemonic(pDISState), (RTGCPTR)pRegFrame->rip));
2470
2471 /* Only for the VT-x real-mode emulation case. */
2472 AssertReturn(CPUMIsGuestInRealMode(pVCpu), VERR_EM_INTERPRETER);
2473
2474 int rc = DISQueryParamVal(pRegFrame, pDISState, &pDISState->param1, &param1, PARAM_SOURCE);
2475 if(RT_FAILURE(rc))
2476 return VERR_EM_INTERPRETER;
2477
2478 switch(param1.type)
2479 {
2480 case PARMTYPE_ADDRESS:
2481 pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pDISState, &pDISState->param1, param1.val.val16);
2482 break;
2483
2484 default:
2485 return VERR_EM_INTERPRETER;
2486 }
2487
2488 rc = emRamRead(pVM, pVCpu, pRegFrame, &dtr32, pParam1, sizeof(dtr32));
2489 AssertRCReturn(rc, VERR_EM_INTERPRETER);
2490
2491 if (!(pDISState->prefix & PREFIX_OPSIZE))
2492 dtr32.uAddr &= 0xffffff; /* 16 bits operand size */
2493
2494 if (pDISState->pCurInstr->opcode == OP_LIDT)
2495 CPUMSetGuestIDTR(pVCpu, dtr32.uAddr, dtr32.cb);
2496 else
2497 CPUMSetGuestGDTR(pVCpu, dtr32.uAddr, dtr32.cb);
2498
2499 return VINF_SUCCESS;
2500}
2501#endif
2502
2503
2504#ifdef IN_RC
2505/**
2506 * STI Emulation.
2507 *
2508 * @remark the instruction following sti is guaranteed to be executed before any interrupts are dispatched
2509 */
2510static int emInterpretSti(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
2511{
2512 PPATMGCSTATE pGCState = PATMQueryGCState(pVM);
2513
2514 if(!pGCState)
2515 {
2516 Assert(pGCState);
2517 return VERR_EM_INTERPRETER;
2518 }
2519 pGCState->uVMFlags |= X86_EFL_IF;
2520
2521 Assert(pRegFrame->eflags.u32 & X86_EFL_IF);
2522 Assert(pvFault == SELMToFlat(pVM, DIS_SELREG_CS, pRegFrame, (RTGCPTR)pRegFrame->rip));
2523
2524 pVCpu->em.s.GCPtrInhibitInterrupts = pRegFrame->eip + pDISState->opsize;
2525 VMCPU_FF_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
2526
2527 return VINF_SUCCESS;
2528}
2529#endif /* IN_RC */
2530
2531
2532/**
2533 * HLT Emulation.
2534 */
2535static int emInterpretHlt(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
2536{
2537 return VINF_EM_HALT;
2538}
2539
2540
2541/**
2542 * Interpret RDTSC
2543 *
2544 * @returns VBox status code.
2545 * @param pVM The VM handle.
2546 * @param pVCpu The VMCPU handle.
2547 * @param pRegFrame The register frame.
2548 *
2549 */
2550VMMDECL(int) EMInterpretRdtsc(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame)
2551{
2552 unsigned uCR4 = CPUMGetGuestCR4(pVCpu);
2553
2554 if (uCR4 & X86_CR4_TSD)
2555 return VERR_EM_INTERPRETER; /* genuine #GP */
2556
2557 uint64_t uTicks = TMCpuTickGet(pVCpu);
2558
2559 /* Same behaviour in 32 & 64 bits mode */
2560 pRegFrame->rax = (uint32_t)uTicks;
2561 pRegFrame->rdx = (uTicks >> 32ULL);
2562
2563 return VINF_SUCCESS;
2564}
2565
2566/**
2567 * Interpret RDTSCP
2568 *
2569 * @returns VBox status code.
2570 * @param pVM The VM handle.
2571 * @param pVCpu The VMCPU handle.
2572 * @param pCtx The CPU context.
2573 *
2574 */
2575VMMDECL(int) EMInterpretRdtscp(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx)
2576{
2577 unsigned uCR4 = CPUMGetGuestCR4(pVCpu);
2578
2579 if (!CPUMGetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_RDTSCP))
2580 {
2581 AssertFailed();
2582 return VERR_EM_INTERPRETER; /* genuine #UD */
2583 }
2584
2585 if (uCR4 & X86_CR4_TSD)
2586 return VERR_EM_INTERPRETER; /* genuine #GP */
2587
2588 uint64_t uTicks = TMCpuTickGet(pVCpu);
2589
2590 /* Same behaviour in 32 & 64 bits mode */
2591 pCtx->rax = (uint32_t)uTicks;
2592 pCtx->rdx = (uTicks >> 32ULL);
2593 /* Low dword of the TSC_AUX msr only. */
2594 pCtx->rcx = (uint32_t)CPUMGetGuestMsr(pVCpu, MSR_K8_TSC_AUX);
2595
2596 return VINF_SUCCESS;
2597}
2598
2599/**
2600 * RDTSC Emulation.
2601 */
2602static int emInterpretRdtsc(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
2603{
2604 return EMInterpretRdtsc(pVM, pVCpu, pRegFrame);
2605}
2606
2607/**
2608 * Interpret RDPMC
2609 *
2610 * @returns VBox status code.
2611 * @param pVM The VM handle.
2612 * @param pVCpu The VMCPU handle.
2613 * @param pRegFrame The register frame.
2614 *
2615 */
2616VMMDECL(int) EMInterpretRdpmc(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame)
2617{
2618 unsigned uCR4 = CPUMGetGuestCR4(pVCpu);
2619
2620 /* If X86_CR4_PCE is not set, then CPL must be zero. */
2621 if ( !(uCR4 & X86_CR4_PCE)
2622 && CPUMGetGuestCPL(pVCpu, pRegFrame) != 0)
2623 {
2624 Assert(CPUMGetGuestCR0(pVCpu) & X86_CR0_PE);
2625 return VERR_EM_INTERPRETER; /* genuine #GP */
2626 }
2627
2628 /* Just return zero here; rather tricky to properly emulate this, especially as the specs are a mess. */
2629 pRegFrame->rax = 0;
2630 pRegFrame->rdx = 0;
2631 /* @todo We should trigger a #GP here if the cpu doesn't support the index in ecx. */
2632 return VINF_SUCCESS;
2633}
2634
2635/**
2636 * RDPMC Emulation
2637 */
2638static int emInterpretRdpmc(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
2639{
2640 return EMInterpretRdpmc(pVM, pVCpu, pRegFrame);
2641}
2642
2643/**
2644 * MONITOR Emulation.
2645 */
2646static int emInterpretMonitor(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
2647{
2648 uint32_t u32Dummy, u32ExtFeatures, cpl;
2649
2650 Assert(pDISState->mode != CPUMODE_64BIT); /** @todo check */
2651 if (pRegFrame->ecx != 0)
2652 return VERR_EM_INTERPRETER; /* illegal value. */
2653
2654 /* Get the current privilege level. */
2655 cpl = CPUMGetGuestCPL(pVCpu, pRegFrame);
2656 if (cpl != 0)
2657 return VERR_EM_INTERPRETER; /* supervisor only */
2658
2659 CPUMGetGuestCpuId(pVCpu, 1, &u32Dummy, &u32Dummy, &u32ExtFeatures, &u32Dummy);
2660 if (!(u32ExtFeatures & X86_CPUID_FEATURE_ECX_MONITOR))
2661 return VERR_EM_INTERPRETER; /* not supported */
2662
2663 return VINF_SUCCESS;
2664}
2665
2666
2667/**
2668 * MWAIT Emulation.
2669 */
2670static int emInterpretMWait(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
2671{
2672 uint32_t u32Dummy, u32ExtFeatures, cpl;
2673
2674 Assert(pDISState->mode != CPUMODE_64BIT); /** @todo check */
2675 if (pRegFrame->ecx != 0)
2676 return VERR_EM_INTERPRETER; /* illegal value. */
2677
2678 /* Get the current privilege level. */
2679 cpl = CPUMGetGuestCPL(pVCpu, pRegFrame);
2680 if (cpl != 0)
2681 return VERR_EM_INTERPRETER; /* supervisor only */
2682
2683 CPUMGetGuestCpuId(pVCpu, 1, &u32Dummy, &u32Dummy, &u32ExtFeatures, &u32Dummy);
2684 if (!(u32ExtFeatures & X86_CPUID_FEATURE_ECX_MONITOR))
2685 return VERR_EM_INTERPRETER; /* not supported */
2686
2687 /** @todo not completely correct */
2688 return VINF_EM_HALT;
2689}
2690
2691
2692#ifdef LOG_ENABLED
2693static const char *emMSRtoString(uint32_t uMsr)
2694{
2695 switch (uMsr)
2696 {
2697 case MSR_IA32_APICBASE:
2698 return "MSR_IA32_APICBASE";
2699 case MSR_IA32_CR_PAT:
2700 return "MSR_IA32_CR_PAT";
2701 case MSR_IA32_SYSENTER_CS:
2702 return "MSR_IA32_SYSENTER_CS";
2703 case MSR_IA32_SYSENTER_EIP:
2704 return "MSR_IA32_SYSENTER_EIP";
2705 case MSR_IA32_SYSENTER_ESP:
2706 return "MSR_IA32_SYSENTER_ESP";
2707 case MSR_K6_EFER:
2708 return "MSR_K6_EFER";
2709 case MSR_K8_SF_MASK:
2710 return "MSR_K8_SF_MASK";
2711 case MSR_K6_STAR:
2712 return "MSR_K6_STAR";
2713 case MSR_K8_LSTAR:
2714 return "MSR_K8_LSTAR";
2715 case MSR_K8_CSTAR:
2716 return "MSR_K8_CSTAR";
2717 case MSR_K8_FS_BASE:
2718 return "MSR_K8_FS_BASE";
2719 case MSR_K8_GS_BASE:
2720 return "MSR_K8_GS_BASE";
2721 case MSR_K8_KERNEL_GS_BASE:
2722 return "MSR_K8_KERNEL_GS_BASE";
2723 case MSR_K8_TSC_AUX:
2724 return "MSR_K8_TSC_AUX";
2725 case MSR_IA32_BIOS_SIGN_ID:
2726 return "Unsupported MSR_IA32_BIOS_SIGN_ID";
2727 case MSR_IA32_PLATFORM_ID:
2728 return "Unsupported MSR_IA32_PLATFORM_ID";
2729 case MSR_IA32_BIOS_UPDT_TRIG:
2730 return "Unsupported MSR_IA32_BIOS_UPDT_TRIG";
2731 case MSR_IA32_TSC:
2732 return "MSR_IA32_TSC";
2733 case MSR_IA32_MTRR_CAP:
2734 return "Unsupported MSR_IA32_MTRR_CAP";
2735 case MSR_IA32_MCP_CAP:
2736 return "Unsupported MSR_IA32_MCP_CAP";
2737 case MSR_IA32_MCP_STATUS:
2738 return "Unsupported MSR_IA32_MCP_STATUS";
2739 case MSR_IA32_MCP_CTRL:
2740 return "Unsupported MSR_IA32_MCP_CTRL";
2741 case MSR_IA32_MTRR_DEF_TYPE:
2742 return "Unsupported MSR_IA32_MTRR_DEF_TYPE";
2743 case MSR_K7_EVNTSEL0:
2744 return "Unsupported MSR_K7_EVNTSEL0";
2745 case MSR_K7_EVNTSEL1:
2746 return "Unsupported MSR_K7_EVNTSEL1";
2747 case MSR_K7_EVNTSEL2:
2748 return "Unsupported MSR_K7_EVNTSEL2";
2749 case MSR_K7_EVNTSEL3:
2750 return "Unsupported MSR_K7_EVNTSEL3";
2751 case MSR_IA32_MC0_CTL:
2752 return "Unsupported MSR_IA32_MC0_CTL";
2753 case MSR_IA32_MC0_STATUS:
2754 return "Unsupported MSR_IA32_MC0_STATUS";
2755 case MSR_IA32_PERFEVTSEL0:
2756 return "Unsupported MSR_IA32_PERFEVTSEL0";
2757 case MSR_IA32_PERFEVTSEL1:
2758 return "Unsupported MSR_IA32_PERFEVTSEL1";
2759 case MSR_IA32_PERF_STATUS:
2760 return "Unsupported MSR_IA32_PERF_STATUS";
2761 case MSR_IA32_PERF_CTL:
2762 return "Unsupported MSR_IA32_PERF_CTL";
2763 }
2764 return "Unknown MSR";
2765}
2766#endif /* LOG_ENABLED */
2767
2768
2769/**
2770 * Interpret RDMSR
2771 *
2772 * @returns VBox status code.
2773 * @param pVM The VM handle.
2774 * @param pVCpu The VMCPU handle.
2775 * @param pRegFrame The register frame.
2776 *
2777 */
2778VMMDECL(int) EMInterpretRdmsr(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame)
2779{
2780 uint32_t u32Dummy, u32Features, cpl;
2781 uint64_t val;
2782 CPUMCTX *pCtx;
2783 int rc = VINF_SUCCESS;
2784
2785 /** @todo According to the Intel manuals, there's a REX version of RDMSR that is slightly different.
2786 * That version clears the high dwords of both RDX & RAX */
2787 pCtx = CPUMQueryGuestCtxPtr(pVCpu);
2788
2789 /* Get the current privilege level. */
2790 cpl = CPUMGetGuestCPL(pVCpu, pRegFrame);
2791 if (cpl != 0)
2792 return VERR_EM_INTERPRETER; /* supervisor only */
2793
2794 CPUMGetGuestCpuId(pVCpu, 1, &u32Dummy, &u32Dummy, &u32Dummy, &u32Features);
2795 if (!(u32Features & X86_CPUID_FEATURE_EDX_MSR))
2796 return VERR_EM_INTERPRETER; /* not supported */
2797
2798 switch (pRegFrame->ecx)
2799 {
2800 case MSR_IA32_TSC:
2801 val = TMCpuTickGet(pVCpu);
2802 break;
2803
2804 case MSR_IA32_APICBASE:
2805 rc = PDMApicGetBase(pVM, &val);
2806 AssertRC(rc);
2807 break;
2808
2809 case MSR_IA32_CR_PAT:
2810 val = pCtx->msrPAT;
2811 break;
2812
2813 case MSR_IA32_SYSENTER_CS:
2814 val = pCtx->SysEnter.cs;
2815 break;
2816
2817 case MSR_IA32_SYSENTER_EIP:
2818 val = pCtx->SysEnter.eip;
2819 break;
2820
2821 case MSR_IA32_SYSENTER_ESP:
2822 val = pCtx->SysEnter.esp;
2823 break;
2824
2825 case MSR_K6_EFER:
2826 val = pCtx->msrEFER;
2827 break;
2828
2829 case MSR_K8_SF_MASK:
2830 val = pCtx->msrSFMASK;
2831 break;
2832
2833 case MSR_K6_STAR:
2834 val = pCtx->msrSTAR;
2835 break;
2836
2837 case MSR_K8_LSTAR:
2838 val = pCtx->msrLSTAR;
2839 break;
2840
2841 case MSR_K8_CSTAR:
2842 val = pCtx->msrCSTAR;
2843 break;
2844
2845 case MSR_K8_FS_BASE:
2846 val = pCtx->fsHid.u64Base;
2847 break;
2848
2849 case MSR_K8_GS_BASE:
2850 val = pCtx->gsHid.u64Base;
2851 break;
2852
2853 case MSR_K8_KERNEL_GS_BASE:
2854 val = pCtx->msrKERNELGSBASE;
2855 break;
2856
2857 case MSR_K8_TSC_AUX:
2858 val = CPUMGetGuestMsr(pVCpu, MSR_K8_TSC_AUX);
2859 break;
2860
2861#if 0 /*def IN_RING0 */
2862 case MSR_IA32_PLATFORM_ID:
2863 case MSR_IA32_BIOS_SIGN_ID:
2864 if (CPUMGetCPUVendor(pVM) == CPUMCPUVENDOR_INTEL)
2865 {
2866 /* Available since the P6 family. VT-x implies that this feature is present. */
2867 if (pRegFrame->ecx == MSR_IA32_PLATFORM_ID)
2868 val = ASMRdMsr(MSR_IA32_PLATFORM_ID);
2869 else
2870 if (pRegFrame->ecx == MSR_IA32_BIOS_SIGN_ID)
2871 val = ASMRdMsr(MSR_IA32_BIOS_SIGN_ID);
2872 break;
2873 }
2874 /* no break */
2875#endif
2876 default:
2877 /* In X2APIC specification this range is reserved for APIC control. */
2878 if ((pRegFrame->ecx >= MSR_IA32_APIC_START) && (pRegFrame->ecx < MSR_IA32_APIC_END))
2879 rc = PDMApicReadMSR(pVM, pVCpu->idCpu, pRegFrame->ecx, &val);
2880 else
2881 /* We should actually trigger a #GP here, but don't as that might cause more trouble. */
2882 val = 0;
2883 break;
2884 }
2885 LogFlow(("EMInterpretRdmsr %s (%x) -> val=%RX64\n", emMSRtoString(pRegFrame->ecx), pRegFrame->ecx, val));
2886 if (rc == VINF_SUCCESS)
2887 {
2888 pRegFrame->rax = (uint32_t) val;
2889 pRegFrame->rdx = (uint32_t) (val >> 32ULL);
2890 }
2891 return rc;
2892}
2893
2894
2895/**
2896 * RDMSR Emulation.
2897 */
2898static int emInterpretRdmsr(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
2899{
2900 /* Note: the Intel manual claims there's a REX version of RDMSR that's slightly different, so we play safe by completely disassembling the instruction. */
2901 Assert(!(pDISState->prefix & PREFIX_REX));
2902 return EMInterpretRdmsr(pVM, pVCpu, pRegFrame);
2903}
2904
2905
2906/**
2907 * Interpret WRMSR
2908 *
2909 * @returns VBox status code.
2910 * @param pVM The VM handle.
2911 * @param pVCpu The VMCPU handle.
2912 * @param pRegFrame The register frame.
2913 */
2914VMMDECL(int) EMInterpretWrmsr(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame)
2915{
2916 uint32_t u32Dummy, u32Features, cpl;
2917 uint64_t val;
2918 CPUMCTX *pCtx;
2919
2920 /* Note: works the same in 32 and 64 bits modes. */
2921 pCtx = CPUMQueryGuestCtxPtr(pVCpu);
2922
2923 /* Get the current privilege level. */
2924 cpl = CPUMGetGuestCPL(pVCpu, pRegFrame);
2925 if (cpl != 0)
2926 return VERR_EM_INTERPRETER; /* supervisor only */
2927
2928 CPUMGetGuestCpuId(pVCpu, 1, &u32Dummy, &u32Dummy, &u32Dummy, &u32Features);
2929 if (!(u32Features & X86_CPUID_FEATURE_EDX_MSR))
2930 return VERR_EM_INTERPRETER; /* not supported */
2931
2932 val = RT_MAKE_U64(pRegFrame->eax, pRegFrame->edx);
2933 LogFlow(("EMInterpretWrmsr %s (%x) val=%RX64\n", emMSRtoString(pRegFrame->ecx), pRegFrame->ecx, val));
2934 switch (pRegFrame->ecx)
2935 {
2936 case MSR_IA32_APICBASE:
2937 {
2938 int rc = PDMApicSetBase(pVM, val);
2939 AssertRC(rc);
2940 break;
2941 }
2942
2943 case MSR_IA32_CR_PAT:
2944 pCtx->msrPAT = val;
2945 break;
2946
2947 case MSR_IA32_SYSENTER_CS:
2948 pCtx->SysEnter.cs = val & 0xffff; /* 16 bits selector */
2949 break;
2950
2951 case MSR_IA32_SYSENTER_EIP:
2952 pCtx->SysEnter.eip = val;
2953 break;
2954
2955 case MSR_IA32_SYSENTER_ESP:
2956 pCtx->SysEnter.esp = val;
2957 break;
2958
2959 case MSR_K6_EFER:
2960 {
2961 uint64_t uMask = 0;
2962 uint64_t oldval = pCtx->msrEFER;
2963
2964 /* Filter out those bits the guest is allowed to change. (e.g. LMA is read-only) */
2965 CPUMGetGuestCpuId(pVCpu, 0x80000001, &u32Dummy, &u32Dummy, &u32Dummy, &u32Features);
2966 if (u32Features & X86_CPUID_AMD_FEATURE_EDX_NX)
2967 uMask |= MSR_K6_EFER_NXE;
2968 if (u32Features & X86_CPUID_AMD_FEATURE_EDX_LONG_MODE)
2969 uMask |= MSR_K6_EFER_LME;
2970 if (u32Features & X86_CPUID_AMD_FEATURE_EDX_SEP)
2971 uMask |= MSR_K6_EFER_SCE;
2972 if (u32Features & X86_CPUID_AMD_FEATURE_EDX_FFXSR)
2973 uMask |= MSR_K6_EFER_FFXSR;
2974
2975 /* Check for illegal MSR_K6_EFER_LME transitions: not allowed to change LME if paging is enabled. (AMD Arch. Programmer's Manual Volume 2: Table 14-5) */
2976 if ( ((pCtx->msrEFER & MSR_K6_EFER_LME) != (val & uMask & MSR_K6_EFER_LME))
2977 && (pCtx->cr0 & X86_CR0_PG))
2978 {
2979 AssertMsgFailed(("Illegal MSR_K6_EFER_LME change: paging is enabled!!\n"));
2980 return VERR_EM_INTERPRETER; /* @todo generate #GP(0) */
2981 }
2982
2983 /* There are a few more: e.g. MSR_K6_EFER_LMSLE */
2984 AssertMsg(!(val & ~(MSR_K6_EFER_NXE|MSR_K6_EFER_LME|MSR_K6_EFER_LMA /* ignored anyway */ |MSR_K6_EFER_SCE|MSR_K6_EFER_FFXSR)), ("Unexpected value %RX64\n", val));
2985 pCtx->msrEFER = (pCtx->msrEFER & ~uMask) | (val & uMask);
2986
2987 /* AMD64 Architecture Programmer's Manual: 15.15 TLB Control; flush the TLB if MSR_K6_EFER_NXE, MSR_K6_EFER_LME or MSR_K6_EFER_LMA are changed. */
2988 if ((oldval & (MSR_K6_EFER_NXE|MSR_K6_EFER_LME|MSR_K6_EFER_LMA)) != (pCtx->msrEFER & (MSR_K6_EFER_NXE|MSR_K6_EFER_LME|MSR_K6_EFER_LMA)))
2989 HWACCMFlushTLB(pVM);
2990
2991 break;
2992 }
2993
2994 case MSR_K8_SF_MASK:
2995 pCtx->msrSFMASK = val;
2996 break;
2997
2998 case MSR_K6_STAR:
2999 pCtx->msrSTAR = val;
3000 break;
3001
3002 case MSR_K8_LSTAR:
3003 pCtx->msrLSTAR = val;
3004 break;
3005
3006 case MSR_K8_CSTAR:
3007 pCtx->msrCSTAR = val;
3008 break;
3009
3010 case MSR_K8_FS_BASE:
3011 pCtx->fsHid.u64Base = val;
3012 break;
3013
3014 case MSR_K8_GS_BASE:
3015 pCtx->gsHid.u64Base = val;
3016 break;
3017
3018 case MSR_K8_KERNEL_GS_BASE:
3019 pCtx->msrKERNELGSBASE = val;
3020 break;
3021
3022 case MSR_K8_TSC_AUX:
3023 CPUMSetGuestMsr(pVCpu, MSR_K8_TSC_AUX, val);
3024 break;
3025
3026 default:
3027 /* In X2APIC specification this range is reserved for APIC control. */
3028 if ((pRegFrame->ecx >= MSR_IA32_APIC_START) && (pRegFrame->ecx < MSR_IA32_APIC_END))
3029 return PDMApicWriteMSR(pVM, pVCpu->idCpu, pRegFrame->ecx, val);
3030
3031 /* We should actually trigger a #GP here, but don't as that might cause more trouble. */
3032 break;
3033 }
3034 return VINF_SUCCESS;
3035}
3036
3037
3038/**
3039 * WRMSR Emulation.
3040 */
3041static int emInterpretWrmsr(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
3042{
3043 return EMInterpretWrmsr(pVM, pVCpu, pRegFrame);
3044}
3045
3046
3047/**
3048 * Internal worker.
3049 * @copydoc EMInterpretInstructionCPU
3050 */
3051DECLINLINE(int) emInterpretInstructionCPU(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDISState, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
3052{
3053 Assert(pcbSize);
3054 *pcbSize = 0;
3055
3056 /*
3057 * Only supervisor guest code!!
3058 * And no complicated prefixes.
3059 */
3060 /* Get the current privilege level. */
3061 uint32_t cpl = CPUMGetGuestCPL(pVCpu, pRegFrame);
3062 if ( cpl != 0
3063 && pDISState->pCurInstr->opcode != OP_RDTSC) /* rdtsc requires emulation in ring 3 as well */
3064 {
3065 Log(("WARNING: refusing instruction emulation for user-mode code!!\n"));
3066 STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,FailedUserMode));
3067 return VERR_EM_INTERPRETER;
3068 }
3069
3070#ifdef IN_RC
3071 if ( (pDISState->prefix & (PREFIX_REPNE | PREFIX_REP))
3072 || ( (pDISState->prefix & PREFIX_LOCK)
3073 && pDISState->pCurInstr->opcode != OP_CMPXCHG
3074 && pDISState->pCurInstr->opcode != OP_CMPXCHG8B
3075 && pDISState->pCurInstr->opcode != OP_XADD
3076 && pDISState->pCurInstr->opcode != OP_OR
3077 && pDISState->pCurInstr->opcode != OP_BTR
3078 )
3079 )
3080#else
3081 if ( (pDISState->prefix & PREFIX_REPNE)
3082 || ( (pDISState->prefix & PREFIX_REP)
3083 && pDISState->pCurInstr->opcode != OP_STOSWD
3084 )
3085 || ( (pDISState->prefix & PREFIX_LOCK)
3086 && pDISState->pCurInstr->opcode != OP_OR
3087 && pDISState->pCurInstr->opcode != OP_BTR
3088 && pDISState->pCurInstr->opcode != OP_CMPXCHG
3089 && pDISState->pCurInstr->opcode != OP_CMPXCHG8B
3090 )
3091 )
3092#endif
3093 {
3094 //Log(("EMInterpretInstruction: wrong prefix!!\n"));
3095 STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,FailedPrefix));
3096 return VERR_EM_INTERPRETER;
3097 }
3098
3099#if HC_ARCH_BITS == 32
3100 /*
3101 * Unable to emulate most >4 bytes accesses in 32 bits mode.
3102 * Whitelisted instructions are safe.
3103 */
3104 if ( pDISState->param1.size > 4
3105 && CPUMIsGuestIn64BitCode(pVCpu, pRegFrame))
3106 {
3107 uint32_t uOpCode = pDISState->pCurInstr->opcode;
3108 if ( uOpCode != OP_STOSWD
3109 && uOpCode != OP_MOV
3110 && uOpCode != OP_CMPXCHG8B
3111 && uOpCode != OP_XCHG
3112 && uOpCode != OP_BTS
3113 && uOpCode != OP_BTR
3114 && uOpCode != OP_BTC
3115# ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
3116 && uOpCode != OP_CMPXCHG /* solaris */
3117 && uOpCode != OP_AND /* windows */
3118 && uOpCode != OP_OR /* windows */
3119 && uOpCode != OP_XOR /* because we can */
3120 && uOpCode != OP_ADD /* windows (dripple) */
3121 && uOpCode != OP_ADC /* because we can */
3122 && uOpCode != OP_SUB /* because we can */
3123 /** @todo OP_BTS or is that a different kind of failure? */
3124# endif
3125 )
3126 {
3127# ifdef VBOX_WITH_STATISTICS
3128 switch (pDISState->pCurInstr->opcode)
3129 {
3130# define INTERPRET_FAILED_CASE(opcode, Instr) \
3131 case opcode: STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,Failed##Instr)); break;
3132 INTERPRET_FAILED_CASE(OP_XCHG,Xchg);
3133 INTERPRET_FAILED_CASE(OP_DEC,Dec);
3134 INTERPRET_FAILED_CASE(OP_INC,Inc);
3135 INTERPRET_FAILED_CASE(OP_POP,Pop);
3136 INTERPRET_FAILED_CASE(OP_OR, Or);
3137 INTERPRET_FAILED_CASE(OP_XOR,Xor);
3138 INTERPRET_FAILED_CASE(OP_AND,And);
3139 INTERPRET_FAILED_CASE(OP_MOV,Mov);
3140 INTERPRET_FAILED_CASE(OP_STOSWD,StosWD);
3141 INTERPRET_FAILED_CASE(OP_INVLPG,InvlPg);
3142 INTERPRET_FAILED_CASE(OP_CPUID,CpuId);
3143 INTERPRET_FAILED_CASE(OP_MOV_CR,MovCRx);
3144 INTERPRET_FAILED_CASE(OP_MOV_DR,MovDRx);
3145 INTERPRET_FAILED_CASE(OP_LLDT,LLdt);
3146 INTERPRET_FAILED_CASE(OP_LIDT,LIdt);
3147 INTERPRET_FAILED_CASE(OP_LGDT,LGdt);
3148 INTERPRET_FAILED_CASE(OP_LMSW,Lmsw);
3149 INTERPRET_FAILED_CASE(OP_CLTS,Clts);
3150 INTERPRET_FAILED_CASE(OP_MONITOR,Monitor);
3151 INTERPRET_FAILED_CASE(OP_MWAIT,MWait);
3152 INTERPRET_FAILED_CASE(OP_RDMSR,Rdmsr);
3153 INTERPRET_FAILED_CASE(OP_WRMSR,Wrmsr);
3154 INTERPRET_FAILED_CASE(OP_ADD,Add);
3155 INTERPRET_FAILED_CASE(OP_SUB,Sub);
3156 INTERPRET_FAILED_CASE(OP_ADC,Adc);
3157 INTERPRET_FAILED_CASE(OP_BTR,Btr);
3158 INTERPRET_FAILED_CASE(OP_BTS,Bts);
3159 INTERPRET_FAILED_CASE(OP_BTC,Btc);
3160 INTERPRET_FAILED_CASE(OP_RDTSC,Rdtsc);
3161 INTERPRET_FAILED_CASE(OP_CMPXCHG, CmpXchg);
3162 INTERPRET_FAILED_CASE(OP_STI, Sti);
3163 INTERPRET_FAILED_CASE(OP_XADD,XAdd);
3164 INTERPRET_FAILED_CASE(OP_CMPXCHG8B,CmpXchg8b);
3165 INTERPRET_FAILED_CASE(OP_HLT, Hlt);
3166 INTERPRET_FAILED_CASE(OP_IRET,Iret);
3167 INTERPRET_FAILED_CASE(OP_WBINVD,WbInvd);
3168 INTERPRET_FAILED_CASE(OP_MOVNTPS,MovNTPS);
3169# undef INTERPRET_FAILED_CASE
3170 default:
3171 STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,FailedMisc));
3172 break;
3173 }
3174# endif /* VBOX_WITH_STATISTICS */
3175 return VERR_EM_INTERPRETER;
3176 }
3177 }
3178#endif
3179
3180 int rc;
3181#if (defined(VBOX_STRICT) || defined(LOG_ENABLED))
3182 LogFlow(("emInterpretInstructionCPU %s\n", emGetMnemonic(pDISState)));
3183#endif
3184 switch (pDISState->pCurInstr->opcode)
3185 {
3186 /*
3187 * Macros for generating the right case statements.
3188 */
3189# define INTERPRET_CASE_EX_LOCK_PARAM3(opcode, Instr, InstrFn, pfnEmulate, pfnEmulateLock) \
3190 case opcode:\
3191 if (pDISState->prefix & PREFIX_LOCK) \
3192 rc = emInterpretLock##InstrFn(pVM, pVCpu, pDISState, pRegFrame, pvFault, pcbSize, pfnEmulateLock); \
3193 else \
3194 rc = emInterpret##InstrFn(pVM, pVCpu, pDISState, pRegFrame, pvFault, pcbSize, pfnEmulate); \
3195 if (RT_SUCCESS(rc)) \
3196 STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,Instr)); \
3197 else \
3198 STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,Failed##Instr)); \
3199 return rc
3200#define INTERPRET_CASE_EX_PARAM3(opcode, Instr, InstrFn, pfnEmulate) \
3201 case opcode:\
3202 rc = emInterpret##InstrFn(pVM, pVCpu, pDISState, pRegFrame, pvFault, pcbSize, pfnEmulate); \
3203 if (RT_SUCCESS(rc)) \
3204 STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,Instr)); \
3205 else \
3206 STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,Failed##Instr)); \
3207 return rc
3208
3209#define INTERPRET_CASE_EX_PARAM2(opcode, Instr, InstrFn, pfnEmulate) \
3210 INTERPRET_CASE_EX_PARAM3(opcode, Instr, InstrFn, pfnEmulate)
3211#define INTERPRET_CASE_EX_LOCK_PARAM2(opcode, Instr, InstrFn, pfnEmulate, pfnEmulateLock) \
3212 INTERPRET_CASE_EX_LOCK_PARAM3(opcode, Instr, InstrFn, pfnEmulate, pfnEmulateLock)
3213
3214#define INTERPRET_CASE(opcode, Instr) \
3215 case opcode:\
3216 rc = emInterpret##Instr(pVM, pVCpu, pDISState, pRegFrame, pvFault, pcbSize); \
3217 if (RT_SUCCESS(rc)) \
3218 STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,Instr)); \
3219 else \
3220 STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,Failed##Instr)); \
3221 return rc
3222
3223#define INTERPRET_CASE_EX_DUAL_PARAM2(opcode, Instr, InstrFn) \
3224 case opcode:\
3225 rc = emInterpret##InstrFn(pVM, pVCpu, pDISState, pRegFrame, pvFault, pcbSize); \
3226 if (RT_SUCCESS(rc)) \
3227 STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,Instr)); \
3228 else \
3229 STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,Failed##Instr)); \
3230 return rc
3231
3232#define INTERPRET_STAT_CASE(opcode, Instr) \
3233 case opcode: STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,Failed##Instr)); return VERR_EM_INTERPRETER;
3234
3235 /*
3236 * The actual case statements.
3237 */
3238 INTERPRET_CASE(OP_XCHG,Xchg);
3239 INTERPRET_CASE_EX_PARAM2(OP_DEC,Dec, IncDec, EMEmulateDec);
3240 INTERPRET_CASE_EX_PARAM2(OP_INC,Inc, IncDec, EMEmulateInc);
3241 INTERPRET_CASE(OP_POP,Pop);
3242 INTERPRET_CASE_EX_LOCK_PARAM3(OP_OR, Or, OrXorAnd, EMEmulateOr, EMEmulateLockOr);
3243 INTERPRET_CASE_EX_PARAM3(OP_XOR,Xor, OrXorAnd, EMEmulateXor);
3244 INTERPRET_CASE_EX_PARAM3(OP_AND,And, OrXorAnd, EMEmulateAnd);
3245 INTERPRET_CASE(OP_MOV,Mov);
3246#ifndef IN_RC
3247 INTERPRET_CASE(OP_STOSWD,StosWD);
3248#endif
3249 INTERPRET_CASE(OP_INVLPG,InvlPg);
3250 INTERPRET_CASE(OP_CPUID,CpuId);
3251 INTERPRET_CASE(OP_MOV_CR,MovCRx);
3252 INTERPRET_CASE(OP_MOV_DR,MovDRx);
3253#ifdef IN_RING0
3254 INTERPRET_CASE_EX_DUAL_PARAM2(OP_LIDT, LIdt, LIGdt);
3255 INTERPRET_CASE_EX_DUAL_PARAM2(OP_LGDT, LGdt, LIGdt);
3256#endif
3257 INTERPRET_CASE(OP_LLDT,LLdt);
3258 INTERPRET_CASE(OP_LMSW,Lmsw);
3259#ifdef EM_EMULATE_SMSW
3260 INTERPRET_CASE(OP_SMSW,Smsw);
3261#endif
3262 INTERPRET_CASE(OP_CLTS,Clts);
3263 INTERPRET_CASE(OP_MONITOR, Monitor);
3264 INTERPRET_CASE(OP_MWAIT, MWait);
3265 INTERPRET_CASE(OP_RDMSR, Rdmsr);
3266 INTERPRET_CASE(OP_WRMSR, Wrmsr);
3267 INTERPRET_CASE_EX_PARAM3(OP_ADD,Add, AddSub, EMEmulateAdd);
3268 INTERPRET_CASE_EX_PARAM3(OP_SUB,Sub, AddSub, EMEmulateSub);
3269 INTERPRET_CASE(OP_ADC,Adc);
3270 INTERPRET_CASE_EX_LOCK_PARAM2(OP_BTR,Btr, BitTest, EMEmulateBtr, EMEmulateLockBtr);
3271 INTERPRET_CASE_EX_PARAM2(OP_BTS,Bts, BitTest, EMEmulateBts);
3272 INTERPRET_CASE_EX_PARAM2(OP_BTC,Btc, BitTest, EMEmulateBtc);
3273 INTERPRET_CASE(OP_RDPMC,Rdpmc);
3274 INTERPRET_CASE(OP_RDTSC,Rdtsc);
3275 INTERPRET_CASE(OP_CMPXCHG, CmpXchg);
3276#ifdef IN_RC
3277 INTERPRET_CASE(OP_STI,Sti);
3278 INTERPRET_CASE(OP_XADD, XAdd);
3279#endif
3280 INTERPRET_CASE(OP_CMPXCHG8B, CmpXchg8b);
3281 INTERPRET_CASE(OP_HLT,Hlt);
3282 INTERPRET_CASE(OP_IRET,Iret);
3283 INTERPRET_CASE(OP_WBINVD,WbInvd);
3284#ifdef VBOX_WITH_STATISTICS
3285# ifndef IN_RC
3286 INTERPRET_STAT_CASE(OP_XADD, XAdd);
3287# endif
3288 INTERPRET_STAT_CASE(OP_MOVNTPS,MovNTPS);
3289#endif
3290
3291 default:
3292 Log3(("emInterpretInstructionCPU: opcode=%d\n", pDISState->pCurInstr->opcode));
3293 STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,FailedMisc));
3294 return VERR_EM_INTERPRETER;
3295
3296#undef INTERPRET_CASE_EX_PARAM2
3297#undef INTERPRET_STAT_CASE
3298#undef INTERPRET_CASE_EX
3299#undef INTERPRET_CASE
3300 } /* switch (opcode) */
3301 AssertFailed();
3302 return VERR_INTERNAL_ERROR;
3303}
3304
3305
3306/**
3307 * Sets the PC for which interrupts should be inhibited.
3308 *
3309 * @param pVCpu The VMCPU handle.
3310 * @param PC The PC.
3311 */
3312VMMDECL(void) EMSetInhibitInterruptsPC(PVMCPU pVCpu, RTGCUINTPTR PC)
3313{
3314 pVCpu->em.s.GCPtrInhibitInterrupts = PC;
3315 VMCPU_FF_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
3316}
3317
3318
3319/**
3320 * Gets the PC for which interrupts should be inhibited.
3321 *
3322 * There are a few instructions which inhibits or delays interrupts
3323 * for the instruction following them. These instructions are:
3324 * - STI
3325 * - MOV SS, r/m16
3326 * - POP SS
3327 *
3328 * @returns The PC for which interrupts should be inhibited.
3329 * @param pVCpu The VMCPU handle.
3330 *
3331 */
3332VMMDECL(RTGCUINTPTR) EMGetInhibitInterruptsPC(PVMCPU pVCpu)
3333{
3334 return pVCpu->em.s.GCPtrInhibitInterrupts;
3335}
3336
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette