~ubuntu-branches/ubuntu/karmic/virtualbox-ose/karmic-updates

« back to all changes in this revision

Viewing changes to src/VBox/VMM/EM.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2009-09-14 18:25:07 UTC
  • mfrom: (0.4.1 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090914182507-c98g07mq16hjmn6d
Tags: 3.0.6-dfsg-1ubuntu1
* Merge from debian unstable (LP: #429697), remaining changes:
  - Enable DKMS support on virtualbox host and guest modules (LP: #267097)
    - Drop virtualbox-ose{-guest,}-modules-* package templates
    - Recommend *-source instead of *-modules packages
    - Replace error messages related to missing/mismatched
      kernel module accordingly
  - Autoload kernel module
    - LOAD_VBOXDRV_MODULE=1 in virtualbox-ose.default
  - Disable update action
    - patches/u01-disable-update-action.dpatch
  - Virtualbox should go in Accessories, not in System tools (LP: #288590)
    - virtualbox-ose-qt.files/virtualbox-ose.desktop
  - Add apport hook
    - virtualbox-ose.files/source_virtualbox-ose.py
    - virtualbox-ose.install
  - Add launchpad integration
    - control
    - lpi-bug.xpm
    - patches/u02-lp-integration.dpatch
  - virtualbox, virtualbox-* (names of the upstream proprietary packages)
    conflict with virtualbox-ose (LP: #379878)
* Make debug package depend on normal or guest utils package
* Drop patches/22-pulseaudio-stubs.dpatch (applied upstream)
* Rename Ubuntu specific patches to uXX-*.dpatch
* Fix lintian warnings in maintainer scripts

Show diffs side-by-side

added added

removed removed

Lines of Context:
67
67
#include <VBox/disopcode.h>
68
68
#include <VBox/dbgf.h>
69
69
 
70
 
#include <VBox/log.h>
71
 
#include <iprt/thread.h>
72
 
#include <iprt/assert.h>
73
 
#include <iprt/asm.h>
74
 
#include <iprt/semaphore.h>
75
70
#include <iprt/string.h>
76
 
#include <iprt/avl.h>
77
71
#include <iprt/stream.h>
78
 
#include <VBox/param.h>
79
 
#include <VBox/err.h>
80
72
 
81
73
 
82
74
/*******************************************************************************
95
87
static int emR3Debug(PVM pVM, PVMCPU pVCpu, int rc);
96
88
static int emR3RemStep(PVM pVM, PVMCPU pVCpu);
97
89
static int emR3RemExecute(PVM pVM, PVMCPU pVCpu, bool *pfFFDone);
98
 
static int emR3RawResumeHyper(PVM pVM, PVMCPU pVCpu);
99
 
static int emR3RawStep(PVM pVM, PVMCPU pVCpu);
100
 
DECLINLINE(int) emR3RawHandleRC(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, int rc);
101
 
DECLINLINE(int) emR3RawUpdateForceFlag(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, int rc);
102
 
static int emR3RawForcedActions(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx);
103
 
static int emR3RawExecute(PVM pVM, PVMCPU pVCpu, bool *pfFFDone);
104
90
DECLINLINE(int) emR3RawExecuteInstruction(PVM pVM, PVMCPU pVCpu, const char *pszPrefix, int rcGC = VINF_SUCCESS);
105
 
static int emR3HighPriorityPostForcedActions(PVM pVM, PVMCPU pVCpu, int rc);
106
 
static int emR3ForcedActions(PVM pVM, PVMCPU pVCpu, int rc);
107
 
static int emR3RawGuestTrap(PVM pVM, PVMCPU pVCpu);
108
 
static int emR3PatchTrap(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, int gcret);
109
 
static int emR3SingleStepExecRem(PVM pVM, uint32_t cIterations);
110
 
static EMSTATE emR3Reschedule(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx);
 
91
int emR3HighPriorityPostForcedActions(PVM pVM, PVMCPU pVCpu, int rc);
 
92
 
111
93
 
112
94
/**
113
95
 * Initializes the EM.
367
349
        EM_REG_COUNTER_USED(&pStats->StatSti,                    "/EM/CPU%d/R3/PrivInst/Sti",                "Number of sli instructions.");
368
350
        EM_REG_COUNTER_USED(&pStats->StatIn,                     "/EM/CPU%d/R3/PrivInst/In",                 "Number of in instructions.");
369
351
        EM_REG_COUNTER_USED(&pStats->StatOut,                    "/EM/CPU%d/R3/PrivInst/Out",                "Number of out instructions.");
 
352
        EM_REG_COUNTER_USED(&pStats->StatIoRestarted,            "/EM/CPU%d/R3/PrivInst/IoRestarted",        "Number of restarted i/o instructions.");
370
353
        EM_REG_COUNTER_USED(&pStats->StatHlt,                    "/EM/CPU%d/R3/PrivInst/Hlt",                "Number of hlt instructions not handled in GC because of PATM.");
371
354
        EM_REG_COUNTER_USED(&pStats->StatInvlpg,                 "/EM/CPU%d/R3/PrivInst/Invlpg",             "Number of invlpg instructions.");
372
355
        EM_REG_COUNTER_USED(&pStats->StatMisc,                   "/EM/CPU%d/R3/PrivInst/Misc",               "Number of misc. instructions.");
575
558
 
576
559
 
577
560
/**
578
 
 * Enables or disables a set of raw-mode execution modes.
579
 
 *
580
 
 * @returns VINF_SUCCESS on success.
581
 
 * @returns VINF_RESCHEDULE if a rescheduling might be required.
582
 
 * @returns VERR_INVALID_PARAMETER on an invalid enmMode value.
583
 
 *
584
 
 * @param   pVM         The VM to operate on.
585
 
 * @param   enmMode     The execution mode change.
586
 
 * @thread  The emulation thread.
587
 
 */
588
 
VMMR3DECL(int) EMR3RawSetMode(PVM pVM, EMRAWMODE enmMode)
589
 
{
590
 
    switch (enmMode)
591
 
    {
592
 
        case EMRAW_NONE:
593
 
            pVM->fRawR3Enabled = false;
594
 
            pVM->fRawR0Enabled = false;
595
 
            break;
596
 
        case EMRAW_RING3_ENABLE:
597
 
            pVM->fRawR3Enabled = true;
598
 
            break;
599
 
        case EMRAW_RING3_DISABLE:
600
 
            pVM->fRawR3Enabled = false;
601
 
            break;
602
 
        case EMRAW_RING0_ENABLE:
603
 
            pVM->fRawR0Enabled = true;
604
 
            break;
605
 
        case EMRAW_RING0_DISABLE:
606
 
            pVM->fRawR0Enabled = false;
607
 
            break;
608
 
        default:
609
 
            AssertMsgFailed(("Invalid enmMode=%d\n", enmMode));
610
 
            return VERR_INVALID_PARAMETER;
611
 
    }
612
 
    Log(("EMR3SetRawMode: fRawR3Enabled=%RTbool fRawR0Enabled=%RTbool\n",
613
 
          pVM->fRawR3Enabled, pVM->fRawR0Enabled));
614
 
    return pVM->aCpus[0].em.s.enmState == EMSTATE_RAW ? VINF_EM_RESCHEDULE : VINF_SUCCESS;
615
 
}
616
 
 
617
 
 
618
 
/**
619
561
 * Raise a fatal error.
620
562
 *
621
563
 * Safely terminate the VM with full state report and stuff. This function
1062
1004
}
1063
1005
 
1064
1006
 
1065
 
/**
1066
 
 * Resumes executing hypervisor after a debug event.
1067
 
 *
1068
 
 * This is kind of special since our current guest state is
1069
 
 * potentially out of sync.
1070
 
 *
1071
 
 * @returns VBox status code.
1072
 
 * @param   pVM     The VM handle.
1073
 
 * @param   pVCpu   The VMCPU handle.
1074
 
 */
1075
 
static int emR3RawResumeHyper(PVM pVM, PVMCPU pVCpu)
1076
 
{
1077
 
    int         rc;
1078
 
    PCPUMCTX    pCtx = pVCpu->em.s.pCtx;
1079
 
    Assert(pVCpu->em.s.enmState == EMSTATE_DEBUG_HYPER);
1080
 
    Log(("emR3RawResumeHyper: cs:eip=%RTsel:%RGr efl=%RGr\n", pCtx->cs, pCtx->eip, pCtx->eflags));
1081
 
 
1082
 
    /*
1083
 
     * Resume execution.
1084
 
     */
1085
 
    CPUMRawEnter(pVCpu, NULL);
1086
 
    CPUMSetHyperEFlags(pVCpu, CPUMGetHyperEFlags(pVCpu) | X86_EFL_RF);
1087
 
    rc = VMMR3ResumeHyper(pVM, pVCpu);
1088
 
    Log(("emR3RawStep: cs:eip=%RTsel:%RGr efl=%RGr - returned from GC with rc=%Rrc\n", pCtx->cs, pCtx->eip, pCtx->eflags, rc));
1089
 
    rc = CPUMRawLeave(pVCpu, NULL, rc);
1090
 
    VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_RESUME_GUEST_MASK);
1091
 
 
1092
 
    /*
1093
 
     * Deal with the return code.
1094
 
     */
1095
 
    rc = emR3HighPriorityPostForcedActions(pVM, pVCpu, rc);
1096
 
    rc = emR3RawHandleRC(pVM, pVCpu, pCtx, rc);
1097
 
    rc = emR3RawUpdateForceFlag(pVM, pVCpu, pCtx, rc);
1098
 
    return rc;
1099
 
}
1100
 
 
1101
 
 
1102
 
/**
1103
 
 * Steps rawmode.
1104
 
 *
1105
 
 * @returns VBox status code.
1106
 
 * @param   pVM     The VM handle.
1107
 
 * @param   pVCpu   The VMCPU handle.
1108
 
 */
1109
 
static int emR3RawStep(PVM pVM, PVMCPU pVCpu)
1110
 
{
1111
 
    Assert(   pVCpu->em.s.enmState == EMSTATE_DEBUG_HYPER
1112
 
           || pVCpu->em.s.enmState == EMSTATE_DEBUG_GUEST_RAW
1113
 
           || pVCpu->em.s.enmState == EMSTATE_DEBUG_GUEST_REM);
1114
 
    int         rc;
1115
 
    PCPUMCTX    pCtx   = pVCpu->em.s.pCtx;
1116
 
    bool        fGuest = pVCpu->em.s.enmState != EMSTATE_DEBUG_HYPER;
1117
 
#ifndef DEBUG_sandervl
1118
 
    Log(("emR3RawStep: cs:eip=%RTsel:%RGr efl=%RGr\n", fGuest ? CPUMGetGuestCS(pVCpu) : CPUMGetHyperCS(pVCpu),
1119
 
         fGuest ? CPUMGetGuestEIP(pVCpu) : CPUMGetHyperEIP(pVCpu), fGuest ? CPUMGetGuestEFlags(pVCpu) : CPUMGetHyperEFlags(pVCpu)));
1120
 
#endif
1121
 
    if (fGuest)
1122
 
    {
1123
 
        /*
1124
 
         * Check vital forced actions, but ignore pending interrupts and timers.
1125
 
         */
1126
 
        if (    VM_FF_ISPENDING(pVM, VM_FF_HIGH_PRIORITY_PRE_RAW_MASK)
1127
 
            ||  VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_HIGH_PRIORITY_PRE_RAW_MASK))
1128
 
        {
1129
 
            rc = emR3RawForcedActions(pVM, pVCpu, pCtx);
1130
 
            if (rc != VINF_SUCCESS)
1131
 
                return rc;
1132
 
        }
1133
 
 
1134
 
        /*
1135
 
         * Set flags for single stepping.
1136
 
         */
1137
 
        CPUMSetGuestEFlags(pVCpu, CPUMGetGuestEFlags(pVCpu) | X86_EFL_TF | X86_EFL_RF);
1138
 
    }
1139
 
    else
1140
 
        CPUMSetHyperEFlags(pVCpu, CPUMGetHyperEFlags(pVCpu) | X86_EFL_TF | X86_EFL_RF);
1141
 
 
1142
 
    /*
1143
 
     * Single step.
1144
 
     * We do not start time or anything, if anything we should just do a few nanoseconds.
1145
 
     */
1146
 
    CPUMRawEnter(pVCpu, NULL);
1147
 
    do
1148
 
    {
1149
 
        if (pVCpu->em.s.enmState == EMSTATE_DEBUG_HYPER)
1150
 
            rc = VMMR3ResumeHyper(pVM, pVCpu);
1151
 
        else
1152
 
            rc = VMMR3RawRunGC(pVM, pVCpu);
1153
 
#ifndef DEBUG_sandervl
1154
 
        Log(("emR3RawStep: cs:eip=%RTsel:%RGr efl=%RGr - GC rc %Rrc\n", fGuest ? CPUMGetGuestCS(pVCpu) : CPUMGetHyperCS(pVCpu),
1155
 
             fGuest ? CPUMGetGuestEIP(pVCpu) : CPUMGetHyperEIP(pVCpu), fGuest ? CPUMGetGuestEFlags(pVCpu) : CPUMGetHyperEFlags(pVCpu), rc));
1156
 
#endif
1157
 
    } while (   rc == VINF_SUCCESS
1158
 
             || rc == VINF_EM_RAW_INTERRUPT);
1159
 
    rc = CPUMRawLeave(pVCpu, NULL, rc);
1160
 
    VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_RESUME_GUEST_MASK);
1161
 
 
1162
 
    /*
1163
 
     * Make sure the trap flag is cleared.
1164
 
     * (Too bad if the guest is trying to single step too.)
1165
 
     */
1166
 
    if (fGuest)
1167
 
        CPUMSetGuestEFlags(pVCpu, CPUMGetGuestEFlags(pVCpu) & ~X86_EFL_TF);
1168
 
    else
1169
 
        CPUMSetHyperEFlags(pVCpu, CPUMGetHyperEFlags(pVCpu) & ~X86_EFL_TF);
1170
 
 
1171
 
    /*
1172
 
     * Deal with the return codes.
1173
 
     */
1174
 
    rc = emR3HighPriorityPostForcedActions(pVM, pVCpu, rc);
1175
 
    rc = emR3RawHandleRC(pVM, pVCpu, pCtx, rc);
1176
 
    rc = emR3RawUpdateForceFlag(pVM, pVCpu, pCtx, rc);
1177
 
    return rc;
1178
 
}
1179
 
 
1180
 
 
1181
1007
#ifdef DEBUG
1182
1008
 
1183
 
/**
1184
 
 * Steps hardware accelerated mode.
1185
 
 *
1186
 
 * @returns VBox status code.
1187
 
 * @param   pVM     The VM handle.
1188
 
 * @param   pVCpu   The VMCPU handle.
1189
 
 */
1190
 
static int emR3HwAccStep(PVM pVM, PVMCPU pVCpu)
1191
 
{
1192
 
    Assert(pVCpu->em.s.enmState == EMSTATE_DEBUG_GUEST_HWACC);
1193
 
 
1194
 
    int         rc;
1195
 
    PCPUMCTX    pCtx   = pVCpu->em.s.pCtx;
1196
 
    VMCPU_FF_CLEAR(pVCpu, (VMCPU_FF_SELM_SYNC_GDT | VMCPU_FF_SELM_SYNC_LDT | VMCPU_FF_TRPM_SYNC_IDT | VMCPU_FF_SELM_SYNC_TSS));
1197
 
 
1198
 
    /*
1199
 
     * Check vital forced actions, but ignore pending interrupts and timers.
1200
 
     */
1201
 
    if (    VM_FF_ISPENDING(pVM, VM_FF_HIGH_PRIORITY_PRE_RAW_MASK)
1202
 
        ||  VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_HIGH_PRIORITY_PRE_RAW_MASK))
1203
 
    {
1204
 
        rc = emR3RawForcedActions(pVM, pVCpu, pCtx);
1205
 
        if (rc != VINF_SUCCESS)
1206
 
            return rc;
1207
 
    }
1208
 
    /*
1209
 
     * Set flags for single stepping.
1210
 
     */
1211
 
    CPUMSetGuestEFlags(pVCpu, CPUMGetGuestEFlags(pVCpu) | X86_EFL_TF | X86_EFL_RF);
1212
 
 
1213
 
    /*
1214
 
     * Single step.
1215
 
     * We do not start time or anything, if anything we should just do a few nanoseconds.
1216
 
     */
1217
 
    do
1218
 
    {
1219
 
        rc = VMMR3HwAccRunGC(pVM, pVCpu);
1220
 
    } while (   rc == VINF_SUCCESS
1221
 
             || rc == VINF_EM_RAW_INTERRUPT);
1222
 
    VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_RESUME_GUEST_MASK);
1223
 
 
1224
 
    /*
1225
 
     * Make sure the trap flag is cleared.
1226
 
     * (Too bad if the guest is trying to single step too.)
1227
 
     */
1228
 
    CPUMSetGuestEFlags(pVCpu, CPUMGetGuestEFlags(pVCpu) & ~X86_EFL_TF);
1229
 
 
1230
 
    /*
1231
 
     * Deal with the return codes.
1232
 
     */
1233
 
    rc = emR3HighPriorityPostForcedActions(pVM, pVCpu, rc);
1234
 
    rc = emR3RawHandleRC(pVM, pVCpu, pCtx, rc);
1235
 
    rc = emR3RawUpdateForceFlag(pVM, pVCpu, pCtx, rc);
1236
 
    return rc;
1237
 
}
1238
 
 
1239
 
 
1240
 
int emR3SingleStepExecRaw(PVM pVM, PVMCPU pVCpu, uint32_t cIterations)
1241
 
{
1242
 
    int     rc          = VINF_SUCCESS;
1243
 
    EMSTATE enmOldState = pVCpu->em.s.enmState;
1244
 
    pVCpu->em.s.enmState  = EMSTATE_DEBUG_GUEST_RAW;
1245
 
 
1246
 
    Log(("Single step BEGIN:\n"));
1247
 
    for (uint32_t i = 0; i < cIterations; i++)
1248
 
    {
1249
 
        DBGFR3PrgStep(pVCpu);
1250
 
        DBGFR3DisasInstrCurrentLog(pVCpu, "RSS: ");
1251
 
        rc = emR3RawStep(pVM, pVCpu);
1252
 
        if (rc != VINF_SUCCESS)
1253
 
            break;
1254
 
    }
1255
 
    Log(("Single step END: rc=%Rrc\n", rc));
1256
 
    CPUMSetGuestEFlags(pVCpu, CPUMGetGuestEFlags(pVCpu) & ~X86_EFL_TF);
1257
 
    pVCpu->em.s.enmState = enmOldState;
1258
 
    return rc;
1259
 
}
1260
 
 
1261
 
 
1262
 
static int emR3SingleStepExecHwAcc(PVM pVM, PVMCPU pVCpu, uint32_t cIterations)
1263
 
{
1264
 
    int     rc          = VINF_SUCCESS;
1265
 
    EMSTATE enmOldState = pVCpu->em.s.enmState;
1266
 
    pVCpu->em.s.enmState  = EMSTATE_DEBUG_GUEST_HWACC;
1267
 
 
1268
 
    Log(("Single step BEGIN:\n"));
1269
 
    for (uint32_t i = 0; i < cIterations; i++)
1270
 
    {
1271
 
        DBGFR3PrgStep(pVCpu);
1272
 
        DBGFR3DisasInstrCurrentLog(pVCpu, "RSS: ");
1273
 
        rc = emR3HwAccStep(pVM, pVCpu);
1274
 
        if (    rc != VINF_SUCCESS
1275
 
            ||  !HWACCMR3CanExecuteGuest(pVM, pVCpu->em.s.pCtx))
1276
 
            break;
1277
 
    }
1278
 
    Log(("Single step END: rc=%Rrc\n", rc));
1279
 
    CPUMSetGuestEFlags(pVCpu, CPUMGetGuestEFlags(pVCpu) & ~X86_EFL_TF);
1280
 
    pVCpu->em.s.enmState = enmOldState;
1281
 
    return rc == VINF_SUCCESS ? VINF_EM_RESCHEDULE_REM : rc;
1282
 
}
1283
 
 
1284
 
 
1285
 
static int emR3SingleStepExecRem(PVM pVM, PVMCPU pVCpu, uint32_t cIterations)
 
1009
int emR3SingleStepExecRem(PVM pVM, PVMCPU pVCpu, uint32_t cIterations)
1286
1010
{
1287
1011
    EMSTATE  enmOldState = pVCpu->em.s.enmState;
1288
1012
 
1307
1031
 
1308
1032
 
1309
1033
/**
1310
 
 * Executes one (or perhaps a few more) instruction(s).
1311
 
 *
1312
 
 * @returns VBox status code suitable for EM.
1313
 
 *
1314
 
 * @param   pVM         VM handle.
1315
 
 * @param   pVCpu       VMCPU handle
1316
 
 * @param   rcGC        GC return code
1317
 
 * @param   pszPrefix   Disassembly prefix. If not NULL we'll disassemble the
1318
 
 *                      instruction and prefix the log output with this text.
1319
 
 */
1320
 
#ifdef LOG_ENABLED
1321
 
static int emR3RawExecuteInstructionWorker(PVM pVM, PVMCPU pVCpu, int rcGC, const char *pszPrefix)
1322
 
#else
1323
 
static int emR3RawExecuteInstructionWorker(PVM pVM, PVMCPU pVCpu, int rcGC)
1324
 
#endif
1325
 
{
1326
 
    PCPUMCTX pCtx = pVCpu->em.s.pCtx;
1327
 
    int      rc;
1328
 
 
1329
 
    /*
1330
 
     *
1331
 
     * The simple solution is to use the recompiler.
1332
 
     * The better solution is to disassemble the current instruction and
1333
 
     * try handle as many as possible without using REM.
1334
 
     *
1335
 
     */
1336
 
 
1337
 
#ifdef LOG_ENABLED
1338
 
    /*
1339
 
     * Disassemble the instruction if requested.
1340
 
     */
1341
 
    if (pszPrefix)
1342
 
    {
1343
 
        DBGFR3InfoLog(pVM, "cpumguest", pszPrefix);
1344
 
        DBGFR3DisasInstrCurrentLog(pVCpu, pszPrefix);
1345
 
    }
1346
 
#endif /* LOG_ENABLED */
1347
 
 
1348
 
    /*
1349
 
     * PATM is making life more interesting.
1350
 
     * We cannot hand anything to REM which has an EIP inside patch code. So, we'll
1351
 
     * tell PATM there is a trap in this code and have it take the appropriate actions
1352
 
     * to allow us execute the code in REM.
1353
 
     */
1354
 
    if (PATMIsPatchGCAddr(pVM, pCtx->eip))
1355
 
    {
1356
 
        Log(("emR3RawExecuteInstruction: In patch block. eip=%RRv\n", (RTRCPTR)pCtx->eip));
1357
 
 
1358
 
        RTGCPTR pNewEip;
1359
 
        rc = PATMR3HandleTrap(pVM, pCtx, pCtx->eip, &pNewEip);
1360
 
        switch (rc)
1361
 
        {
1362
 
            /*
1363
 
             * It's not very useful to emulate a single instruction and then go back to raw
1364
 
             * mode; just execute the whole block until IF is set again.
1365
 
             */
1366
 
            case VINF_SUCCESS:
1367
 
                Log(("emR3RawExecuteInstruction: Executing instruction starting at new address %RGv IF=%d VMIF=%x\n",
1368
 
                     pNewEip, pCtx->eflags.Bits.u1IF, pVCpu->em.s.pPatmGCState->uVMFlags));
1369
 
                pCtx->eip = pNewEip;
1370
 
                Assert(pCtx->eip);
1371
 
 
1372
 
                if (pCtx->eflags.Bits.u1IF)
1373
 
                {
1374
 
                    /*
1375
 
                     * The last instruction in the patch block needs to be executed!! (sti/sysexit for example)
1376
 
                     */
1377
 
                    Log(("PATCH: IF=1 -> emulate last instruction as it can't be interrupted!!\n"));
1378
 
                    return emR3RawExecuteInstruction(pVM, pVCpu, "PATCHIR");
1379
 
                }
1380
 
                else if (rcGC == VINF_PATM_PENDING_IRQ_AFTER_IRET)
1381
 
                {
1382
 
                    /* special case: iret, that sets IF,  detected a pending irq/event */
1383
 
                    return emR3RawExecuteInstruction(pVM, pVCpu, "PATCHIRET");
1384
 
                }
1385
 
                return VINF_EM_RESCHEDULE_REM;
1386
 
 
1387
 
            /*
1388
 
             * One instruction.
1389
 
             */
1390
 
            case VINF_PATCH_EMULATE_INSTR:
1391
 
                Log(("emR3RawExecuteInstruction: Emulate patched instruction at %RGv IF=%d VMIF=%x\n",
1392
 
                     pNewEip, pCtx->eflags.Bits.u1IF, pVCpu->em.s.pPatmGCState->uVMFlags));
1393
 
                pCtx->eip = pNewEip;
1394
 
                return emR3RawExecuteInstruction(pVM, pVCpu, "PATCHIR");
1395
 
 
1396
 
            /*
1397
 
             * The patch was disabled, hand it to the REM.
1398
 
             */
1399
 
            case VERR_PATCH_DISABLED:
1400
 
                Log(("emR3RawExecuteInstruction: Disabled patch -> new eip %RGv IF=%d VMIF=%x\n",
1401
 
                     pNewEip, pCtx->eflags.Bits.u1IF, pVCpu->em.s.pPatmGCState->uVMFlags));
1402
 
                pCtx->eip = pNewEip;
1403
 
                if (pCtx->eflags.Bits.u1IF)
1404
 
                {
1405
 
                    /*
1406
 
                     * The last instruction in the patch block needs to be executed!! (sti/sysexit for example)
1407
 
                     */
1408
 
                    Log(("PATCH: IF=1 -> emulate last instruction as it can't be interrupted!!\n"));
1409
 
                    return emR3RawExecuteInstruction(pVM, pVCpu, "PATCHIR");
1410
 
                }
1411
 
                return VINF_EM_RESCHEDULE_REM;
1412
 
 
1413
 
            /* Force continued patch exection; usually due to write monitored stack. */
1414
 
            case VINF_PATCH_CONTINUE:
1415
 
                return VINF_SUCCESS;
1416
 
 
1417
 
            default:
1418
 
                AssertReleaseMsgFailed(("Unknown return code %Rrc from PATMR3HandleTrap\n", rc));
1419
 
                return VERR_IPE_UNEXPECTED_STATUS;
1420
 
        }
1421
 
    }
1422
 
 
1423
 
#if 0
1424
 
    /* Try our own instruction emulator before falling back to the recompiler. */
1425
 
    DISCPUSTATE Cpu;
1426
 
    rc = CPUMR3DisasmInstrCPU(pVM, pVCpu, pCtx, pCtx->rip, &Cpu, "GEN EMU");
1427
 
    if (RT_SUCCESS(rc))
1428
 
    {
1429
 
        uint32_t size;
1430
 
 
1431
 
        switch (Cpu.pCurInstr->opcode)
1432
 
        {
1433
 
        /* @todo we can do more now */
1434
 
        case OP_MOV:
1435
 
        case OP_AND:
1436
 
        case OP_OR:
1437
 
        case OP_XOR:
1438
 
        case OP_POP:
1439
 
        case OP_INC:
1440
 
        case OP_DEC:
1441
 
        case OP_XCHG:
1442
 
            STAM_PROFILE_START(&pVCpu->em.s.StatMiscEmu, a);
1443
 
            rc = EMInterpretInstructionCPU(pVM, &Cpu, CPUMCTX2CORE(pCtx), 0, &size);
1444
 
            if (RT_SUCCESS(rc))
1445
 
            {
1446
 
                pCtx->rip += Cpu.opsize;
1447
 
#ifdef EM_NOTIFY_HWACCM
1448
 
                if (pVCpu->em.s.enmState == EMSTATE_DEBUG_GUEST_HWACC)
1449
 
                    HWACCMR3NotifyEmulated(pVCpu);
1450
 
#endif
1451
 
                STAM_PROFILE_STOP(&pVCpu->em.s.StatMiscEmu, a);
1452
 
                return rc;
1453
 
            }
1454
 
            if (rc != VERR_EM_INTERPRETER)
1455
 
                AssertMsgFailedReturn(("rc=%Rrc\n", rc), rc);
1456
 
            STAM_PROFILE_STOP(&pVCpu->em.s.StatMiscEmu, a);
1457
 
            break;
1458
 
        }
1459
 
    }
1460
 
#endif /* 0 */
1461
 
    STAM_PROFILE_START(&pVCpu->em.s.StatREMEmu, a);
1462
 
    Log(("EMINS: %04x:%RGv RSP=%RGv\n", pCtx->cs, (RTGCPTR)pCtx->rip, (RTGCPTR)pCtx->rsp));
1463
 
    EMRemLock(pVM);
1464
 
    /* Flush the recompiler TLB if the VCPU has changed. */
1465
 
    if (pVM->em.s.idLastRemCpu != pVCpu->idCpu)
1466
 
        CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_ALL);
1467
 
    pVM->em.s.idLastRemCpu = pVCpu->idCpu;
1468
 
 
1469
 
    rc = REMR3EmulateInstruction(pVM, pVCpu);
1470
 
    EMRemUnlock(pVM);
1471
 
    STAM_PROFILE_STOP(&pVCpu->em.s.StatREMEmu, a);
1472
 
 
1473
 
#ifdef EM_NOTIFY_HWACCM
1474
 
    if (pVCpu->em.s.enmState == EMSTATE_DEBUG_GUEST_HWACC)
1475
 
        HWACCMR3NotifyEmulated(pVCpu);
1476
 
#endif
1477
 
    return rc;
1478
 
}
1479
 
 
1480
 
 
1481
 
/**
1482
 
 * Executes one (or perhaps a few more) instruction(s).
1483
 
 * This is just a wrapper for discarding pszPrefix in non-logging builds.
1484
 
 *
1485
 
 * @returns VBox status code suitable for EM.
1486
 
 * @param   pVM         VM handle.
1487
 
 * @param   pVCpu       VMCPU handle.
1488
 
 * @param   pszPrefix   Disassembly prefix. If not NULL we'll disassemble the
1489
 
 *                      instruction and prefix the log output with this text.
1490
 
 * @param   rcGC        GC return code
1491
 
 */
1492
 
DECLINLINE(int) emR3RawExecuteInstruction(PVM pVM, PVMCPU pVCpu, const char *pszPrefix, int rcGC)
1493
 
{
1494
 
#ifdef LOG_ENABLED
1495
 
    return emR3RawExecuteInstructionWorker(pVM, pVCpu, rcGC, pszPrefix);
1496
 
#else
1497
 
    return emR3RawExecuteInstructionWorker(pVM, pVCpu, rcGC);
1498
 
#endif
1499
 
}
1500
 
 
1501
 
/**
1502
 
 * Executes one (or perhaps a few more) IO instruction(s).
1503
 
 *
1504
 
 * @returns VBox status code suitable for EM.
1505
 
 * @param   pVM         VM handle.
1506
 
 * @param   pVCpu       VMCPU handle.
1507
 
 */
1508
 
int emR3RawExecuteIOInstruction(PVM pVM, PVMCPU pVCpu)
1509
 
{
1510
 
    int         rc;
1511
 
    PCPUMCTX    pCtx = pVCpu->em.s.pCtx;
1512
 
 
1513
 
    STAM_PROFILE_START(&pVCpu->em.s.StatIOEmu, a);
1514
 
 
1515
 
    /** @todo probably we should fall back to the recompiler; otherwise we'll go back and forth between HC & GC
1516
 
     *   as io instructions tend to come in packages of more than one
1517
 
     */
1518
 
    DISCPUSTATE Cpu;
1519
 
    rc = CPUMR3DisasmInstrCPU(pVM, pVCpu, pCtx, pCtx->rip, &Cpu, "IO EMU");
1520
 
    if (RT_SUCCESS(rc))
1521
 
    {
1522
 
        rc = VINF_EM_RAW_EMULATE_INSTR;
1523
 
 
1524
 
        if (!(Cpu.prefix & (PREFIX_REP | PREFIX_REPNE)))
1525
 
        {
1526
 
            switch (Cpu.pCurInstr->opcode)
1527
 
            {
1528
 
                case OP_IN:
1529
 
                {
1530
 
                    STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->StatIn);
1531
 
                    rc = IOMInterpretIN(pVM, CPUMCTX2CORE(pCtx), &Cpu);
1532
 
                    break;
1533
 
                }
1534
 
 
1535
 
                case OP_OUT:
1536
 
                {
1537
 
                    STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->StatOut);
1538
 
                    rc = IOMInterpretOUT(pVM, CPUMCTX2CORE(pCtx), &Cpu);
1539
 
                    break;
1540
 
                }
1541
 
            }
1542
 
        }
1543
 
        else if (Cpu.prefix & PREFIX_REP)
1544
 
        {
1545
 
            switch (Cpu.pCurInstr->opcode)
1546
 
            {
1547
 
                case OP_INSB:
1548
 
                case OP_INSWD:
1549
 
                {
1550
 
                    STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->StatIn);
1551
 
                    rc = IOMInterpretINS(pVM, CPUMCTX2CORE(pCtx), &Cpu);
1552
 
                    break;
1553
 
                }
1554
 
 
1555
 
                case OP_OUTSB:
1556
 
                case OP_OUTSWD:
1557
 
                {
1558
 
                    STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->StatOut);
1559
 
                    rc = IOMInterpretOUTS(pVM, CPUMCTX2CORE(pCtx), &Cpu);
1560
 
                    break;
1561
 
                }
1562
 
            }
1563
 
        }
1564
 
 
1565
 
        /*
1566
 
         * Handled the I/O return codes.
1567
 
         * (The unhandled cases end up with rc == VINF_EM_RAW_EMULATE_INSTR.)
1568
 
         */
1569
 
        if (IOM_SUCCESS(rc))
1570
 
        {
1571
 
            pCtx->rip += Cpu.opsize;
1572
 
            STAM_PROFILE_STOP(&pVCpu->em.s.StatIOEmu, a);
1573
 
            return rc;
1574
 
        }
1575
 
 
1576
 
        if (rc == VINF_EM_RAW_GUEST_TRAP)
1577
 
        {
1578
 
            STAM_PROFILE_STOP(&pVCpu->em.s.StatIOEmu, a);
1579
 
            rc = emR3RawGuestTrap(pVM, pVCpu);
1580
 
            return rc;
1581
 
        }
1582
 
        AssertMsg(rc != VINF_TRPM_XCPT_DISPATCHED, ("Handle VINF_TRPM_XCPT_DISPATCHED\n"));
1583
 
 
1584
 
        if (RT_FAILURE(rc))
1585
 
        {
1586
 
            STAM_PROFILE_STOP(&pVCpu->em.s.StatIOEmu, a);
1587
 
            return rc;
1588
 
        }
1589
 
        AssertMsg(rc == VINF_EM_RAW_EMULATE_INSTR || rc == VINF_EM_RESCHEDULE_REM, ("rc=%Rrc\n", rc));
1590
 
    }
1591
 
    STAM_PROFILE_STOP(&pVCpu->em.s.StatIOEmu, a);
1592
 
    return emR3RawExecuteInstruction(pVM, pVCpu, "IO: ");
1593
 
}
1594
 
 
1595
 
 
1596
 
/**
1597
 
 * Handle a guest context trap.
1598
 
 *
1599
 
 * @returns VBox status code suitable for EM.
1600
 
 * @param   pVM         VM handle.
1601
 
 * @param   pVCpu       VMCPU handle.
1602
 
 */
1603
 
static int emR3RawGuestTrap(PVM pVM, PVMCPU pVCpu)
1604
 
{
1605
 
    PCPUMCTX pCtx = pVCpu->em.s.pCtx;
1606
 
 
1607
 
    /*
1608
 
     * Get the trap info.
1609
 
     */
1610
 
    uint8_t         u8TrapNo;
1611
 
    TRPMEVENT       enmType;
1612
 
    RTGCUINT        uErrorCode;
1613
 
    RTGCUINTPTR     uCR2;
1614
 
    int rc = TRPMQueryTrapAll(pVCpu, &u8TrapNo, &enmType, &uErrorCode, &uCR2);
1615
 
    if (RT_FAILURE(rc))
1616
 
    {
1617
 
        AssertReleaseMsgFailed(("No trap! (rc=%Rrc)\n", rc));
1618
 
        return rc;
1619
 
    }
1620
 
 
1621
 
    /*
1622
 
     * Traps can be directly forwarded in hardware accelerated mode.
1623
 
     */
1624
 
    if (HWACCMIsEnabled(pVM))
1625
 
    {
1626
 
#ifdef LOGGING_ENABLED
1627
 
        DBGFR3InfoLog(pVM, "cpumguest", "Guest trap");
1628
 
        DBGFR3DisasInstrCurrentLog(pVCpu, "Guest trap");
1629
 
#endif
1630
 
        return VINF_EM_RESCHEDULE_HWACC;
1631
 
    }
1632
 
 
1633
 
#if 1 /* Experimental: Review, disable if it causes trouble. */
1634
 
    /*
1635
 
     * Handle traps in patch code first.
1636
 
     *
1637
 
     * We catch a few of these cases in RC before returning to R3 (#PF, #GP, #BP)
1638
 
     * but several traps isn't handled specially by TRPM in RC and we end up here
1639
 
     * instead. One example is #DE.
1640
 
     */
1641
 
    uint32_t uCpl = CPUMGetGuestCPL(pVCpu, CPUMCTX2CORE(pCtx));
1642
 
    if (    uCpl == 0
1643
 
        &&  PATMIsPatchGCAddr(pVM, (RTGCPTR)pCtx->eip))
1644
 
    {
1645
 
        LogFlow(("emR3RawGuestTrap: trap %#x in patch code; eip=%08x\n", u8TrapNo, pCtx->eip));
1646
 
        return emR3PatchTrap(pVM, pVCpu, pCtx, rc);
1647
 
    }
1648
 
#endif
1649
 
 
1650
 
    /*
1651
 
     * If the guest gate is marked unpatched, then we will check again if we can patch it.
1652
 
     * (This assumes that we've already tried and failed to dispatch the trap in
1653
 
     * RC for the gates that already has been patched. Which is true for most high
1654
 
     * volume traps, because these are handled specially, but not for odd ones like #DE.)
1655
 
     */
1656
 
    if (TRPMR3GetGuestTrapHandler(pVM, u8TrapNo) == TRPM_INVALID_HANDLER)
1657
 
    {
1658
 
        CSAMR3CheckGates(pVM, u8TrapNo, 1);
1659
 
        Log(("emR3RawHandleRC: recheck gate %x -> valid=%d\n", u8TrapNo, TRPMR3GetGuestTrapHandler(pVM, u8TrapNo) != TRPM_INVALID_HANDLER));
1660
 
 
1661
 
        /* If it was successful, then we could go back to raw mode. */
1662
 
        if (TRPMR3GetGuestTrapHandler(pVM, u8TrapNo) != TRPM_INVALID_HANDLER)
1663
 
        {
1664
 
            /* Must check pending forced actions as our IDT or GDT might be out of sync. */
1665
 
            rc = EMR3CheckRawForcedActions(pVM, pVCpu);
1666
 
            AssertRCReturn(rc, rc);
1667
 
 
1668
 
            TRPMERRORCODE enmError = uErrorCode != ~0U
1669
 
                                   ? TRPM_TRAP_HAS_ERRORCODE
1670
 
                                   : TRPM_TRAP_NO_ERRORCODE;
1671
 
            rc = TRPMForwardTrap(pVCpu, CPUMCTX2CORE(pCtx), u8TrapNo, uErrorCode, enmError, TRPM_TRAP, -1);
1672
 
            if (rc == VINF_SUCCESS /* Don't use RT_SUCCESS */)
1673
 
            {
1674
 
                TRPMResetTrap(pVCpu);
1675
 
                return VINF_EM_RESCHEDULE_RAW;
1676
 
            }
1677
 
            AssertMsg(rc == VINF_EM_RAW_GUEST_TRAP, ("%Rrc\n", rc));
1678
 
        }
1679
 
    }
1680
 
 
1681
 
    /*
1682
 
     * Scan kernel code that traps; we might not get another chance.
1683
 
     */
1684
 
    /** @todo move this up before the dispatching? */
1685
 
    if (    (pCtx->ss & X86_SEL_RPL) <= 1
1686
 
        &&  !pCtx->eflags.Bits.u1VM)
1687
 
    {
1688
 
        Assert(!PATMIsPatchGCAddr(pVM, pCtx->eip));
1689
 
        CSAMR3CheckCodeEx(pVM, CPUMCTX2CORE(pCtx), pCtx->eip);
1690
 
    }
1691
 
 
1692
 
    /*
1693
 
     * Trap specific handling.
1694
 
     */
1695
 
    if (u8TrapNo == 6) /* (#UD) Invalid opcode. */
1696
 
    {
1697
 
        /*
1698
 
         * If MONITOR & MWAIT are supported, then interpret them here.
1699
 
         */
1700
 
        DISCPUSTATE cpu;
1701
 
        rc = CPUMR3DisasmInstrCPU(pVM, pVCpu, pCtx, pCtx->rip, &cpu, "Guest Trap (#UD): ");
1702
 
        if (    RT_SUCCESS(rc)
1703
 
            && (cpu.pCurInstr->opcode == OP_MONITOR || cpu.pCurInstr->opcode == OP_MWAIT))
1704
 
        {
1705
 
            uint32_t u32Dummy, u32Features, u32ExtFeatures;
1706
 
            CPUMGetGuestCpuId(pVCpu, 1, &u32Dummy, &u32Dummy, &u32ExtFeatures, &u32Features);
1707
 
            if (u32ExtFeatures & X86_CPUID_FEATURE_ECX_MONITOR)
1708
 
            {
1709
 
                rc = TRPMResetTrap(pVCpu);
1710
 
                AssertRC(rc);
1711
 
 
1712
 
                uint32_t opsize;
1713
 
                rc = EMInterpretInstructionCPU(pVM, pVCpu, &cpu, CPUMCTX2CORE(pCtx), 0, &opsize);
1714
 
                if (RT_SUCCESS(rc))
1715
 
                {
1716
 
                    pCtx->rip += cpu.opsize;
1717
 
#ifdef EM_NOTIFY_HWACCM
1718
 
                    if (pVCpu->em.s.enmState == EMSTATE_DEBUG_GUEST_HWACC)
1719
 
                        HWACCMR3NotifyEmulated(pVCpu);
1720
 
#endif
1721
 
                    return rc;
1722
 
                }
1723
 
                return emR3RawExecuteInstruction(pVM, pVCpu, "Monitor: ");
1724
 
            }
1725
 
        }
1726
 
    }
1727
 
    else if (u8TrapNo == 13) /* (#GP) Privileged exception */
1728
 
    {
1729
 
        /*
1730
 
         * Handle I/O bitmap?
1731
 
         */
1732
 
        /** @todo We're not supposed to be here with a false guest trap concerning
1733
 
         *        I/O access. We can easily handle those in RC.  */
1734
 
        DISCPUSTATE cpu;
1735
 
        rc = CPUMR3DisasmInstrCPU(pVM, pVCpu, pCtx, pCtx->rip, &cpu, "Guest Trap: ");
1736
 
        if (    RT_SUCCESS(rc)
1737
 
            &&  (cpu.pCurInstr->optype & OPTYPE_PORTIO))
1738
 
        {
1739
 
            /*
1740
 
             * We should really check the TSS for the IO bitmap, but it's not like this
1741
 
             * lazy approach really makes things worse.
1742
 
             */
1743
 
            rc = TRPMResetTrap(pVCpu);
1744
 
            AssertRC(rc);
1745
 
            return emR3RawExecuteInstruction(pVM, pVCpu, "IO Guest Trap: ");
1746
 
        }
1747
 
    }
1748
 
 
1749
 
#ifdef LOG_ENABLED
1750
 
    DBGFR3InfoLog(pVM, "cpumguest", "Guest trap");
1751
 
    DBGFR3DisasInstrCurrentLog(pVCpu, "Guest trap");
1752
 
 
1753
 
    /* Get guest page information. */
1754
 
    uint64_t    fFlags = 0;
1755
 
    RTGCPHYS    GCPhys = 0;
1756
 
    int rc2 = PGMGstGetPage(pVCpu, uCR2, &fFlags, &GCPhys);
1757
 
    Log(("emR3RawGuestTrap: cs:eip=%04x:%08x: trap=%02x err=%08x cr2=%08x cr0=%08x%s: Phys=%RGp fFlags=%08llx %s %s %s%s rc2=%d\n",
1758
 
         pCtx->cs, pCtx->eip, u8TrapNo, uErrorCode, uCR2, (uint32_t)pCtx->cr0, (enmType == TRPM_SOFTWARE_INT) ? " software" : "",  GCPhys, fFlags,
1759
 
         fFlags & X86_PTE_P  ? "P " : "NP", fFlags & X86_PTE_US ? "U"  : "S",
1760
 
         fFlags & X86_PTE_RW ? "RW" : "R0", fFlags & X86_PTE_G  ? " G" : "", rc2));
1761
 
#endif
1762
 
 
1763
 
    /*
1764
 
     * #PG has CR2.
1765
 
     * (Because of stuff like above we must set CR2 in a delayed fashion.)
1766
 
     */
1767
 
    if (u8TrapNo == 14 /* #PG */)
1768
 
        pCtx->cr2 = uCR2;
1769
 
 
1770
 
    return VINF_EM_RESCHEDULE_REM;
1771
 
}
1772
 
 
1773
 
 
1774
 
/**
1775
 
 * Handle a ring switch trap.
1776
 
 * Need to do statistics and to install patches. The result is going to REM.
1777
 
 *
1778
 
 * @returns VBox status code suitable for EM.
1779
 
 * @param   pVM     VM handle.
1780
 
 * @param   pVCpu       VMCPU handle.
1781
 
 */
1782
 
int emR3RawRingSwitch(PVM pVM, PVMCPU pVCpu)
1783
 
{
1784
 
    int         rc;
1785
 
    DISCPUSTATE Cpu;
1786
 
    PCPUMCTX    pCtx = pVCpu->em.s.pCtx;
1787
 
 
1788
 
    /*
1789
 
     * sysenter, syscall & callgate
1790
 
     */
1791
 
    rc = CPUMR3DisasmInstrCPU(pVM, pVCpu, pCtx, pCtx->rip, &Cpu, "RSWITCH: ");
1792
 
    if (RT_SUCCESS(rc))
1793
 
    {
1794
 
        if (Cpu.pCurInstr->opcode == OP_SYSENTER)
1795
 
        {
1796
 
            if (pCtx->SysEnter.cs != 0)
1797
 
            {
1798
 
                rc = PATMR3InstallPatch(pVM, SELMToFlat(pVM, DIS_SELREG_CS, CPUMCTX2CORE(pCtx), pCtx->eip),
1799
 
                                        (SELMGetCpuModeFromSelector(pVM, pCtx->eflags, pCtx->cs, &pCtx->csHid) == CPUMODE_32BIT) ? PATMFL_CODE32 : 0);
1800
 
                if (RT_SUCCESS(rc))
1801
 
                {
1802
 
                    DBGFR3DisasInstrCurrentLog(pVCpu, "Patched sysenter instruction");
1803
 
                    return VINF_EM_RESCHEDULE_RAW;
1804
 
                }
1805
 
            }
1806
 
        }
1807
 
 
1808
 
#ifdef VBOX_WITH_STATISTICS
1809
 
        switch (Cpu.pCurInstr->opcode)
1810
 
        {
1811
 
            case OP_SYSENTER:
1812
 
                STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->StatSysEnter);
1813
 
                break;
1814
 
            case OP_SYSEXIT:
1815
 
                STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->StatSysExit);
1816
 
                break;
1817
 
            case OP_SYSCALL:
1818
 
                STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->StatSysCall);
1819
 
                break;
1820
 
            case OP_SYSRET:
1821
 
                STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->StatSysRet);
1822
 
                break;
1823
 
        }
1824
 
#endif
1825
 
    }
1826
 
    else
1827
 
        AssertRC(rc);
1828
 
 
1829
 
    /* go to the REM to emulate a single instruction */
1830
 
    return emR3RawExecuteInstruction(pVM, pVCpu, "RSWITCH: ");
1831
 
}
1832
 
 
1833
 
 
1834
 
/**
1835
 
 * Handle a trap (\#PF or \#GP) in patch code
1836
 
 *
1837
 
 * @returns VBox status code suitable for EM.
1838
 
 * @param   pVM     VM handle.
1839
 
 * @param   pVCpu   VMCPU handle.
1840
 
 * @param   pCtx    CPU context
1841
 
 * @param   gcret   GC return code
1842
 
 */
1843
 
static int emR3PatchTrap(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, int gcret)
1844
 
{
1845
 
    uint8_t         u8TrapNo;
1846
 
    int             rc;
1847
 
    TRPMEVENT       enmType;
1848
 
    RTGCUINT        uErrorCode;
1849
 
    RTGCUINTPTR     uCR2;
1850
 
 
1851
 
    Assert(PATMIsPatchGCAddr(pVM, pCtx->eip));
1852
 
 
1853
 
    if (gcret == VINF_PATM_PATCH_INT3)
1854
 
    {
1855
 
        u8TrapNo   = 3;
1856
 
        uCR2       = 0;
1857
 
        uErrorCode = 0;
1858
 
    }
1859
 
    else if (gcret == VINF_PATM_PATCH_TRAP_GP)
1860
 
    {
1861
 
        /* No active trap in this case. Kind of ugly. */
1862
 
        u8TrapNo   = X86_XCPT_GP;
1863
 
        uCR2       = 0;
1864
 
        uErrorCode = 0;
1865
 
    }
1866
 
    else
1867
 
    {
1868
 
        rc = TRPMQueryTrapAll(pVCpu, &u8TrapNo, &enmType, &uErrorCode, &uCR2);
1869
 
        if (RT_FAILURE(rc))
1870
 
        {
1871
 
            AssertReleaseMsgFailed(("emR3PatchTrap: no trap! (rc=%Rrc) gcret=%Rrc\n", rc, gcret));
1872
 
            return rc;
1873
 
        }
1874
 
        /* Reset the trap as we'll execute the original instruction again. */
1875
 
        TRPMResetTrap(pVCpu);
1876
 
    }
1877
 
 
1878
 
    /*
1879
 
     * Deal with traps inside patch code.
1880
 
     * (This code won't run outside GC.)
1881
 
     */
1882
 
    if (u8TrapNo != 1)
1883
 
    {
1884
 
#ifdef LOG_ENABLED
1885
 
        DBGFR3InfoLog(pVM, "cpumguest", "Trap in patch code");
1886
 
        DBGFR3DisasInstrCurrentLog(pVCpu, "Patch code");
1887
 
 
1888
 
        DISCPUSTATE Cpu;
1889
 
        int         rc;
1890
 
 
1891
 
        rc = CPUMR3DisasmInstrCPU(pVM, pVCpu, pCtx, pCtx->eip, &Cpu, "Patch code: ");
1892
 
        if (    RT_SUCCESS(rc)
1893
 
            &&  Cpu.pCurInstr->opcode == OP_IRET)
1894
 
        {
1895
 
            uint32_t eip, selCS, uEFlags;
1896
 
 
1897
 
            /* Iret crashes are bad as we have already changed the flags on the stack */
1898
 
            rc  = PGMPhysSimpleReadGCPtr(pVCpu, &eip,     pCtx->esp, 4);
1899
 
            rc |= PGMPhysSimpleReadGCPtr(pVCpu, &selCS,   pCtx->esp+4, 4);
1900
 
            rc |= PGMPhysSimpleReadGCPtr(pVCpu, &uEFlags, pCtx->esp+8, 4);
1901
 
            if (rc == VINF_SUCCESS)
1902
 
            {
1903
 
                if (    (uEFlags & X86_EFL_VM)
1904
 
                    ||  (selCS & X86_SEL_RPL) == 3)
1905
 
                {
1906
 
                    uint32_t selSS, esp;
1907
 
 
1908
 
                    rc |= PGMPhysSimpleReadGCPtr(pVCpu, &esp,     pCtx->esp + 12, 4);
1909
 
                    rc |= PGMPhysSimpleReadGCPtr(pVCpu, &selSS,   pCtx->esp + 16, 4);
1910
 
 
1911
 
                    if (uEFlags & X86_EFL_VM)
1912
 
                    {
1913
 
                        uint32_t selDS, selES, selFS, selGS;
1914
 
                        rc  = PGMPhysSimpleReadGCPtr(pVCpu, &selES,   pCtx->esp + 20, 4);
1915
 
                        rc |= PGMPhysSimpleReadGCPtr(pVCpu, &selDS,   pCtx->esp + 24, 4);
1916
 
                        rc |= PGMPhysSimpleReadGCPtr(pVCpu, &selFS,   pCtx->esp + 28, 4);
1917
 
                        rc |= PGMPhysSimpleReadGCPtr(pVCpu, &selGS,   pCtx->esp + 32, 4);
1918
 
                        if (rc == VINF_SUCCESS)
1919
 
                        {
1920
 
                            Log(("Patch code: IRET->VM stack frame: return address %04X:%08RX32 eflags=%08x ss:esp=%04X:%08RX32\n", selCS, eip, uEFlags, selSS, esp));
1921
 
                            Log(("Patch code: IRET->VM stack frame: DS=%04X ES=%04X FS=%04X GS=%04X\n", selDS, selES, selFS, selGS));
1922
 
                        }
1923
 
                    }
1924
 
                    else
1925
 
                        Log(("Patch code: IRET stack frame: return address %04X:%08RX32 eflags=%08x ss:esp=%04X:%08RX32\n", selCS, eip, uEFlags, selSS, esp));
1926
 
                }
1927
 
                else
1928
 
                    Log(("Patch code: IRET stack frame: return address %04X:%08RX32 eflags=%08x\n", selCS, eip, uEFlags));
1929
 
            }
1930
 
        }
1931
 
#endif /* LOG_ENABLED */
1932
 
        Log(("emR3PatchTrap: in patch: eip=%08x: trap=%02x err=%08x cr2=%08x cr0=%08x\n",
1933
 
             pCtx->eip, u8TrapNo, uErrorCode, uCR2, (uint32_t)pCtx->cr0));
1934
 
 
1935
 
        RTGCPTR pNewEip;
1936
 
        rc = PATMR3HandleTrap(pVM, pCtx, pCtx->eip, &pNewEip);
1937
 
        switch (rc)
1938
 
        {
1939
 
            /*
1940
 
             * Execute the faulting instruction.
1941
 
             */
1942
 
            case VINF_SUCCESS:
1943
 
            {
1944
 
                /** @todo execute a whole block */
1945
 
                Log(("emR3PatchTrap: Executing faulting instruction at new address %RGv\n", pNewEip));
1946
 
                if (!(pVCpu->em.s.pPatmGCState->uVMFlags & X86_EFL_IF))
1947
 
                    Log(("emR3PatchTrap: Virtual IF flag disabled!!\n"));
1948
 
 
1949
 
                pCtx->eip = pNewEip;
1950
 
                AssertRelease(pCtx->eip);
1951
 
 
1952
 
                if (pCtx->eflags.Bits.u1IF)
1953
 
                {
1954
 
                    /* Windows XP lets irets fault intentionally and then takes action based on the opcode; an
1955
 
                     * int3 patch overwrites it and leads to blue screens. Remove the patch in this case.
1956
 
                     */
1957
 
                    if (    u8TrapNo == X86_XCPT_GP
1958
 
                        &&  PATMIsInt3Patch(pVM, pCtx->eip, NULL, NULL))
1959
 
                    {
1960
 
                        /** @todo move to PATMR3HandleTrap */
1961
 
                        Log(("Possible Windows XP iret fault at %08RX32\n", pCtx->eip));
1962
 
                        PATMR3RemovePatch(pVM, pCtx->eip);
1963
 
                    }
1964
 
 
1965
 
                    /** @todo Knoppix 5 regression when returning VINF_SUCCESS here and going back to raw mode. */
1966
 
                    /* Note: possibly because a reschedule is required (e.g. iret to V86 code) */
1967
 
 
1968
 
                    return emR3RawExecuteInstruction(pVM, pVCpu, "PATCHIR");
1969
 
                    /* Interrupts are enabled; just go back to the original instruction.
1970
 
                    return VINF_SUCCESS; */
1971
 
                }
1972
 
                return VINF_EM_RESCHEDULE_REM;
1973
 
            }
1974
 
 
1975
 
            /*
1976
 
             * One instruction.
1977
 
             */
1978
 
            case VINF_PATCH_EMULATE_INSTR:
1979
 
                Log(("emR3PatchTrap: Emulate patched instruction at %RGv IF=%d VMIF=%x\n",
1980
 
                     pNewEip, pCtx->eflags.Bits.u1IF, pVCpu->em.s.pPatmGCState->uVMFlags));
1981
 
                pCtx->eip = pNewEip;
1982
 
                AssertRelease(pCtx->eip);
1983
 
                return emR3RawExecuteInstruction(pVM, pVCpu, "PATCHEMUL: ");
1984
 
 
1985
 
            /*
1986
 
             * The patch was disabled, hand it to the REM.
1987
 
             */
1988
 
            case VERR_PATCH_DISABLED:
1989
 
                if (!(pVCpu->em.s.pPatmGCState->uVMFlags & X86_EFL_IF))
1990
 
                    Log(("emR3PatchTrap: Virtual IF flag disabled!!\n"));
1991
 
                pCtx->eip = pNewEip;
1992
 
                AssertRelease(pCtx->eip);
1993
 
 
1994
 
                if (pCtx->eflags.Bits.u1IF)
1995
 
                {
1996
 
                    /*
1997
 
                     * The last instruction in the patch block needs to be executed!! (sti/sysexit for example)
1998
 
                     */
1999
 
                    Log(("PATCH: IF=1 -> emulate last instruction as it can't be interrupted!!\n"));
2000
 
                    return emR3RawExecuteInstruction(pVM, pVCpu, "PATCHIR");
2001
 
                }
2002
 
                return VINF_EM_RESCHEDULE_REM;
2003
 
 
2004
 
            /* Force continued patch exection; usually due to write monitored stack. */
2005
 
            case VINF_PATCH_CONTINUE:
2006
 
                return VINF_SUCCESS;
2007
 
 
2008
 
            /*
2009
 
             * Anything else is *fatal*.
2010
 
             */
2011
 
            default:
2012
 
                AssertReleaseMsgFailed(("Unknown return code %Rrc from PATMR3HandleTrap!\n", rc));
2013
 
                return VERR_IPE_UNEXPECTED_STATUS;
2014
 
        }
2015
 
    }
2016
 
    return VINF_SUCCESS;
2017
 
}
2018
 
 
2019
 
 
2020
 
/**
2021
 
 * Handle a privileged instruction.
2022
 
 *
2023
 
 * @returns VBox status code suitable for EM.
2024
 
 * @param   pVM     VM handle.
2025
 
 * @param   pVCpu   VMCPU handle;
2026
 
 */
2027
 
int emR3RawPrivileged(PVM pVM, PVMCPU pVCpu)
2028
 
{
2029
 
    STAM_PROFILE_START(&pVCpu->em.s.StatPrivEmu, a);
2030
 
    PCPUMCTX    pCtx = pVCpu->em.s.pCtx;
2031
 
 
2032
 
    Assert(!pCtx->eflags.Bits.u1VM);
2033
 
 
2034
 
    if (PATMIsEnabled(pVM))
2035
 
    {
2036
 
        /*
2037
 
         * Check if in patch code.
2038
 
         */
2039
 
        if (PATMR3IsInsidePatchJump(pVM, pCtx->eip, NULL))
2040
 
        {
2041
 
#ifdef LOG_ENABLED
2042
 
            DBGFR3InfoLog(pVM, "cpumguest", "PRIV");
2043
 
#endif
2044
 
            AssertMsgFailed(("FATAL ERROR: executing random instruction inside generated patch jump %08X\n", pCtx->eip));
2045
 
            return VERR_EM_RAW_PATCH_CONFLICT;
2046
 
        }
2047
 
        if (   (pCtx->ss & X86_SEL_RPL) == 0
2048
 
            && !pCtx->eflags.Bits.u1VM
2049
 
            && !PATMIsPatchGCAddr(pVM, pCtx->eip))
2050
 
        {
2051
 
            int rc = PATMR3InstallPatch(pVM, SELMToFlat(pVM, DIS_SELREG_CS, CPUMCTX2CORE(pCtx), pCtx->eip),
2052
 
                                        (SELMGetCpuModeFromSelector(pVM, pCtx->eflags, pCtx->cs, &pCtx->csHid) == CPUMODE_32BIT) ? PATMFL_CODE32 : 0);
2053
 
            if (RT_SUCCESS(rc))
2054
 
            {
2055
 
#ifdef LOG_ENABLED
2056
 
                DBGFR3InfoLog(pVM, "cpumguest", "PRIV");
2057
 
#endif
2058
 
                DBGFR3DisasInstrCurrentLog(pVCpu, "Patched privileged instruction");
2059
 
                return VINF_SUCCESS;
2060
 
            }
2061
 
        }
2062
 
    }
2063
 
 
2064
 
#ifdef LOG_ENABLED
2065
 
    if (!PATMIsPatchGCAddr(pVM, pCtx->eip))
2066
 
    {
2067
 
        DBGFR3InfoLog(pVM, "cpumguest", "PRIV");
2068
 
        DBGFR3DisasInstrCurrentLog(pVCpu, "Privileged instr: ");
2069
 
    }
2070
 
#endif
2071
 
 
2072
 
    /*
2073
 
     * Instruction statistics and logging.
2074
 
     */
2075
 
    DISCPUSTATE Cpu;
2076
 
    int         rc;
2077
 
 
2078
 
    rc = CPUMR3DisasmInstrCPU(pVM, pVCpu, pCtx, pCtx->rip, &Cpu, "PRIV: ");
2079
 
    if (RT_SUCCESS(rc))
2080
 
    {
2081
 
#ifdef VBOX_WITH_STATISTICS
2082
 
        PEMSTATS pStats = pVCpu->em.s.CTX_SUFF(pStats);
2083
 
        switch (Cpu.pCurInstr->opcode)
2084
 
        {
2085
 
            case OP_INVLPG:
2086
 
                STAM_COUNTER_INC(&pStats->StatInvlpg);
2087
 
                break;
2088
 
            case OP_IRET:
2089
 
                STAM_COUNTER_INC(&pStats->StatIret);
2090
 
                break;
2091
 
            case OP_CLI:
2092
 
                STAM_COUNTER_INC(&pStats->StatCli);
2093
 
                emR3RecordCli(pVM, pVCpu, pCtx->rip);
2094
 
                break;
2095
 
            case OP_STI:
2096
 
                STAM_COUNTER_INC(&pStats->StatSti);
2097
 
                break;
2098
 
            case OP_INSB:
2099
 
            case OP_INSWD:
2100
 
            case OP_IN:
2101
 
            case OP_OUTSB:
2102
 
            case OP_OUTSWD:
2103
 
            case OP_OUT:
2104
 
                AssertMsgFailed(("Unexpected privileged exception due to port IO\n"));
2105
 
                break;
2106
 
 
2107
 
            case OP_MOV_CR:
2108
 
                if (Cpu.param1.flags & USE_REG_GEN32)
2109
 
                {
2110
 
                    //read
2111
 
                    Assert(Cpu.param2.flags & USE_REG_CR);
2112
 
                    Assert(Cpu.param2.base.reg_ctrl <= USE_REG_CR4);
2113
 
                    STAM_COUNTER_INC(&pStats->StatMovReadCR[Cpu.param2.base.reg_ctrl]);
2114
 
                }
2115
 
                else
2116
 
                {
2117
 
                    //write
2118
 
                    Assert(Cpu.param1.flags & USE_REG_CR);
2119
 
                    Assert(Cpu.param1.base.reg_ctrl <= USE_REG_CR4);
2120
 
                    STAM_COUNTER_INC(&pStats->StatMovWriteCR[Cpu.param1.base.reg_ctrl]);
2121
 
                }
2122
 
                break;
2123
 
 
2124
 
            case OP_MOV_DR:
2125
 
                STAM_COUNTER_INC(&pStats->StatMovDRx);
2126
 
                break;
2127
 
            case OP_LLDT:
2128
 
                STAM_COUNTER_INC(&pStats->StatMovLldt);
2129
 
                break;
2130
 
            case OP_LIDT:
2131
 
                STAM_COUNTER_INC(&pStats->StatMovLidt);
2132
 
                break;
2133
 
            case OP_LGDT:
2134
 
                STAM_COUNTER_INC(&pStats->StatMovLgdt);
2135
 
                break;
2136
 
            case OP_SYSENTER:
2137
 
                STAM_COUNTER_INC(&pStats->StatSysEnter);
2138
 
                break;
2139
 
            case OP_SYSEXIT:
2140
 
                STAM_COUNTER_INC(&pStats->StatSysExit);
2141
 
                break;
2142
 
            case OP_SYSCALL:
2143
 
                STAM_COUNTER_INC(&pStats->StatSysCall);
2144
 
                break;
2145
 
            case OP_SYSRET:
2146
 
                STAM_COUNTER_INC(&pStats->StatSysRet);
2147
 
                break;
2148
 
            case OP_HLT:
2149
 
                STAM_COUNTER_INC(&pStats->StatHlt);
2150
 
                break;
2151
 
            default:
2152
 
                STAM_COUNTER_INC(&pStats->StatMisc);
2153
 
                Log4(("emR3RawPrivileged: opcode=%d\n", Cpu.pCurInstr->opcode));
2154
 
                break;
2155
 
        }
2156
 
#endif /* VBOX_WITH_STATISTICS */
2157
 
        if (    (pCtx->ss & X86_SEL_RPL) == 0
2158
 
            &&  !pCtx->eflags.Bits.u1VM
2159
 
            &&  SELMGetCpuModeFromSelector(pVM, pCtx->eflags, pCtx->cs, &pCtx->csHid) == CPUMODE_32BIT)
2160
 
        {
2161
 
            uint32_t size;
2162
 
 
2163
 
            STAM_PROFILE_START(&pVCpu->em.s.StatPrivEmu, a);
2164
 
            switch (Cpu.pCurInstr->opcode)
2165
 
            {
2166
 
                case OP_CLI:
2167
 
                    pCtx->eflags.u32 &= ~X86_EFL_IF;
2168
 
                    Assert(Cpu.opsize == 1);
2169
 
                    pCtx->rip += Cpu.opsize;
2170
 
                    STAM_PROFILE_STOP(&pVCpu->em.s.StatPrivEmu, a);
2171
 
                    return VINF_EM_RESCHEDULE_REM; /* must go to the recompiler now! */
2172
 
 
2173
 
                case OP_STI:
2174
 
                    pCtx->eflags.u32 |= X86_EFL_IF;
2175
 
                    EMSetInhibitInterruptsPC(pVCpu, pCtx->rip + Cpu.opsize);
2176
 
                    Assert(Cpu.opsize == 1);
2177
 
                    pCtx->rip += Cpu.opsize;
2178
 
                    STAM_PROFILE_STOP(&pVCpu->em.s.StatPrivEmu, a);
2179
 
                    return VINF_SUCCESS;
2180
 
 
2181
 
                case OP_HLT:
2182
 
                    if (PATMIsPatchGCAddr(pVM, (RTGCPTR)pCtx->eip))
2183
 
                    {
2184
 
                        PATMTRANSSTATE  enmState;
2185
 
                        RTGCPTR         pOrgInstrGC = PATMR3PatchToGCPtr(pVM, pCtx->eip, &enmState);
2186
 
 
2187
 
                        if (enmState == PATMTRANS_OVERWRITTEN)
2188
 
                        {
2189
 
                            rc = PATMR3DetectConflict(pVM, pOrgInstrGC, pOrgInstrGC);
2190
 
                            Assert(rc == VERR_PATCH_DISABLED);
2191
 
                            /* Conflict detected, patch disabled */
2192
 
                            Log(("emR3RawPrivileged: detected conflict -> disabled patch at %08RX32\n", pCtx->eip));
2193
 
 
2194
 
                            enmState = PATMTRANS_SAFE;
2195
 
                        }
2196
 
 
2197
 
                        /* The translation had better be successful. Otherwise we can't recover. */
2198
 
                        AssertReleaseMsg(pOrgInstrGC && enmState != PATMTRANS_OVERWRITTEN, ("Unable to translate instruction address at %08RX32\n", pCtx->eip));
2199
 
                        if (enmState != PATMTRANS_OVERWRITTEN)
2200
 
                            pCtx->eip = pOrgInstrGC;
2201
 
                    }
2202
 
                    /* no break; we could just return VINF_EM_HALT here */
2203
 
 
2204
 
                case OP_MOV_CR:
2205
 
                case OP_MOV_DR:
2206
 
#ifdef LOG_ENABLED
2207
 
                    if (PATMIsPatchGCAddr(pVM, pCtx->eip))
2208
 
                    {
2209
 
                        DBGFR3InfoLog(pVM, "cpumguest", "PRIV");
2210
 
                        DBGFR3DisasInstrCurrentLog(pVCpu, "Privileged instr: ");
2211
 
                    }
2212
 
#endif
2213
 
 
2214
 
                    rc = EMInterpretInstructionCPU(pVM, pVCpu, &Cpu, CPUMCTX2CORE(pCtx), 0, &size);
2215
 
                    if (RT_SUCCESS(rc))
2216
 
                    {
2217
 
                        pCtx->rip += Cpu.opsize;
2218
 
#ifdef EM_NOTIFY_HWACCM
2219
 
                        if (pVCpu->em.s.enmState == EMSTATE_DEBUG_GUEST_HWACC)
2220
 
                            HWACCMR3NotifyEmulated(pVCpu);
2221
 
#endif
2222
 
                        STAM_PROFILE_STOP(&pVCpu->em.s.StatPrivEmu, a);
2223
 
 
2224
 
                        if (    Cpu.pCurInstr->opcode == OP_MOV_CR
2225
 
                            &&  Cpu.param1.flags == USE_REG_CR /* write */
2226
 
                           )
2227
 
                        {
2228
 
                            /* Deal with CR0 updates inside patch code that force
2229
 
                             * us to go to the recompiler.
2230
 
                             */
2231
 
                            if (   PATMIsPatchGCAddr(pVM, pCtx->rip)
2232
 
                                && (pCtx->cr0 & (X86_CR0_WP|X86_CR0_PG|X86_CR0_PE)) != (X86_CR0_WP|X86_CR0_PG|X86_CR0_PE))
2233
 
                            {
2234
 
                                PATMTRANSSTATE  enmState;
2235
 
                                RTGCPTR         pOrgInstrGC = PATMR3PatchToGCPtr(pVM, pCtx->rip, &enmState);
2236
 
 
2237
 
                                Log(("Force recompiler switch due to cr0 (%RGp) update rip=%RGv -> %RGv (enmState=%d)\n", pCtx->cr0, pCtx->rip, pOrgInstrGC, enmState));
2238
 
                                if (enmState == PATMTRANS_OVERWRITTEN)
2239
 
                                {
2240
 
                                    rc = PATMR3DetectConflict(pVM, pOrgInstrGC, pOrgInstrGC);
2241
 
                                    Assert(rc == VERR_PATCH_DISABLED);
2242
 
                                    /* Conflict detected, patch disabled */
2243
 
                                    Log(("emR3RawPrivileged: detected conflict -> disabled patch at %RGv\n", (RTGCPTR)pCtx->rip));
2244
 
                                    enmState = PATMTRANS_SAFE;
2245
 
                                }
2246
 
                                /* The translation had better be successful. Otherwise we can't recover. */
2247
 
                                AssertReleaseMsg(pOrgInstrGC && enmState != PATMTRANS_OVERWRITTEN, ("Unable to translate instruction address at %RGv\n", (RTGCPTR)pCtx->rip));
2248
 
                                if (enmState != PATMTRANS_OVERWRITTEN)
2249
 
                                    pCtx->rip = pOrgInstrGC;
2250
 
                            }
2251
 
 
2252
 
                            /* Reschedule is necessary as the execution/paging mode might have changed. */
2253
 
                            return VINF_EM_RESCHEDULE;
2254
 
                        }
2255
 
                        return rc; /* can return VINF_EM_HALT as well. */
2256
 
                    }
2257
 
                    AssertMsgReturn(rc == VERR_EM_INTERPRETER, ("%Rrc\n", rc), rc);
2258
 
                    break; /* fall back to the recompiler */
2259
 
            }
2260
 
            STAM_PROFILE_STOP(&pVCpu->em.s.StatPrivEmu, a);
2261
 
        }
2262
 
    }
2263
 
 
2264
 
    if (PATMIsPatchGCAddr(pVM, pCtx->eip))
2265
 
        return emR3PatchTrap(pVM, pVCpu, pCtx, VINF_PATM_PATCH_TRAP_GP);
2266
 
 
2267
 
    return emR3RawExecuteInstruction(pVM, pVCpu, "PRIV");
2268
 
}
2269
 
 
2270
 
 
2271
 
/**
2272
 
 * Update the forced rawmode execution modifier.
2273
 
 *
2274
 
 * This function is called when we're returning from the raw-mode loop(s). If we're
2275
 
 * in patch code, it will set a flag forcing execution to be resumed in raw-mode,
2276
 
 * if not in patch code, the flag will be cleared.
2277
 
 *
2278
 
 * We should never interrupt patch code while it's being executed. Cli patches can
2279
 
 * contain big code blocks, but they are always executed with IF=0. Other patches
2280
 
 * replace single instructions and should be atomic.
2281
 
 *
2282
 
 * @returns Updated rc.
2283
 
 *
2284
 
 * @param   pVM     The VM handle.
2285
 
 * @param   pVCpu   The VMCPU handle.
2286
 
 * @param   pCtx    The guest CPU context.
2287
 
 * @param   rc      The result code.
2288
 
 */
2289
 
DECLINLINE(int) emR3RawUpdateForceFlag(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, int rc)
2290
 
{
2291
 
    if (PATMIsPatchGCAddr(pVM, pCtx->eip)) /** @todo check cs selector base/type */
2292
 
    {
2293
 
        /* ignore reschedule attempts. */
2294
 
        switch (rc)
2295
 
        {
2296
 
            case VINF_EM_RESCHEDULE:
2297
 
            case VINF_EM_RESCHEDULE_REM:
2298
 
                LogFlow(("emR3RawUpdateForceFlag: patch address -> force raw reschedule\n"));
2299
 
                rc = VINF_SUCCESS;
2300
 
                break;
2301
 
        }
2302
 
        pVCpu->em.s.fForceRAW = true;
2303
 
    }
2304
 
    else
2305
 
        pVCpu->em.s.fForceRAW = false;
2306
 
    return rc;
2307
 
}
2308
 
 
2309
 
 
2310
 
/**
2311
 
 * Process a subset of the raw-mode return code.
2312
 
 *
2313
 
 * Since we have to share this with raw-mode single stepping, this inline
2314
 
 * function has been created to avoid code duplication.
2315
 
 *
2316
 
 * @returns VINF_SUCCESS if it's ok to continue raw mode.
2317
 
 * @returns VBox status code to return to the EM main loop.
2318
 
 *
2319
 
 * @param   pVM     The VM handle
2320
 
 * @param   pVCpu   The VMCPU handle
2321
 
 * @param   rc      The return code.
2322
 
 * @param   pCtx    The guest cpu context.
2323
 
 */
2324
 
DECLINLINE(int) emR3RawHandleRC(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, int rc)
2325
 
{
2326
 
    switch (rc)
2327
 
    {
2328
 
        /*
2329
 
         * Common & simple ones.
2330
 
         */
2331
 
        case VINF_SUCCESS:
2332
 
            break;
2333
 
        case VINF_EM_RESCHEDULE_RAW:
2334
 
        case VINF_EM_RESCHEDULE_HWACC:
2335
 
        case VINF_EM_RAW_INTERRUPT:
2336
 
        case VINF_EM_RAW_TO_R3:
2337
 
        case VINF_EM_RAW_TIMER_PENDING:
2338
 
        case VINF_EM_PENDING_REQUEST:
2339
 
            rc = VINF_SUCCESS;
2340
 
            break;
2341
 
 
2342
 
        /*
2343
 
         * Privileged instruction.
2344
 
         */
2345
 
        case VINF_EM_RAW_EXCEPTION_PRIVILEGED:
2346
 
        case VINF_PATM_PATCH_TRAP_GP:
2347
 
            rc = emR3RawPrivileged(pVM, pVCpu);
2348
 
            break;
2349
 
 
2350
 
        /*
2351
 
         * Got a trap which needs dispatching.
2352
 
         */
2353
 
        case VINF_EM_RAW_GUEST_TRAP:
2354
 
            if (PATMR3IsInsidePatchJump(pVM, pCtx->eip, NULL))
2355
 
            {
2356
 
                AssertReleaseMsgFailed(("FATAL ERROR: executing random instruction inside generated patch jump %08X\n", CPUMGetGuestEIP(pVCpu)));
2357
 
                rc = VERR_EM_RAW_PATCH_CONFLICT;
2358
 
                break;
2359
 
            }
2360
 
            rc = emR3RawGuestTrap(pVM, pVCpu);
2361
 
            break;
2362
 
 
2363
 
        /*
2364
 
         * Trap in patch code.
2365
 
         */
2366
 
        case VINF_PATM_PATCH_TRAP_PF:
2367
 
        case VINF_PATM_PATCH_INT3:
2368
 
            rc = emR3PatchTrap(pVM, pVCpu, pCtx, rc);
2369
 
            break;
2370
 
 
2371
 
        case VINF_PATM_DUPLICATE_FUNCTION:
2372
 
            Assert(PATMIsPatchGCAddr(pVM, (RTGCPTR)pCtx->eip));
2373
 
            rc = PATMR3DuplicateFunctionRequest(pVM, pCtx);
2374
 
            AssertRC(rc);
2375
 
            rc = VINF_SUCCESS;
2376
 
            break;
2377
 
 
2378
 
        case VINF_PATM_CHECK_PATCH_PAGE:
2379
 
            rc = PATMR3HandleMonitoredPage(pVM);
2380
 
            AssertRC(rc);
2381
 
            rc = VINF_SUCCESS;
2382
 
            break;
2383
 
 
2384
 
        /*
2385
 
         * Patch manager.
2386
 
         */
2387
 
        case VERR_EM_RAW_PATCH_CONFLICT:
2388
 
            AssertReleaseMsgFailed(("%Rrc handling is not yet implemented\n", rc));
2389
 
            break;
2390
 
 
2391
 
#ifdef VBOX_WITH_VMI
2392
 
        /*
2393
 
         * PARAV function.
2394
 
         */
2395
 
        case VINF_EM_RESCHEDULE_PARAV:
2396
 
            rc = PARAVCallFunction(pVM);
2397
 
            break;
2398
 
#endif
2399
 
 
2400
 
        /*
2401
 
         * Memory mapped I/O access - attempt to patch the instruction
2402
 
         */
2403
 
        case VINF_PATM_HC_MMIO_PATCH_READ:
2404
 
            rc = PATMR3InstallPatch(pVM, SELMToFlat(pVM, DIS_SELREG_CS, CPUMCTX2CORE(pCtx), pCtx->eip),
2405
 
                                    PATMFL_MMIO_ACCESS | ((SELMGetCpuModeFromSelector(pVM, pCtx->eflags, pCtx->cs, &pCtx->csHid) == CPUMODE_32BIT) ? PATMFL_CODE32 : 0));
2406
 
            if (RT_FAILURE(rc))
2407
 
                rc = emR3RawExecuteInstruction(pVM, pVCpu, "MMIO");
2408
 
            break;
2409
 
 
2410
 
        case VINF_PATM_HC_MMIO_PATCH_WRITE:
2411
 
            AssertFailed(); /* not yet implemented. */
2412
 
            rc = emR3RawExecuteInstruction(pVM, pVCpu, "MMIO");
2413
 
            break;
2414
 
 
2415
 
        /*
2416
 
         * Conflict or out of page tables.
2417
 
         *
2418
 
         * VM_FF_PGM_SYNC_CR3 is set by the hypervisor and all we need to
2419
 
         * do here is to execute the pending forced actions.
2420
 
         */
2421
 
        case VINF_PGM_SYNC_CR3:
2422
 
            AssertMsg(VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL),
2423
 
                      ("VINF_PGM_SYNC_CR3 and no VMCPU_FF_PGM_SYNC_CR3*!\n"));
2424
 
            rc = VINF_SUCCESS;
2425
 
            break;
2426
 
 
2427
 
        /*
2428
 
         * Paging mode change.
2429
 
         */
2430
 
        case VINF_PGM_CHANGE_MODE:
2431
 
            rc = PGMChangeMode(pVCpu, pCtx->cr0, pCtx->cr4, pCtx->msrEFER);
2432
 
            if (rc == VINF_SUCCESS)
2433
 
                rc = VINF_EM_RESCHEDULE;
2434
 
            AssertMsg(RT_FAILURE(rc) || (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST), ("%Rrc\n", rc));
2435
 
            break;
2436
 
 
2437
 
        /*
2438
 
         * CSAM wants to perform a task in ring-3. It has set an FF action flag.
2439
 
         */
2440
 
        case VINF_CSAM_PENDING_ACTION:
2441
 
            rc = VINF_SUCCESS;
2442
 
            break;
2443
 
 
2444
 
        /*
2445
 
         * Invoked Interrupt gate - must directly (!) go to the recompiler.
2446
 
         */
2447
 
        case VINF_EM_RAW_INTERRUPT_PENDING:
2448
 
        case VINF_EM_RAW_RING_SWITCH_INT:
2449
 
            Assert(TRPMHasTrap(pVCpu));
2450
 
            Assert(!PATMIsPatchGCAddr(pVM, (RTGCPTR)pCtx->eip));
2451
 
 
2452
 
            if (TRPMHasTrap(pVCpu))
2453
 
            {
2454
 
                /* If the guest gate is marked unpatched, then we will check again if we can patch it. */
2455
 
                uint8_t u8Interrupt = TRPMGetTrapNo(pVCpu);
2456
 
                if (TRPMR3GetGuestTrapHandler(pVM, u8Interrupt) == TRPM_INVALID_HANDLER)
2457
 
                {
2458
 
                    CSAMR3CheckGates(pVM, u8Interrupt, 1);
2459
 
                    Log(("emR3RawHandleRC: recheck gate %x -> valid=%d\n", u8Interrupt, TRPMR3GetGuestTrapHandler(pVM, u8Interrupt) != TRPM_INVALID_HANDLER));
2460
 
                    /* Note: If it was successful, then we could go back to raw mode, but let's keep things simple for now. */
2461
 
                }
2462
 
            }
2463
 
            rc = VINF_EM_RESCHEDULE_REM;
2464
 
            break;
2465
 
 
2466
 
        /*
2467
 
         * Other ring switch types.
2468
 
         */
2469
 
        case VINF_EM_RAW_RING_SWITCH:
2470
 
            rc = emR3RawRingSwitch(pVM, pVCpu);
2471
 
            break;
2472
 
 
2473
 
        /*
2474
 
         * I/O Port access - emulate the instruction.
2475
 
         */
2476
 
        case VINF_IOM_HC_IOPORT_READ:
2477
 
        case VINF_IOM_HC_IOPORT_WRITE:
2478
 
            rc = emR3RawExecuteIOInstruction(pVM, pVCpu);
2479
 
            break;
2480
 
 
2481
 
        /*
2482
 
         * Memory mapped I/O access - emulate the instruction.
2483
 
         */
2484
 
        case VINF_IOM_HC_MMIO_READ:
2485
 
        case VINF_IOM_HC_MMIO_WRITE:
2486
 
        case VINF_IOM_HC_MMIO_READ_WRITE:
2487
 
            rc = emR3RawExecuteInstruction(pVM, pVCpu, "MMIO");
2488
 
            break;
2489
 
 
2490
 
        /*
2491
 
         * (MM)IO intensive code block detected; fall back to the recompiler for better performance
2492
 
         */
2493
 
        case VINF_EM_RAW_EMULATE_IO_BLOCK:
2494
 
            rc = HWACCMR3EmulateIoBlock(pVM, pCtx);
2495
 
            break;
2496
 
 
2497
 
        /*
2498
 
         * Execute instruction.
2499
 
         */
2500
 
        case VINF_EM_RAW_EMULATE_INSTR_LDT_FAULT:
2501
 
            rc = emR3RawExecuteInstruction(pVM, pVCpu, "LDT FAULT: ");
2502
 
            break;
2503
 
        case VINF_EM_RAW_EMULATE_INSTR_GDT_FAULT:
2504
 
            rc = emR3RawExecuteInstruction(pVM, pVCpu, "GDT FAULT: ");
2505
 
            break;
2506
 
        case VINF_EM_RAW_EMULATE_INSTR_IDT_FAULT:
2507
 
            rc = emR3RawExecuteInstruction(pVM, pVCpu, "IDT FAULT: ");
2508
 
            break;
2509
 
        case VINF_EM_RAW_EMULATE_INSTR_TSS_FAULT:
2510
 
            rc = emR3RawExecuteInstruction(pVM, pVCpu, "TSS FAULT: ");
2511
 
            break;
2512
 
        case VINF_EM_RAW_EMULATE_INSTR_PD_FAULT:
2513
 
            rc = emR3RawExecuteInstruction(pVM, pVCpu, "PD FAULT: ");
2514
 
            break;
2515
 
 
2516
 
        case VINF_EM_RAW_EMULATE_INSTR_HLT:
2517
 
            /** @todo skip instruction and go directly to the halt state. (see REM for implementation details) */
2518
 
            rc = emR3RawPrivileged(pVM, pVCpu);
2519
 
            break;
2520
 
 
2521
 
        case VINF_PATM_PENDING_IRQ_AFTER_IRET:
2522
 
            rc = emR3RawExecuteInstruction(pVM, pVCpu, "EMUL: ", VINF_PATM_PENDING_IRQ_AFTER_IRET);
2523
 
            break;
2524
 
 
2525
 
        case VINF_EM_RAW_EMULATE_INSTR:
2526
 
        case VINF_PATCH_EMULATE_INSTR:
2527
 
            rc = emR3RawExecuteInstruction(pVM, pVCpu, "EMUL: ");
2528
 
            break;
2529
 
 
2530
 
        /*
2531
 
         * Stale selector and iret traps => REM.
2532
 
         */
2533
 
        case VINF_EM_RAW_STALE_SELECTOR:
2534
 
        case VINF_EM_RAW_IRET_TRAP:
2535
 
            /* We will not go to the recompiler if EIP points to patch code. */
2536
 
            if (PATMIsPatchGCAddr(pVM, pCtx->eip))
2537
 
            {
2538
 
                pCtx->eip = PATMR3PatchToGCPtr(pVM, (RTGCPTR)pCtx->eip, 0);
2539
 
            }
2540
 
            LogFlow(("emR3RawHandleRC: %Rrc -> %Rrc\n", rc, VINF_EM_RESCHEDULE_REM));
2541
 
            rc = VINF_EM_RESCHEDULE_REM;
2542
 
            break;
2543
 
 
2544
 
        /*
2545
 
         * Up a level.
2546
 
         */
2547
 
        case VINF_EM_TERMINATE:
2548
 
        case VINF_EM_OFF:
2549
 
        case VINF_EM_RESET:
2550
 
        case VINF_EM_SUSPEND:
2551
 
        case VINF_EM_HALT:
2552
 
        case VINF_EM_RESUME:
2553
 
        case VINF_EM_NO_MEMORY:
2554
 
        case VINF_EM_RESCHEDULE:
2555
 
        case VINF_EM_RESCHEDULE_REM:
2556
 
        case VINF_EM_WAIT_SIPI:
2557
 
            break;
2558
 
 
2559
 
        /*
2560
 
         * Up a level and invoke the debugger.
2561
 
         */
2562
 
        case VINF_EM_DBG_STEPPED:
2563
 
        case VINF_EM_DBG_BREAKPOINT:
2564
 
        case VINF_EM_DBG_STEP:
2565
 
        case VINF_EM_DBG_HYPER_BREAKPOINT:
2566
 
        case VINF_EM_DBG_HYPER_STEPPED:
2567
 
        case VINF_EM_DBG_HYPER_ASSERTION:
2568
 
        case VINF_EM_DBG_STOP:
2569
 
            break;
2570
 
 
2571
 
        /*
2572
 
         * Up a level, dump and debug.
2573
 
         */
2574
 
        case VERR_TRPM_DONT_PANIC:
2575
 
        case VERR_TRPM_PANIC:
2576
 
        case VERR_VMM_RING0_ASSERTION:
2577
 
        case VERR_VMM_HYPER_CR3_MISMATCH:
2578
 
        case VERR_VMM_RING3_CALL_DISABLED:
2579
 
            break;
2580
 
 
2581
 
        /*
2582
 
         * Up a level, after HwAccM have done some release logging.
2583
 
         */
2584
 
        case VERR_VMX_INVALID_VMCS_FIELD:
2585
 
        case VERR_VMX_INVALID_VMCS_PTR:
2586
 
        case VERR_VMX_INVALID_VMXON_PTR:
2587
 
        case VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_CODE:
2588
 
        case VERR_VMX_UNEXPECTED_EXCEPTION:
2589
 
        case VERR_VMX_UNEXPECTED_EXIT_CODE:
2590
 
        case VERR_VMX_INVALID_GUEST_STATE:
2591
 
        case VERR_VMX_UNABLE_TO_START_VM:
2592
 
        case VERR_VMX_UNABLE_TO_RESUME_VM:
2593
 
            HWACCMR3CheckError(pVM, rc);
2594
 
            break;
2595
 
        /*
2596
 
         * Anything which is not known to us means an internal error
2597
 
         * and the termination of the VM!
2598
 
         */
2599
 
        default:
2600
 
            AssertMsgFailed(("Unknown GC return code: %Rra\n", rc));
2601
 
            break;
2602
 
    }
2603
 
    return rc;
2604
 
}
2605
 
 
2606
 
 
2607
 
/**
2608
 
 * Check for pending raw actions
2609
 
 *
2610
 
 * @returns VBox status code. May return VINF_EM_NO_MEMORY but none of the other
2611
 
 *          EM statuses.
2612
 
 * @param   pVM         The VM to operate on.
2613
 
 * @param   pVCpu       The VMCPU handle.
2614
 
 */
2615
 
VMMR3DECL(int) EMR3CheckRawForcedActions(PVM pVM, PVMCPU pVCpu)
2616
 
{
2617
 
    return emR3RawForcedActions(pVM, pVCpu, pVCpu->em.s.pCtx);
2618
 
}
2619
 
 
2620
 
 
2621
 
/**
2622
 
 * Process raw-mode specific forced actions.
2623
 
 *
2624
 
 * This function is called when any FFs in the VM_FF_HIGH_PRIORITY_PRE_RAW_MASK is pending.
2625
 
 *
2626
 
 * @returns VBox status code. May return VINF_EM_NO_MEMORY but none of the other
2627
 
 *          EM statuses.
2628
 
 * @param   pVM         The VM handle.
2629
 
 * @param   pVCpu       The VMCPU handle.
2630
 
 * @param   pCtx        The guest CPUM register context.
2631
 
 */
2632
 
static int emR3RawForcedActions(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx)
2633
 
{
2634
 
    /*
2635
 
     * Note that the order is *vitally* important!
2636
 
     * Also note that SELMR3UpdateFromCPUM may trigger VM_FF_SELM_SYNC_TSS.
2637
 
     */
2638
 
 
2639
 
 
2640
 
    /*
2641
 
     * Sync selector tables.
2642
 
     */
2643
 
    if (VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_SELM_SYNC_GDT | VMCPU_FF_SELM_SYNC_LDT))
2644
 
    {
2645
 
        int rc = SELMR3UpdateFromCPUM(pVM, pVCpu);
2646
 
        if (RT_FAILURE(rc))
2647
 
            return rc;
2648
 
    }
2649
 
 
2650
 
    /*
2651
 
     * Sync IDT.
2652
 
     *
2653
 
     * The CSAMR3CheckGates call in TRPMR3SyncIDT may call PGMPrefetchPage
2654
 
     * and PGMShwModifyPage, so we're in for trouble if for instance a
2655
 
     * PGMSyncCR3+pgmPoolClearAll is pending.
2656
 
     */
2657
 
    if (VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_TRPM_SYNC_IDT))
2658
 
    {
2659
 
        if (   VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_PGM_SYNC_CR3)
2660
 
            && EMIsRawRing0Enabled(pVM)
2661
 
            && CSAMIsEnabled(pVM))
2662
 
        {
2663
 
            int rc = PGMSyncCR3(pVCpu, pCtx->cr0, pCtx->cr3, pCtx->cr4, VMCPU_FF_ISSET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
2664
 
            if (RT_FAILURE(rc))
2665
 
                return rc;
2666
 
        }
2667
 
 
2668
 
        int rc = TRPMR3SyncIDT(pVM, pVCpu);
2669
 
        if (RT_FAILURE(rc))
2670
 
            return rc;
2671
 
    }
2672
 
 
2673
 
    /*
2674
 
     * Sync TSS.
2675
 
     */
2676
 
    if (VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_SELM_SYNC_TSS))
2677
 
    {
2678
 
        int rc = SELMR3SyncTSS(pVM, pVCpu);
2679
 
        if (RT_FAILURE(rc))
2680
 
            return rc;
2681
 
    }
2682
 
 
2683
 
    /*
2684
 
     * Sync page directory.
2685
 
     */
2686
 
    if (VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL))
2687
 
    {
2688
 
        Assert(pVCpu->em.s.enmState != EMSTATE_WAIT_SIPI);
2689
 
        int rc = PGMSyncCR3(pVCpu, pCtx->cr0, pCtx->cr3, pCtx->cr4, VMCPU_FF_ISSET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
2690
 
        if (RT_FAILURE(rc))
2691
 
            return rc;
2692
 
 
2693
 
        Assert(!VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_SELM_SYNC_GDT | VMCPU_FF_SELM_SYNC_LDT));
2694
 
 
2695
 
        /* Prefetch pages for EIP and ESP. */
2696
 
        /** @todo This is rather expensive. Should investigate if it really helps at all. */
2697
 
        rc = PGMPrefetchPage(pVCpu, SELMToFlat(pVM, DIS_SELREG_CS, CPUMCTX2CORE(pCtx), pCtx->rip));
2698
 
        if (rc == VINF_SUCCESS)
2699
 
            rc = PGMPrefetchPage(pVCpu, SELMToFlat(pVM, DIS_SELREG_SS, CPUMCTX2CORE(pCtx), pCtx->rsp));
2700
 
        if (rc != VINF_SUCCESS)
2701
 
        {
2702
 
            if (rc != VINF_PGM_SYNC_CR3)
2703
 
            {
2704
 
                AssertLogRelMsgReturn(RT_FAILURE(rc), ("%Rrc\n", rc), VERR_IPE_UNEXPECTED_INFO_STATUS);
2705
 
                return rc;
2706
 
            }
2707
 
            rc = PGMSyncCR3(pVCpu, pCtx->cr0, pCtx->cr3, pCtx->cr4, VMCPU_FF_ISSET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
2708
 
            if (RT_FAILURE(rc))
2709
 
                return rc;
2710
 
        }
2711
 
        /** @todo maybe prefetch the supervisor stack page as well */
2712
 
        Assert(!VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_SELM_SYNC_GDT | VMCPU_FF_SELM_SYNC_LDT));
2713
 
    }
2714
 
 
2715
 
    /*
2716
 
     * Allocate handy pages (just in case the above actions have consumed some pages).
2717
 
     */
2718
 
    if (VM_FF_IS_PENDING_EXCEPT(pVM, VM_FF_PGM_NEED_HANDY_PAGES, VM_FF_PGM_NO_MEMORY))
2719
 
    {
2720
 
        int rc = PGMR3PhysAllocateHandyPages(pVM);
2721
 
        if (RT_FAILURE(rc))
2722
 
            return rc;
2723
 
    }
2724
 
 
2725
 
    /*
2726
 
     * Check whether we're out of memory now.
2727
 
     *
2728
 
     * This may stem from some of the above actions or operations that has been executed
2729
 
     * since we ran FFs. The allocate handy pages must for instance always be followed by
2730
 
     * this check.
2731
 
     */
2732
 
    if (VM_FF_ISPENDING(pVM, VM_FF_PGM_NO_MEMORY))
2733
 
        return VINF_EM_NO_MEMORY;
2734
 
 
2735
 
    return VINF_SUCCESS;
2736
 
}
2737
 
 
2738
 
 
2739
 
/**
2740
 
 * Executes raw code.
2741
 
 *
2742
 
 * This function contains the raw-mode version of the inner
2743
 
 * execution loop (the outer loop being in EMR3ExecuteVM()).
2744
 
 *
2745
 
 * @returns VBox status code. The most important ones are: VINF_EM_RESCHEDULE,
2746
 
 *          VINF_EM_RESCHEDULE_REM, VINF_EM_SUSPEND, VINF_EM_RESET and VINF_EM_TERMINATE.
2747
 
 *
2748
 
 * @param   pVM         VM handle.
2749
 
 * @param   pVCpu       VMCPU handle.
2750
 
 * @param   pfFFDone    Where to store an indicator telling whether or not
2751
 
 *                      FFs were done before returning.
2752
 
 */
2753
 
static int emR3RawExecute(PVM pVM, PVMCPU pVCpu, bool *pfFFDone)
2754
 
{
2755
 
    STAM_REL_PROFILE_ADV_START(&pVCpu->em.s.StatRAWTotal, a);
2756
 
 
2757
 
    int      rc = VERR_INTERNAL_ERROR;
2758
 
    PCPUMCTX pCtx = pVCpu->em.s.pCtx;
2759
 
    LogFlow(("emR3RawExecute: (cs:eip=%04x:%08x)\n", pCtx->cs, pCtx->eip));
2760
 
    pVCpu->em.s.fForceRAW = false;
2761
 
    *pfFFDone = false;
2762
 
 
2763
 
 
2764
 
    /*
2765
 
     *
2766
 
     * Spin till we get a forced action or raw mode status code resulting in
2767
 
     * in anything but VINF_SUCCESS or VINF_EM_RESCHEDULE_RAW.
2768
 
     *
2769
 
     */
2770
 
    for (;;)
2771
 
    {
2772
 
        STAM_PROFILE_ADV_START(&pVCpu->em.s.StatRAWEntry, b);
2773
 
 
2774
 
        /*
2775
 
         * Check various preconditions.
2776
 
         */
2777
 
#ifdef VBOX_STRICT
2778
 
        Assert(REMR3QueryPendingInterrupt(pVM, pVCpu) == REM_NO_PENDING_IRQ);
2779
 
        Assert(pCtx->eflags.Bits.u1VM || (pCtx->ss & X86_SEL_RPL) == 3 || (pCtx->ss & X86_SEL_RPL) == 0);
2780
 
        AssertMsg(   (pCtx->eflags.u32 & X86_EFL_IF)
2781
 
                  || PATMShouldUseRawMode(pVM, (RTGCPTR)pCtx->eip),
2782
 
                  ("Tried to execute code with IF at EIP=%08x!\n", pCtx->eip));
2783
 
        if (    !VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL)
2784
 
            &&  PGMMapHasConflicts(pVM))
2785
 
        {
2786
 
            PGMMapCheck(pVM);
2787
 
            AssertMsgFailed(("We should not get conflicts any longer!!!\n"));
2788
 
            return VERR_INTERNAL_ERROR;
2789
 
        }
2790
 
#endif /* VBOX_STRICT */
2791
 
 
2792
 
        /*
2793
 
         * Process high priority pre-execution raw-mode FFs.
2794
 
         */
2795
 
        if (    VM_FF_ISPENDING(pVM, VM_FF_HIGH_PRIORITY_PRE_RAW_MASK)
2796
 
            ||  VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_HIGH_PRIORITY_PRE_RAW_MASK))
2797
 
        {
2798
 
            rc = emR3RawForcedActions(pVM, pVCpu, pCtx);
2799
 
            if (rc != VINF_SUCCESS)
2800
 
                break;
2801
 
        }
2802
 
 
2803
 
        /*
2804
 
         * If we're going to execute ring-0 code, the guest state needs to
2805
 
         * be modified a bit and some of the state components (IF, SS/CS RPL,
2806
 
         * and perhaps EIP) needs to be stored with PATM.
2807
 
         */
2808
 
        rc = CPUMRawEnter(pVCpu, NULL);
2809
 
        if (rc != VINF_SUCCESS)
2810
 
        {
2811
 
            STAM_PROFILE_ADV_STOP(&pVCpu->em.s.StatRAWEntry, b);
2812
 
            break;
2813
 
        }
2814
 
 
2815
 
        /*
2816
 
         * Scan code before executing it. Don't bother with user mode or V86 code
2817
 
         */
2818
 
        if (    (pCtx->ss & X86_SEL_RPL) <= 1
2819
 
            &&  !pCtx->eflags.Bits.u1VM
2820
 
            && !PATMIsPatchGCAddr(pVM, pCtx->eip))
2821
 
        {
2822
 
            STAM_PROFILE_ADV_SUSPEND(&pVCpu->em.s.StatRAWEntry, b);
2823
 
            CSAMR3CheckCodeEx(pVM, CPUMCTX2CORE(pCtx), pCtx->eip);
2824
 
            STAM_PROFILE_ADV_RESUME(&pVCpu->em.s.StatRAWEntry, b);
2825
 
            if (    VM_FF_ISPENDING(pVM, VM_FF_HIGH_PRIORITY_PRE_RAW_MASK)
2826
 
                ||  VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_HIGH_PRIORITY_PRE_RAW_MASK))
2827
 
            {
2828
 
                rc = emR3RawForcedActions(pVM, pVCpu, pCtx);
2829
 
                if (rc != VINF_SUCCESS)
2830
 
                {
2831
 
                    rc = CPUMRawLeave(pVCpu, NULL, rc);
2832
 
                    break;
2833
 
                }
2834
 
            }
2835
 
        }
2836
 
 
2837
 
#ifdef LOG_ENABLED
2838
 
        /*
2839
 
         * Log important stuff before entering GC.
2840
 
         */
2841
 
        PPATMGCSTATE pGCState = PATMR3QueryGCStateHC(pVM);
2842
 
        if (pCtx->eflags.Bits.u1VM)
2843
 
            Log(("RV86: %04X:%08X IF=%d VMFlags=%x\n", pCtx->cs, pCtx->eip, pCtx->eflags.Bits.u1IF, pGCState->uVMFlags));
2844
 
        else if ((pCtx->ss & X86_SEL_RPL) == 1)
2845
 
        {
2846
 
            bool fCSAMScanned = CSAMIsPageScanned(pVM, (RTGCPTR)pCtx->eip);
2847
 
            Log(("RR0: %08X ESP=%08X IF=%d VMFlags=%x PIF=%d CPL=%d (Scanned=%d)\n", pCtx->eip, pCtx->esp, pCtx->eflags.Bits.u1IF, pGCState->uVMFlags, pGCState->fPIF, (pCtx->ss & X86_SEL_RPL), fCSAMScanned));
2848
 
        }
2849
 
        else if ((pCtx->ss & X86_SEL_RPL) == 3)
2850
 
            Log(("RR3: %08X ESP=%08X IF=%d VMFlags=%x\n", pCtx->eip, pCtx->esp, pCtx->eflags.Bits.u1IF, pGCState->uVMFlags));
2851
 
#endif /* LOG_ENABLED */
2852
 
 
2853
 
 
2854
 
 
2855
 
        /*
2856
 
         * Execute the code.
2857
 
         */
2858
 
        STAM_PROFILE_ADV_STOP(&pVCpu->em.s.StatRAWEntry, b);
2859
 
        STAM_PROFILE_START(&pVCpu->em.s.StatRAWExec, c);
2860
 
        rc = VMMR3RawRunGC(pVM, pVCpu);
2861
 
        STAM_PROFILE_STOP(&pVCpu->em.s.StatRAWExec, c);
2862
 
        STAM_PROFILE_ADV_START(&pVCpu->em.s.StatRAWTail, d);
2863
 
 
2864
 
        LogFlow(("RR0-E: %08X ESP=%08X IF=%d VMFlags=%x PIF=%d CPL=%d\n", pCtx->eip, pCtx->esp, pCtx->eflags.Bits.u1IF, pGCState->uVMFlags, pGCState->fPIF, (pCtx->ss & X86_SEL_RPL)));
2865
 
        LogFlow(("VMMR3RawRunGC returned %Rrc\n", rc));
2866
 
 
2867
 
 
2868
 
 
2869
 
        /*
2870
 
         * Restore the real CPU state and deal with high priority post
2871
 
         * execution FFs before doing anything else.
2872
 
         */
2873
 
        rc = CPUMRawLeave(pVCpu, NULL, rc);
2874
 
        VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_RESUME_GUEST_MASK);
2875
 
        if (    VM_FF_ISPENDING(pVM, VM_FF_HIGH_PRIORITY_POST_MASK)
2876
 
            ||  VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_HIGH_PRIORITY_POST_MASK))
2877
 
            rc = emR3HighPriorityPostForcedActions(pVM, pVCpu, rc);
2878
 
 
2879
 
#ifdef VBOX_STRICT
2880
 
        /*
2881
 
         * Assert TSS consistency & rc vs patch code.
2882
 
         */
2883
 
        if (   !VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_SELM_SYNC_TSS | VMCPU_FF_SELM_SYNC_GDT) /* GDT implies TSS at the moment. */
2884
 
            &&  EMIsRawRing0Enabled(pVM))
2885
 
            SELMR3CheckTSS(pVM);
2886
 
        switch (rc)
2887
 
        {
2888
 
            case VINF_SUCCESS:
2889
 
            case VINF_EM_RAW_INTERRUPT:
2890
 
            case VINF_PATM_PATCH_TRAP_PF:
2891
 
            case VINF_PATM_PATCH_TRAP_GP:
2892
 
            case VINF_PATM_PATCH_INT3:
2893
 
            case VINF_PATM_CHECK_PATCH_PAGE:
2894
 
            case VINF_EM_RAW_EXCEPTION_PRIVILEGED:
2895
 
            case VINF_EM_RAW_GUEST_TRAP:
2896
 
            case VINF_EM_RESCHEDULE_RAW:
2897
 
                break;
2898
 
 
2899
 
            default:
2900
 
                if (PATMIsPatchGCAddr(pVM, pCtx->eip) && !(pCtx->eflags.u32 & X86_EFL_TF))
2901
 
                    LogIt(NULL, 0, LOG_GROUP_PATM, ("Patch code interrupted at %RRv for reason %Rrc\n", (RTRCPTR)CPUMGetGuestEIP(pVCpu), rc));
2902
 
                break;
2903
 
        }
2904
 
        /*
2905
 
         * Let's go paranoid!
2906
 
         */
2907
 
        if (    !VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL)
2908
 
            &&  PGMMapHasConflicts(pVM))
2909
 
        {
2910
 
            PGMMapCheck(pVM);
2911
 
            AssertMsgFailed(("We should not get conflicts any longer!!! rc=%Rrc\n", rc));
2912
 
            return VERR_INTERNAL_ERROR;
2913
 
        }
2914
 
#endif /* VBOX_STRICT */
2915
 
 
2916
 
        /*
2917
 
         * Process the returned status code.
2918
 
         */
2919
 
        if (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST)
2920
 
        {
2921
 
            STAM_PROFILE_ADV_STOP(&pVCpu->em.s.StatRAWTail, d);
2922
 
            break;
2923
 
        }
2924
 
        rc = emR3RawHandleRC(pVM, pVCpu, pCtx, rc);
2925
 
        if (rc != VINF_SUCCESS)
2926
 
        {
2927
 
            rc = emR3RawUpdateForceFlag(pVM, pVCpu, pCtx, rc);
2928
 
            if (rc != VINF_SUCCESS)
2929
 
            {
2930
 
                STAM_PROFILE_ADV_STOP(&pVCpu->em.s.StatRAWTail, d);
2931
 
                break;
2932
 
            }
2933
 
        }
2934
 
 
2935
 
        /*
2936
 
         * Check and execute forced actions.
2937
 
         */
2938
 
#ifdef VBOX_HIGH_RES_TIMERS_HACK
2939
 
        TMTimerPollVoid(pVM, pVCpu);
2940
 
#endif
2941
 
        STAM_PROFILE_ADV_STOP(&pVCpu->em.s.StatRAWTail, d);
2942
 
        if (    VM_FF_ISPENDING(pVM, ~VM_FF_HIGH_PRIORITY_PRE_RAW_MASK | VM_FF_PGM_NO_MEMORY)
2943
 
            ||  VMCPU_FF_ISPENDING(pVCpu, ~VMCPU_FF_HIGH_PRIORITY_PRE_RAW_MASK))
2944
 
        {
2945
 
            Assert(pCtx->eflags.Bits.u1VM || (pCtx->ss & X86_SEL_RPL) != 1);
2946
 
 
2947
 
            STAM_REL_PROFILE_ADV_SUSPEND(&pVCpu->em.s.StatRAWTotal, a);
2948
 
            rc = emR3ForcedActions(pVM, pVCpu, rc);
2949
 
            STAM_REL_PROFILE_ADV_RESUME(&pVCpu->em.s.StatRAWTotal, a);
2950
 
            if (    rc != VINF_SUCCESS
2951
 
                &&  rc != VINF_EM_RESCHEDULE_RAW)
2952
 
            {
2953
 
                rc = emR3RawUpdateForceFlag(pVM, pVCpu, pCtx, rc);
2954
 
                if (rc != VINF_SUCCESS)
2955
 
                {
2956
 
                    *pfFFDone = true;
2957
 
                    break;
2958
 
                }
2959
 
            }
2960
 
        }
2961
 
    }
2962
 
 
2963
 
    /*
2964
 
     * Return to outer loop.
2965
 
     */
2966
 
#if defined(LOG_ENABLED) && defined(DEBUG)
2967
 
    RTLogFlush(NULL);
2968
 
#endif
2969
 
    STAM_REL_PROFILE_ADV_STOP(&pVCpu->em.s.StatRAWTotal, a);
2970
 
    return rc;
2971
 
}
2972
 
 
2973
 
 
2974
 
/**
2975
 
 * Executes hardware accelerated raw code. (Intel VMX & AMD SVM)
2976
 
 *
2977
 
 * This function contains the raw-mode version of the inner
2978
 
 * execution loop (the outer loop being in EMR3ExecuteVM()).
2979
 
 *
2980
 
 * @returns VBox status code. The most important ones are: VINF_EM_RESCHEDULE, VINF_EM_RESCHEDULE_RAW,
2981
 
 *          VINF_EM_RESCHEDULE_REM, VINF_EM_SUSPEND, VINF_EM_RESET and VINF_EM_TERMINATE.
2982
 
 *
2983
 
 * @param   pVM         VM handle.
2984
 
 * @param   pVCpu       VMCPU handle.
2985
 
 * @param   pfFFDone    Where to store an indicator telling whether or not
2986
 
 *                      FFs were done before returning.
2987
 
 */
2988
 
static int emR3HwAccExecute(PVM pVM, PVMCPU pVCpu, bool *pfFFDone)
2989
 
{
2990
 
    int      rc = VERR_INTERNAL_ERROR;
2991
 
    PCPUMCTX pCtx = pVCpu->em.s.pCtx;
2992
 
 
2993
 
    LogFlow(("emR3HwAccExecute%d: (cs:eip=%04x:%RGv)\n", pVCpu->idCpu, pCtx->cs, (RTGCPTR)pCtx->rip));
2994
 
    *pfFFDone = false;
2995
 
 
2996
 
    STAM_COUNTER_INC(&pVCpu->em.s.StatHwAccExecuteEntry);
2997
 
 
2998
 
#ifdef EM_NOTIFY_HWACCM
2999
 
    HWACCMR3NotifyScheduled(pVCpu);
3000
 
#endif
3001
 
 
3002
 
    /*
3003
 
     * Spin till we get a forced action which returns anything but VINF_SUCCESS.
3004
 
     */
3005
 
    for (;;)
3006
 
    {
3007
 
        STAM_PROFILE_ADV_START(&pVCpu->em.s.StatHwAccEntry, a);
3008
 
 
3009
 
        /*
3010
 
         * Process high priority pre-execution raw-mode FFs.
3011
 
         */
3012
 
        VMCPU_FF_CLEAR(pVCpu, (VMCPU_FF_SELM_SYNC_GDT | VMCPU_FF_SELM_SYNC_LDT | VMCPU_FF_TRPM_SYNC_IDT | VMCPU_FF_SELM_SYNC_TSS)); /* not relevant in HWACCM mode; shouldn't be set really. */
3013
 
        if (    VM_FF_ISPENDING(pVM, VM_FF_HIGH_PRIORITY_PRE_RAW_MASK)
3014
 
            ||  VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_HIGH_PRIORITY_PRE_RAW_MASK))
3015
 
        {
3016
 
            rc = emR3RawForcedActions(pVM, pVCpu, pCtx);
3017
 
            if (rc != VINF_SUCCESS)
3018
 
                break;
3019
 
        }
3020
 
 
3021
 
#ifdef LOG_ENABLED
3022
 
        /*
3023
 
         * Log important stuff before entering GC.
3024
 
         */
3025
 
        if (TRPMHasTrap(pVCpu))
3026
 
            Log(("CPU%d: Pending hardware interrupt=0x%x cs:rip=%04X:%RGv\n", pVCpu->idCpu, TRPMGetTrapNo(pVCpu), pCtx->cs, (RTGCPTR)pCtx->rip));
3027
 
 
3028
 
        uint32_t cpl = CPUMGetGuestCPL(pVCpu, CPUMCTX2CORE(pCtx));
3029
 
 
3030
 
        if (pVM->cCPUs == 1)
3031
 
        {
3032
 
            if (pCtx->eflags.Bits.u1VM)
3033
 
                Log(("HWV86: %08X IF=%d\n", pCtx->eip, pCtx->eflags.Bits.u1IF));
3034
 
            else if (CPUMIsGuestIn64BitCodeEx(pCtx))
3035
 
                Log(("HWR%d: %04X:%RGv ESP=%RGv IF=%d IOPL=%d CR0=%x CR4=%x EFER=%x\n", cpl, pCtx->cs, (RTGCPTR)pCtx->rip, pCtx->rsp, pCtx->eflags.Bits.u1IF, pCtx->eflags.Bits.u2IOPL, (uint32_t)pCtx->cr0, (uint32_t)pCtx->cr4, (uint32_t)pCtx->msrEFER));
3036
 
            else
3037
 
                Log(("HWR%d: %04X:%08X ESP=%08X IF=%d IOPL=%d CR0=%x CR4=%x EFER=%x\n", cpl, pCtx->cs,          pCtx->eip, pCtx->esp, pCtx->eflags.Bits.u1IF, pCtx->eflags.Bits.u2IOPL, (uint32_t)pCtx->cr0, (uint32_t)pCtx->cr4, (uint32_t)pCtx->msrEFER));
3038
 
        }
3039
 
        else
3040
 
        {
3041
 
            if (pCtx->eflags.Bits.u1VM)
3042
 
                Log(("HWV86-CPU%d: %08X IF=%d\n", pVCpu->idCpu, pCtx->eip, pCtx->eflags.Bits.u1IF));
3043
 
            else if (CPUMIsGuestIn64BitCodeEx(pCtx))
3044
 
                Log(("HWR%d-CPU%d: %04X:%RGv ESP=%RGv IF=%d IOPL=%d CR0=%x CR4=%x EFER=%x\n", cpl, pVCpu->idCpu, pCtx->cs, (RTGCPTR)pCtx->rip, pCtx->rsp, pCtx->eflags.Bits.u1IF, pCtx->eflags.Bits.u2IOPL, (uint32_t)pCtx->cr0, (uint32_t)pCtx->cr4, (uint32_t)pCtx->msrEFER));
3045
 
            else
3046
 
                Log(("HWR%d-CPU%d: %04X:%08X ESP=%08X IF=%d IOPL=%d CR0=%x CR4=%x EFER=%x\n", cpl, pVCpu->idCpu, pCtx->cs,          pCtx->eip, pCtx->esp, pCtx->eflags.Bits.u1IF, pCtx->eflags.Bits.u2IOPL, (uint32_t)pCtx->cr0, (uint32_t)pCtx->cr4, (uint32_t)pCtx->msrEFER));
3047
 
        }
3048
 
#endif /* LOG_ENABLED */
3049
 
 
3050
 
        /*
3051
 
         * Execute the code.
3052
 
         */
3053
 
        STAM_PROFILE_ADV_STOP(&pVCpu->em.s.StatHwAccEntry, a);
3054
 
        STAM_PROFILE_START(&pVCpu->em.s.StatHwAccExec, x);
3055
 
        rc = VMMR3HwAccRunGC(pVM, pVCpu);
3056
 
        STAM_PROFILE_STOP(&pVCpu->em.s.StatHwAccExec, x);
3057
 
 
3058
 
        /*
3059
 
         * Deal with high priority post execution FFs before doing anything else.
3060
 
         */
3061
 
        VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_RESUME_GUEST_MASK);
3062
 
        if (    VM_FF_ISPENDING(pVM, VM_FF_HIGH_PRIORITY_POST_MASK)
3063
 
            ||  VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_HIGH_PRIORITY_POST_MASK))
3064
 
            rc = emR3HighPriorityPostForcedActions(pVM, pVCpu, rc);
3065
 
 
3066
 
        /*
3067
 
         * Process the returned status code.
3068
 
         */
3069
 
        if (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST)
3070
 
            break;
3071
 
 
3072
 
        rc = emR3RawHandleRC(pVM, pVCpu, pCtx, rc);
3073
 
        if (rc != VINF_SUCCESS)
3074
 
            break;
3075
 
 
3076
 
        /*
3077
 
         * Check and execute forced actions.
3078
 
         */
3079
 
#ifdef VBOX_HIGH_RES_TIMERS_HACK
3080
 
        TMTimerPollVoid(pVM, pVCpu);
3081
 
#endif
3082
 
        if (    VM_FF_ISPENDING(pVM, VM_FF_ALL_MASK)
3083
 
            ||  VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_ALL_MASK))
3084
 
        {
3085
 
            rc = emR3ForcedActions(pVM, pVCpu, rc);
3086
 
            if (    rc != VINF_SUCCESS
3087
 
                &&  rc != VINF_EM_RESCHEDULE_HWACC)
3088
 
            {
3089
 
                *pfFFDone = true;
3090
 
                break;
3091
 
            }
3092
 
        }
3093
 
    }
3094
 
 
3095
 
    /*
3096
 
     * Return to outer loop.
3097
 
     */
3098
 
#if defined(LOG_ENABLED) && defined(DEBUG)
3099
 
    RTLogFlush(NULL);
3100
 
#endif
3101
 
    return rc;
3102
 
}
3103
 
 
3104
 
 
3105
 
/**
3106
1034
 * Decides whether to execute RAW, HWACC or REM.
3107
1035
 *
3108
1036
 * @returns new EM state
3110
1038
 * @param   pVCpu   The VMCPU handle.
3111
1039
 * @param   pCtx    The CPU context.
3112
1040
 */
3113
 
static EMSTATE emR3Reschedule(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx)
 
1041
EMSTATE emR3Reschedule(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx)
3114
1042
{
3115
1043
    /*
3116
1044
     * When forcing raw-mode execution, things are simple.
3265
1193
 * @param   pVCpu       VMCPU handle.
3266
1194
 * @param   rc          The current rc.
3267
1195
 */
3268
 
static int emR3HighPriorityPostForcedActions(PVM pVM, PVMCPU pVCpu, int rc)
 
1196
int emR3HighPriorityPostForcedActions(PVM pVM, PVMCPU pVCpu, int rc)
3269
1197
{
3270
1198
    if (VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_PDM_CRITSECT))
3271
1199
        PDMCritSectFF(pVCpu);
3303
1231
 * @param   rc          The current rc.
3304
1232
 *
3305
1233
 */
3306
 
static int emR3ForcedActions(PVM pVM, PVMCPU pVCpu, int rc)
 
1234
int emR3ForcedActions(PVM pVM, PVMCPU pVCpu, int rc)
3307
1235
{
3308
1236
    STAM_REL_PROFILE_START(&pVCpu->em.s.StatForcedActions, a);
3309
1237
#ifdef VBOX_STRICT