VirtualBox

Ignore:
Timestamp:
Feb 14, 2025 3:54:48 PM (4 weeks ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
167546
Message:

VMM/IEM: Splitting up IEMAll.cpp. jiraref:VBP-1531

File:
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/target-x86/IEMAllMem-x86.cpp

    r108220 r108226  
    11/* $Id$ */
    22/** @file
    3  * IEM - Interpreted Execution Manager - All Contexts.
     3 * IEM - Interpreted Execution Manager - x86 target, memory.
    44 */
    55
     
    2727
    2828
    29 /** @page pg_iem    IEM - Interpreted Execution Manager
    30  *
    31  * The interpreted exeuction manager (IEM) is for executing short guest code
    32  * sequences that are causing too many exits / virtualization traps.  It will
    33  * also be used to interpret single instructions, thus replacing the selective
    34  * interpreters in EM and IOM.
    35  *
    36  * Design goals:
    37  *      - Relatively small footprint, although we favour speed and correctness
    38  *        over size.
    39  *      - Reasonably fast.
    40  *      - Correctly handle lock prefixed instructions.
    41  *      - Complete instruction set - eventually.
    42  *      - Refactorable into a recompiler, maybe.
    43  *      - Replace EMInterpret*.
    44  *
    45  * Using the existing disassembler has been considered, however this is thought
    46  * to conflict with speed as the disassembler chews things a bit too much while
    47  * leaving us with a somewhat complicated state to interpret afterwards.
    48  *
    49  *
    50  * The current code is very much work in progress. You've been warned!
    51  *
    52  *
    53  * @section sec_iem_fpu_instr   FPU Instructions
    54  *
    55  * On x86 and AMD64 hosts, the FPU instructions are implemented by executing the
    56  * same or equivalent instructions on the host FPU.  To make life easy, we also
    57  * let the FPU prioritize the unmasked exceptions for us.  This however, only
    58  * works reliably when CR0.NE is set, i.e. when using \#MF instead the IRQ 13
    59  * for FPU exception delivery, because with CR0.NE=0 there is a window where we
    60  * can trigger spurious FPU exceptions.
    61  *
    62  * The guest FPU state is not loaded into the host CPU and kept there till we
    63  * leave IEM because the calling conventions have declared an all year open
    64  * season on much of the FPU state.  For instance an innocent looking call to
    65  * memcpy might end up using a whole bunch of XMM or MM registers if the
    66  * particular implementation finds it worthwhile.
    67  *
    68  *
    69  * @section sec_iem_logging     Logging
    70  *
    71  * The IEM code uses the \"IEM\" log group for the main logging. The different
    72  * logging levels/flags are generally used for the following purposes:
    73  *      - Level 1  (Log)  : Errors, exceptions, interrupts and such major events.
    74  *      - Flow  (LogFlow) : Basic enter/exit IEM state info.
    75  *      - Level 2  (Log2) : ?
    76  *      - Level 3  (Log3) : More detailed enter/exit IEM state info.
    77  *      - Level 4  (Log4) : Decoding mnemonics w/ EIP.
    78  *      - Level 5  (Log5) : Decoding details.
    79  *      - Level 6  (Log6) : Enables/disables the lockstep comparison with REM.
    80  *      - Level 7  (Log7) : iret++ execution logging.
    81  *      - Level 8  (Log8) :
    82  *      - Level 9  (Log9) :
    83  *      - Level 10 (Log10): TLBs.
    84  *      - Level 11 (Log11): Unmasked FPU exceptions.
    85  *
    86  * The \"IEM_MEM\" log group covers most of memory related details logging,
    87  * except for errors and exceptions:
    88  *      - Level 1  (Log)  : Reads.
    89  *      - Level 2  (Log2) : Read fallbacks.
    90  *      - Level 3  (Log3) : MemMap read.
    91  *      - Level 4  (Log4) : MemMap read fallbacks.
    92  *      - Level 5  (Log5) : Writes
    93  *      - Level 6  (Log6) : Write fallbacks.
    94  *      - Level 7  (Log7) : MemMap writes and read-writes.
    95  *      - Level 8  (Log8) : MemMap write and read-write fallbacks.
    96  *      - Level 9  (Log9) : Stack reads.
    97  *      - Level 10 (Log10): Stack read fallbacks.
    98  *      - Level 11 (Log11): Stack writes.
    99  *      - Level 12 (Log12): Stack write fallbacks.
    100  *      - Flow  (LogFlow) :
    101  *
    102  * The SVM (AMD-V) and VMX (VT-x) code has the following assignments:
    103  *      - Level 1  (Log)  : Errors and other major events.
    104  *      - Flow (LogFlow)  : Misc flow stuff (cleanup?)
    105  *      - Level 2  (Log2) : VM exits.
    106  *
    107  * The syscall logging level assignments:
    108  *      - Level 1: DOS and BIOS.
    109  *      - Level 2: Windows 3.x
    110  *      - Level 3: Linux.
    111  */
    112 
    113 /* Disabled warning C4505: 'iemRaisePageFaultJmp' : unreferenced local function has been removed */
    114 #ifdef _MSC_VER
    115 # pragma warning(disable:4505)
    116 #endif
    117 
    118 
    11929/*********************************************************************************************************************************
    12030*   Header Files                                                                                                                 *
    12131*********************************************************************************************************************************/
    122 #define LOG_GROUP   LOG_GROUP_IEM
     32#define LOG_GROUP LOG_GROUP_IEM_MEM
    12333#define VMCPU_INCL_CPUM_GST_CTX
    12434#ifdef IN_RING0
     
    12737#include <VBox/vmm/iem.h>
    12838#include <VBox/vmm/cpum.h>
    129 #include <VBox/vmm/pdmapic.h>
    130 #include <VBox/vmm/pdm.h>
    13139#include <VBox/vmm/pgm.h>
    132 #include <VBox/vmm/iom.h>
    133 #include <VBox/vmm/em.h>
    134 #include <VBox/vmm/hm.h>
    135 #include <VBox/vmm/nem.h>
    136 #include <VBox/vmm/gcm.h>
    137 #include <VBox/vmm/gim.h>
    138 #ifdef VBOX_WITH_NESTED_HWVIRT_SVM
    139 # include <VBox/vmm/em.h>
    140 # include <VBox/vmm/hm_svm.h>
    141 #endif
    142 #ifdef VBOX_WITH_NESTED_HWVIRT_VMX
    143 # include <VBox/vmm/hmvmxinline.h>
    144 #endif
    145 #include <VBox/vmm/tm.h>
    14640#include <VBox/vmm/dbgf.h>
    147 #include <VBox/vmm/dbgftrace.h>
    14841#include "IEMInternal.h"
    14942#include <VBox/vmm/vmcc.h>
    15043#include <VBox/log.h>
    15144#include <VBox/err.h>
    152 #include <VBox/param.h>
    153 #include <VBox/dis.h>
    154 #include <iprt/asm-math.h>
    155 #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
    156 # include <iprt/asm-amd64-x86.h>
    157 #elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
    158 # include <iprt/asm-arm.h>
    159 #endif
    16045#include <iprt/assert.h>
    16146#include <iprt/string.h>
     
    16348
    16449#include "IEMInline.h"
    165 
    166 
    167 /*********************************************************************************************************************************
    168 *   Structures and Typedefs                                                                                                      *
    169 *********************************************************************************************************************************/
    170 /**
    171  * CPU exception classes.
    172  */
    173 typedef enum IEMXCPTCLASS
    174 {
    175     IEMXCPTCLASS_BENIGN,
    176     IEMXCPTCLASS_CONTRIBUTORY,
    177     IEMXCPTCLASS_PAGE_FAULT,
    178     IEMXCPTCLASS_DOUBLE_FAULT
    179 } IEMXCPTCLASS;
    180 
    181 
    182 /*********************************************************************************************************************************
    183 *   Global Variables                                                                                                             *
    184 *********************************************************************************************************************************/
    185 #if defined(IEM_LOG_MEMORY_WRITES)
    186 /** What IEM just wrote. */
    187 uint8_t g_abIemWrote[256];
    188 /** How much IEM just wrote. */
    189 size_t g_cbIemWrote;
    190 #endif
    191 
    192 
    193 /**
    194  * Calculates IEM_F_BRK_PENDING_XXX (IEM_F_PENDING_BRK_MASK) flags, slow code
    195  * path.
    196  *
    197  * This will also invalidate TLB entries for any pages with active data
    198  * breakpoints on them.
    199  *
    200  * @returns IEM_F_BRK_PENDING_XXX or zero.
    201  * @param   pVCpu               The cross context virtual CPU structure of the
    202  *                              calling thread.
    203  *
    204  * @note    Don't call directly, use iemCalcExecDbgFlags instead.
    205  */
    206 uint32_t iemCalcExecDbgFlagsSlow(PVMCPUCC pVCpu)
    207 {
    208     uint32_t fExec = 0;
    209 
    210     /*
    211      * Helper for invalidate the data TLB for breakpoint addresses.
    212      *
    213      * This is to make sure any access to the page will always trigger a TLB
    214      * load for as long as the breakpoint is enabled.
    215      */
    216 #ifdef IEM_WITH_DATA_TLB
    217 # define INVALID_TLB_ENTRY_FOR_BP(a_uValue) do { \
    218         RTGCPTR uTagNoRev = (a_uValue); \
    219         uTagNoRev = IEMTLB_CALC_TAG_NO_REV(uTagNoRev); \
    220         /** @todo do large page accounting */ \
    221         uintptr_t const idxEven = IEMTLB_TAG_TO_EVEN_INDEX(uTagNoRev); \
    222         if (pVCpu->iem.s.DataTlb.aEntries[idxEven].uTag == (uTagNoRev | pVCpu->iem.s.DataTlb.uTlbRevision)) \
    223             pVCpu->iem.s.DataTlb.aEntries[idxEven].uTag = 0; \
    224         if (pVCpu->iem.s.DataTlb.aEntries[idxEven + 1].uTag == (uTagNoRev | pVCpu->iem.s.DataTlb.uTlbRevisionGlobal)) \
    225             pVCpu->iem.s.DataTlb.aEntries[idxEven + 1].uTag = 0; \
    226     } while (0)
    227 #else
    228 # define INVALID_TLB_ENTRY_FOR_BP(a_uValue) do { } while (0)
    229 #endif
    230 
    231     /*
    232      * Process guest breakpoints.
    233      */
    234 #define PROCESS_ONE_BP(a_fDr7, a_iBp, a_uValue) do { \
    235         if (a_fDr7 & X86_DR7_L_G(a_iBp)) \
    236         { \
    237             switch (X86_DR7_GET_RW(a_fDr7, a_iBp)) \
    238             { \
    239                 case X86_DR7_RW_EO: \
    240                     fExec |= IEM_F_PENDING_BRK_INSTR; \
    241                     break; \
    242                 case X86_DR7_RW_WO: \
    243                 case X86_DR7_RW_RW: \
    244                     fExec |= IEM_F_PENDING_BRK_DATA; \
    245                     INVALID_TLB_ENTRY_FOR_BP(a_uValue); \
    246                     break; \
    247                 case X86_DR7_RW_IO: \
    248                     fExec |= IEM_F_PENDING_BRK_X86_IO; \
    249                     break; \
    250             } \
    251         } \
    252     } while (0)
    253 
    254     uint32_t const fGstDr7 = (uint32_t)pVCpu->cpum.GstCtx.dr[7];
    255     if (fGstDr7 & X86_DR7_ENABLED_MASK)
    256     {
    257 /** @todo extract more details here to simplify matching later. */
    258 #ifdef IEM_WITH_DATA_TLB
    259         IEM_CTX_IMPORT_NORET(pVCpu, CPUMCTX_EXTRN_DR0_DR3);
    260 #endif
    261         PROCESS_ONE_BP(fGstDr7, 0, pVCpu->cpum.GstCtx.dr[0]);
    262         PROCESS_ONE_BP(fGstDr7, 1, pVCpu->cpum.GstCtx.dr[1]);
    263         PROCESS_ONE_BP(fGstDr7, 2, pVCpu->cpum.GstCtx.dr[2]);
    264         PROCESS_ONE_BP(fGstDr7, 3, pVCpu->cpum.GstCtx.dr[3]);
    265     }
    266 
    267     /*
    268      * Process hypervisor breakpoints.
    269      */
    270     PVMCC const    pVM       = pVCpu->CTX_SUFF(pVM);
    271     uint32_t const fHyperDr7 = DBGFBpGetDR7(pVM);
    272     if (fHyperDr7 & X86_DR7_ENABLED_MASK)
    273     {
    274 /** @todo extract more details here to simplify matching later. */
    275         PROCESS_ONE_BP(fHyperDr7, 0, DBGFBpGetDR0(pVM));
    276         PROCESS_ONE_BP(fHyperDr7, 1, DBGFBpGetDR1(pVM));
    277         PROCESS_ONE_BP(fHyperDr7, 2, DBGFBpGetDR2(pVM));
    278         PROCESS_ONE_BP(fHyperDr7, 3, DBGFBpGetDR3(pVM));
    279     }
    280 
    281     return fExec;
    282 }
    283 
    284 
    285 /**
    286  * Initializes the decoder state.
    287  *
    288  * iemReInitDecoder is mostly a copy of this function.
    289  *
    290  * @param   pVCpu               The cross context virtual CPU structure of the
    291  *                              calling thread.
    292  * @param   fExecOpts           Optional execution flags:
    293  *                                  - IEM_F_BYPASS_HANDLERS
    294  *                                  - IEM_F_X86_DISREGARD_LOCK
    295  */
    296 DECLINLINE(void) iemInitDecoder(PVMCPUCC pVCpu, uint32_t fExecOpts)
    297 {
    298     IEM_CTX_ASSERT(pVCpu, IEM_CPUMCTX_EXTRN_MUST_MASK);
    299     Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_IEM));
    300     Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pVCpu->cpum.GstCtx.cs));
    301     Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pVCpu->cpum.GstCtx.ss));
    302     Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pVCpu->cpum.GstCtx.es));
    303     Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pVCpu->cpum.GstCtx.ds));
    304     Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pVCpu->cpum.GstCtx.fs));
    305     Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pVCpu->cpum.GstCtx.gs));
    306     Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pVCpu->cpum.GstCtx.ldtr));
    307     Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pVCpu->cpum.GstCtx.tr));
    308 
    309     /* Execution state: */
    310     uint32_t fExec;
    311     pVCpu->iem.s.fExec = fExec = iemCalcExecFlags(pVCpu) | fExecOpts;
    312 
    313     /* Decoder state: */
    314     pVCpu->iem.s.enmDefAddrMode     = fExec & IEM_F_MODE_CPUMODE_MASK;  /** @todo check if this is correct... */
    315     pVCpu->iem.s.enmEffAddrMode     = fExec & IEM_F_MODE_CPUMODE_MASK;
    316     if ((fExec & IEM_F_MODE_CPUMODE_MASK) != IEMMODE_64BIT)
    317     {
    318         pVCpu->iem.s.enmDefOpSize   = fExec & IEM_F_MODE_CPUMODE_MASK;  /** @todo check if this is correct... */
    319         pVCpu->iem.s.enmEffOpSize   = fExec & IEM_F_MODE_CPUMODE_MASK;
    320     }
    321     else
    322     {
    323         pVCpu->iem.s.enmDefOpSize   = IEMMODE_32BIT;
    324         pVCpu->iem.s.enmEffOpSize   = IEMMODE_32BIT;
    325     }
    326     pVCpu->iem.s.fPrefixes          = 0;
    327     pVCpu->iem.s.uRexReg            = 0;
    328     pVCpu->iem.s.uRexB              = 0;
    329     pVCpu->iem.s.uRexIndex          = 0;
    330     pVCpu->iem.s.idxPrefix          = 0;
    331     pVCpu->iem.s.uVex3rdReg         = 0;
    332     pVCpu->iem.s.uVexLength         = 0;
    333     pVCpu->iem.s.fEvexStuff         = 0;
    334     pVCpu->iem.s.iEffSeg            = X86_SREG_DS;
    335 #ifdef IEM_WITH_CODE_TLB
    336     pVCpu->iem.s.pbInstrBuf         = NULL;
    337     pVCpu->iem.s.offInstrNextByte   = 0;
    338     pVCpu->iem.s.offCurInstrStart   = 0;
    339 # ifdef IEM_WITH_CODE_TLB_AND_OPCODE_BUF
    340     pVCpu->iem.s.offOpcode          = 0;
    341 # endif
    342 # ifdef VBOX_STRICT
    343     pVCpu->iem.s.GCPhysInstrBuf     = NIL_RTGCPHYS;
    344     pVCpu->iem.s.cbInstrBuf         = UINT16_MAX;
    345     pVCpu->iem.s.cbInstrBufTotal    = UINT16_MAX;
    346     pVCpu->iem.s.uInstrBufPc        = UINT64_C(0xc0ffc0ffcff0c0ff);
    347 # endif
    348 #else
    349     pVCpu->iem.s.offOpcode          = 0;
    350     pVCpu->iem.s.cbOpcode           = 0;
    351 #endif
    352     pVCpu->iem.s.offModRm           = 0;
    353     pVCpu->iem.s.cActiveMappings    = 0;
    354     pVCpu->iem.s.iNextMapping       = 0;
    355     pVCpu->iem.s.rcPassUp           = VINF_SUCCESS;
    356 
    357 #ifdef DBGFTRACE_ENABLED
    358     switch (IEM_GET_CPU_MODE(pVCpu))
    359     {
    360         case IEMMODE_64BIT:
    361             RTTraceBufAddMsgF(pVCpu->CTX_SUFF(pVM)->CTX_SUFF(hTraceBuf), "I64/%u %08llx", IEM_GET_CPL(pVCpu), pVCpu->cpum.GstCtx.rip);
    362             break;
    363         case IEMMODE_32BIT:
    364             RTTraceBufAddMsgF(pVCpu->CTX_SUFF(pVM)->CTX_SUFF(hTraceBuf), "I32/%u %04x:%08x", IEM_GET_CPL(pVCpu), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.eip);
    365             break;
    366         case IEMMODE_16BIT:
    367             RTTraceBufAddMsgF(pVCpu->CTX_SUFF(pVM)->CTX_SUFF(hTraceBuf), "I16/%u %04x:%04x", IEM_GET_CPL(pVCpu), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.eip);
    368             break;
    369     }
    370 #endif
    371 }
    372 
    373 
    374 /**
    375  * Reinitializes the decoder state 2nd+ loop of IEMExecLots.
    376  *
    377  * This is mostly a copy of iemInitDecoder.
    378  *
    379  * @param   pVCpu               The cross context virtual CPU structure of the calling EMT.
    380  */
    381 DECLINLINE(void) iemReInitDecoder(PVMCPUCC pVCpu)
    382 {
    383     Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_IEM));
    384     Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pVCpu->cpum.GstCtx.cs));
    385     Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pVCpu->cpum.GstCtx.ss));
    386     Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pVCpu->cpum.GstCtx.es));
    387     Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pVCpu->cpum.GstCtx.ds));
    388     Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pVCpu->cpum.GstCtx.fs));
    389     Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pVCpu->cpum.GstCtx.gs));
    390     Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pVCpu->cpum.GstCtx.ldtr));
    391     Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pVCpu->cpum.GstCtx.tr));
    392 
    393     /* ASSUMES: Anyone changing CPU state affecting the fExec bits will update them! */
    394     AssertMsg((pVCpu->iem.s.fExec & ~IEM_F_USER_OPTS) == iemCalcExecFlags(pVCpu),
    395               ("fExec=%#x iemCalcExecModeFlags=%#x\n", pVCpu->iem.s.fExec, iemCalcExecFlags(pVCpu)));
    396 
    397     IEMMODE const enmMode = IEM_GET_CPU_MODE(pVCpu);
    398     pVCpu->iem.s.enmDefAddrMode     = enmMode;  /** @todo check if this is correct... */
    399     pVCpu->iem.s.enmEffAddrMode     = enmMode;
    400     if (enmMode != IEMMODE_64BIT)
    401     {
    402         pVCpu->iem.s.enmDefOpSize   = enmMode;  /** @todo check if this is correct... */
    403         pVCpu->iem.s.enmEffOpSize   = enmMode;
    404     }
    405     else
    406     {
    407         pVCpu->iem.s.enmDefOpSize   = IEMMODE_32BIT;
    408         pVCpu->iem.s.enmEffOpSize   = IEMMODE_32BIT;
    409     }
    410     pVCpu->iem.s.fPrefixes          = 0;
    411     pVCpu->iem.s.uRexReg            = 0;
    412     pVCpu->iem.s.uRexB              = 0;
    413     pVCpu->iem.s.uRexIndex          = 0;
    414     pVCpu->iem.s.idxPrefix          = 0;
    415     pVCpu->iem.s.uVex3rdReg         = 0;
    416     pVCpu->iem.s.uVexLength         = 0;
    417     pVCpu->iem.s.fEvexStuff         = 0;
    418     pVCpu->iem.s.iEffSeg            = X86_SREG_DS;
    419 #ifdef IEM_WITH_CODE_TLB
    420     if (pVCpu->iem.s.pbInstrBuf)
    421     {
    422         uint64_t off = (enmMode == IEMMODE_64BIT
    423                         ? pVCpu->cpum.GstCtx.rip
    424                         : pVCpu->cpum.GstCtx.eip + (uint32_t)pVCpu->cpum.GstCtx.cs.u64Base)
    425                      - pVCpu->iem.s.uInstrBufPc;
    426         if (off < pVCpu->iem.s.cbInstrBufTotal)
    427         {
    428             pVCpu->iem.s.offInstrNextByte = (uint32_t)off;
    429             pVCpu->iem.s.offCurInstrStart = (uint16_t)off;
    430             if ((uint16_t)off + 15 <= pVCpu->iem.s.cbInstrBufTotal)
    431                 pVCpu->iem.s.cbInstrBuf = (uint16_t)off + 15;
    432             else
    433                 pVCpu->iem.s.cbInstrBuf = pVCpu->iem.s.cbInstrBufTotal;
    434         }
    435         else
    436         {
    437             pVCpu->iem.s.pbInstrBuf       = NULL;
    438             pVCpu->iem.s.offInstrNextByte = 0;
    439             pVCpu->iem.s.offCurInstrStart = 0;
    440             pVCpu->iem.s.cbInstrBuf       = 0;
    441             pVCpu->iem.s.cbInstrBufTotal  = 0;
    442             pVCpu->iem.s.GCPhysInstrBuf   = NIL_RTGCPHYS;
    443         }
    444     }
    445     else
    446     {
    447         pVCpu->iem.s.offInstrNextByte = 0;
    448         pVCpu->iem.s.offCurInstrStart = 0;
    449         pVCpu->iem.s.cbInstrBuf       = 0;
    450         pVCpu->iem.s.cbInstrBufTotal  = 0;
    451 # ifdef VBOX_STRICT
    452         pVCpu->iem.s.GCPhysInstrBuf   = NIL_RTGCPHYS;
    453 # endif
    454     }
    455 # ifdef IEM_WITH_CODE_TLB_AND_OPCODE_BUF
    456     pVCpu->iem.s.offOpcode          = 0;
    457 # endif
    458 #else  /* !IEM_WITH_CODE_TLB */
    459     pVCpu->iem.s.cbOpcode           = 0;
    460     pVCpu->iem.s.offOpcode          = 0;
    461 #endif /* !IEM_WITH_CODE_TLB */
    462     pVCpu->iem.s.offModRm           = 0;
    463     Assert(pVCpu->iem.s.cActiveMappings == 0);
    464     pVCpu->iem.s.iNextMapping       = 0;
    465     Assert(pVCpu->iem.s.rcPassUp   == VINF_SUCCESS);
    466     Assert(!(pVCpu->iem.s.fExec & IEM_F_BYPASS_HANDLERS));
    467 
    468 #ifdef DBGFTRACE_ENABLED
    469     switch (enmMode)
    470     {
    471         case IEMMODE_64BIT:
    472             RTTraceBufAddMsgF(pVCpu->CTX_SUFF(pVM)->CTX_SUFF(hTraceBuf), "I64/%u %08llx", IEM_GET_CPL(pVCpu), pVCpu->cpum.GstCtx.rip);
    473             break;
    474         case IEMMODE_32BIT:
    475             RTTraceBufAddMsgF(pVCpu->CTX_SUFF(pVM)->CTX_SUFF(hTraceBuf), "I32/%u %04x:%08x", IEM_GET_CPL(pVCpu), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.eip);
    476             break;
    477         case IEMMODE_16BIT:
    478             RTTraceBufAddMsgF(pVCpu->CTX_SUFF(pVM)->CTX_SUFF(hTraceBuf), "I16/%u %04x:%04x", IEM_GET_CPL(pVCpu), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.eip);
    479             break;
    480     }
    481 #endif
    482 }
    483 
    484 
    485 
    486 /**
    487  * Prefetch opcodes the first time when starting executing.
    488  *
    489  * @returns Strict VBox status code.
    490  * @param   pVCpu               The cross context virtual CPU structure of the
    491  *                              calling thread.
    492  * @param   fExecOpts           Optional execution flags:
    493  *                                  - IEM_F_BYPASS_HANDLERS
    494  *                                  - IEM_F_X86_DISREGARD_LOCK
    495  */
    496 static VBOXSTRICTRC iemInitDecoderAndPrefetchOpcodes(PVMCPUCC pVCpu, uint32_t fExecOpts) RT_NOEXCEPT
    497 {
    498     iemInitDecoder(pVCpu, fExecOpts);
    499 
    500 #ifndef IEM_WITH_CODE_TLB
    501     /*
    502      * What we're doing here is very similar to iemMemMap/iemMemBounceBufferMap.
    503      *
    504      * First translate CS:rIP to a physical address.
    505      *
    506      * Note! The iemOpcodeFetchMoreBytes code depends on this here code to fetch
    507      *       all relevant bytes from the first page, as it ASSUMES it's only ever
    508      *       called for dealing with CS.LIM, page crossing and instructions that
    509      *       are too long.
    510      */
    511     uint32_t    cbToTryRead;
    512     RTGCPTR     GCPtrPC;
    513     if (IEM_IS_64BIT_CODE(pVCpu))
    514     {
    515         cbToTryRead = GUEST_PAGE_SIZE;
    516         GCPtrPC     = pVCpu->cpum.GstCtx.rip;
    517         if (IEM_IS_CANONICAL(GCPtrPC))
    518             cbToTryRead = GUEST_PAGE_SIZE - (GCPtrPC & GUEST_PAGE_OFFSET_MASK);
    519         else
    520             return iemRaiseGeneralProtectionFault0(pVCpu);
    521     }
    522     else
    523     {
    524         uint32_t GCPtrPC32 = pVCpu->cpum.GstCtx.eip;
    525         AssertMsg(!(GCPtrPC32 & ~(uint32_t)UINT16_MAX) || IEM_IS_32BIT_CODE(pVCpu), ("%04x:%RX64\n", pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
    526         if (GCPtrPC32 <= pVCpu->cpum.GstCtx.cs.u32Limit)
    527             cbToTryRead = pVCpu->cpum.GstCtx.cs.u32Limit - GCPtrPC32 + 1;
    528         else
    529             return iemRaiseSelectorBounds(pVCpu, X86_SREG_CS, IEM_ACCESS_INSTRUCTION);
    530         if (cbToTryRead) { /* likely */ }
    531         else /* overflowed */
    532         {
    533             Assert(GCPtrPC32 == 0); Assert(pVCpu->cpum.GstCtx.cs.u32Limit == UINT32_MAX);
    534             cbToTryRead = UINT32_MAX;
    535         }
    536         GCPtrPC = (uint32_t)pVCpu->cpum.GstCtx.cs.u64Base + GCPtrPC32;
    537         Assert(GCPtrPC <= UINT32_MAX);
    538     }
    539 
    540     PGMPTWALKFAST WalkFast;
    541     int rc = PGMGstQueryPageFast(pVCpu, GCPtrPC,
    542                                  IEM_GET_CPL(pVCpu) == 3 ? PGMQPAGE_F_EXECUTE | PGMQPAGE_F_USER_MODE : PGMQPAGE_F_EXECUTE,
    543                                  &WalkFast);
    544     if (RT_SUCCESS(rc))
    545         Assert(WalkFast.fInfo & PGM_WALKINFO_SUCCEEDED);
    546     else
    547     {
    548         Log(("iemInitDecoderAndPrefetchOpcodes: %RGv - rc=%Rrc\n", GCPtrPC, rc));
    549 # ifdef VBOX_WITH_NESTED_HWVIRT_VMX_EPT
    550 /** @todo This isn't quite right yet, as PGM_GST_SLAT_NAME_EPT(Walk) doesn't
    551  * know about what kind of access we're making! See PGM_GST_NAME(WalkFast). */
    552         if (WalkFast.fFailed & PGM_WALKFAIL_EPT)
    553             IEM_VMX_VMEXIT_EPT_RET(pVCpu, &WalkFast, IEM_ACCESS_INSTRUCTION, IEM_SLAT_FAIL_LINEAR_TO_PHYS_ADDR, 0 /* cbInstr */);
    554 # endif
    555         return iemRaisePageFault(pVCpu, GCPtrPC, 1, IEM_ACCESS_INSTRUCTION, rc);
    556     }
    557 #if 0
    558     if ((WalkFast.fEffective & X86_PTE_US) || IEM_GET_CPL(pVCpu) != 3) { /* likely */ }
    559     else
    560     {
    561         Log(("iemInitDecoderAndPrefetchOpcodes: %RGv - supervisor page\n", GCPtrPC));
    562 # ifdef VBOX_WITH_NESTED_HWVIRT_VMX_EPT
    563 /** @todo this is completely wrong for EPT. WalkFast.fFailed is always zero here!*/
    564 #  error completely wrong
    565         if (WalkFast.fFailed & PGM_WALKFAIL_EPT)
    566             IEM_VMX_VMEXIT_EPT_RET(pVCpu, &WalkFast, IEM_ACCESS_INSTRUCTION, IEM_SLAT_FAIL_LINEAR_TO_PAGE_TABLE, 0 /* cbInstr */);
    567 # endif
    568         return iemRaisePageFault(pVCpu, GCPtrPC, 1, IEM_ACCESS_INSTRUCTION, VERR_ACCESS_DENIED);
    569     }
    570     if (!(WalkFast.fEffective & X86_PTE_PAE_NX) || !(pVCpu->cpum.GstCtx.msrEFER & MSR_K6_EFER_NXE)) { /* likely */ }
    571     else
    572     {
    573         Log(("iemInitDecoderAndPrefetchOpcodes: %RGv - NX\n", GCPtrPC));
    574 # ifdef VBOX_WITH_NESTED_HWVIRT_VMX_EPT
    575 /** @todo this is completely wrong for EPT. WalkFast.fFailed is always zero here!*/
    576 #  error completely wrong.
    577         if (WalkFast.fFailed & PGM_WALKFAIL_EPT)
    578             IEM_VMX_VMEXIT_EPT_RET(pVCpu, &WalkFast, IEM_ACCESS_INSTRUCTION, IEM_SLAT_FAIL_LINEAR_TO_PAGE_TABLE, 0 /* cbInstr */);
    579 # endif
    580         return iemRaisePageFault(pVCpu, GCPtrPC, 1, IEM_ACCESS_INSTRUCTION, VERR_ACCESS_DENIED);
    581     }
    582 #else
    583     Assert((WalkFast.fEffective & X86_PTE_US) || IEM_GET_CPL(pVCpu) != 3);
    584     Assert(!(WalkFast.fEffective & X86_PTE_PAE_NX) || !(pVCpu->cpum.GstCtx.msrEFER & MSR_K6_EFER_NXE));
    585 #endif
    586     RTGCPHYS const GCPhys = WalkFast.GCPhys;
    587 
    588     /*
    589      * Read the bytes at this address.
    590      */
    591     uint32_t cbLeftOnPage = GUEST_PAGE_SIZE - (GCPtrPC & GUEST_PAGE_OFFSET_MASK);
    592     if (cbToTryRead > cbLeftOnPage)
    593         cbToTryRead = cbLeftOnPage;
    594     if (cbToTryRead > sizeof(pVCpu->iem.s.abOpcode))
    595         cbToTryRead = sizeof(pVCpu->iem.s.abOpcode);
    596 
    597     if (!(pVCpu->iem.s.fExec & IEM_F_BYPASS_HANDLERS))
    598     {
    599         VBOXSTRICTRC rcStrict = PGMPhysRead(pVCpu->CTX_SUFF(pVM), GCPhys, pVCpu->iem.s.abOpcode, cbToTryRead, PGMACCESSORIGIN_IEM);
    600         if (RT_LIKELY(rcStrict == VINF_SUCCESS))
    601         { /* likely */ }
    602         else if (PGM_PHYS_RW_IS_SUCCESS(rcStrict))
    603         {
    604             Log(("iemInitDecoderAndPrefetchOpcodes: %RGv/%RGp LB %#x - read status -  rcStrict=%Rrc\n",
    605                  GCPtrPC, GCPhys, VBOXSTRICTRC_VAL(rcStrict), cbToTryRead));
    606             rcStrict = iemSetPassUpStatus(pVCpu, rcStrict);
    607         }
    608         else
    609         {
    610             Log((RT_SUCCESS(rcStrict)
    611                  ? "iemInitDecoderAndPrefetchOpcodes: %RGv/%RGp LB %#x - read status - rcStrict=%Rrc\n"
    612                  : "iemInitDecoderAndPrefetchOpcodes: %RGv/%RGp LB %#x - read error - rcStrict=%Rrc (!!)\n",
    613                  GCPtrPC, GCPhys, VBOXSTRICTRC_VAL(rcStrict), cbToTryRead));
    614             return rcStrict;
    615         }
    616     }
    617     else
    618     {
    619         rc = PGMPhysSimpleReadGCPhys(pVCpu->CTX_SUFF(pVM), pVCpu->iem.s.abOpcode, GCPhys, cbToTryRead);
    620         if (RT_SUCCESS(rc))
    621         { /* likely */ }
    622         else
    623         {
    624             Log(("iemInitDecoderAndPrefetchOpcodes: %RGv/%RGp LB %#x - read error - rc=%Rrc (!!)\n",
    625                  GCPtrPC, GCPhys, rc, cbToTryRead));
    626             return rc;
    627         }
    628     }
    629     pVCpu->iem.s.cbOpcode = cbToTryRead;
    630 #endif /* !IEM_WITH_CODE_TLB */
    631     return VINF_SUCCESS;
    632 }
    633 
    634 
    635 #if defined(IEM_WITH_CODE_TLB) || defined(IEM_WITH_DATA_TLB)
    636 /**
    637  * Helper for doing large page accounting at TLB load time.
    638  */
    639 template<bool const a_fGlobal>
    640 DECL_FORCE_INLINE(void) iemTlbLoadedLargePage(PVMCPUCC pVCpu, IEMTLB *pTlb, RTGCPTR uTagNoRev, bool f2MbLargePages)
    641 {
    642     if (a_fGlobal)
    643         pTlb->cTlbGlobalLargePageCurLoads++;
    644     else
    645         pTlb->cTlbNonGlobalLargePageCurLoads++;
    646 
    647 # ifdef IEMTLB_WITH_LARGE_PAGE_BITMAP
    648     RTGCPTR const idxBit = IEMTLB_TAG_TO_EVEN_INDEX(uTagNoRev) + a_fGlobal;
    649     ASMBitSet(pTlb->bmLargePage, idxBit);
    650 # endif
    651 
    652     AssertCompile(IEMTLB_CALC_TAG_NO_REV((RTGCPTR)0x8731U << GUEST_PAGE_SHIFT) == 0x8731U);
    653     uint32_t const                 fMask = (f2MbLargePages ? _2M - 1U : _4M - 1U) >> GUEST_PAGE_SHIFT;
    654     IEMTLB::LARGEPAGERANGE * const pRange = a_fGlobal
    655                                           ? &pTlb->GlobalLargePageRange
    656                                           : &pTlb->NonGlobalLargePageRange;
    657     uTagNoRev &= ~(RTGCPTR)fMask;
    658     if (uTagNoRev < pRange->uFirstTag)
    659         pRange->uFirstTag = uTagNoRev;
    660 
    661     uTagNoRev |= fMask;
    662     if (uTagNoRev > pRange->uLastTag)
    663         pRange->uLastTag = uTagNoRev;
    664 
    665     RT_NOREF_PV(pVCpu);
    666 }
    667 #endif
    668 
    669 
    670 #if defined(IEM_WITH_CODE_TLB) || defined(IEM_WITH_DATA_TLB)
    671 /**
    672  * Worker for iemTlbInvalidateAll.
    673  */
    674 template<bool a_fGlobal>
    675 DECL_FORCE_INLINE(void) iemTlbInvalidateOne(IEMTLB *pTlb)
    676 {
    677     if (!a_fGlobal)
    678         pTlb->cTlsFlushes++;
    679     else
    680         pTlb->cTlsGlobalFlushes++;
    681 
    682     pTlb->uTlbRevision += IEMTLB_REVISION_INCR;
    683     if (RT_LIKELY(pTlb->uTlbRevision != 0))
    684     { /* very likely */ }
    685     else
    686     {
    687         pTlb->uTlbRevision = IEMTLB_REVISION_INCR;
    688         pTlb->cTlbRevisionRollovers++;
    689         unsigned i = RT_ELEMENTS(pTlb->aEntries) / 2;
    690         while (i-- > 0)
    691             pTlb->aEntries[i * 2].uTag = 0;
    692     }
    693 
    694     pTlb->cTlbNonGlobalLargePageCurLoads    = 0;
    695     pTlb->NonGlobalLargePageRange.uLastTag  = 0;
    696     pTlb->NonGlobalLargePageRange.uFirstTag = UINT64_MAX;
    697 
    698     if (a_fGlobal)
    699     {
    700         pTlb->uTlbRevisionGlobal += IEMTLB_REVISION_INCR;
    701         if (RT_LIKELY(pTlb->uTlbRevisionGlobal != 0))
    702         { /* very likely */ }
    703         else
    704         {
    705             pTlb->uTlbRevisionGlobal = IEMTLB_REVISION_INCR;
    706             pTlb->cTlbRevisionRollovers++;
    707             unsigned i = RT_ELEMENTS(pTlb->aEntries) / 2;
    708             while (i-- > 0)
    709                 pTlb->aEntries[i * 2 + 1].uTag = 0;
    710         }
    711 
    712         pTlb->cTlbGlobalLargePageCurLoads    = 0;
    713         pTlb->GlobalLargePageRange.uLastTag  = 0;
    714         pTlb->GlobalLargePageRange.uFirstTag = UINT64_MAX;
    715     }
    716 }
    717 #endif
    718 
    719 
    720 /**
    721  * Worker for IEMTlbInvalidateAll and IEMTlbInvalidateAllGlobal.
    722  */
    723 template<bool a_fGlobal>
    724 DECL_FORCE_INLINE(void) iemTlbInvalidateAll(PVMCPUCC pVCpu)
    725 {
    726 #if defined(IEM_WITH_CODE_TLB) || defined(IEM_WITH_DATA_TLB)
    727     Log10(("IEMTlbInvalidateAll\n"));
    728 
    729 # ifdef IEM_WITH_CODE_TLB
    730     pVCpu->iem.s.cbInstrBufTotal = 0;
    731     iemTlbInvalidateOne<a_fGlobal>(&pVCpu->iem.s.CodeTlb);
    732     if (a_fGlobal)
    733         IEMTLBTRACE_FLUSH_GLOBAL(pVCpu, pVCpu->iem.s.CodeTlb.uTlbRevision, pVCpu->iem.s.CodeTlb.uTlbRevisionGlobal, false);
    734     else
    735         IEMTLBTRACE_FLUSH(pVCpu, pVCpu->iem.s.CodeTlb.uTlbRevision, false);
    736 # endif
    737 
    738 # ifdef IEM_WITH_DATA_TLB
    739     iemTlbInvalidateOne<a_fGlobal>(&pVCpu->iem.s.DataTlb);
    740     if (a_fGlobal)
    741         IEMTLBTRACE_FLUSH_GLOBAL(pVCpu, pVCpu->iem.s.DataTlb.uTlbRevision, pVCpu->iem.s.DataTlb.uTlbRevisionGlobal, true);
    742     else
    743         IEMTLBTRACE_FLUSH(pVCpu, pVCpu->iem.s.DataTlb.uTlbRevision, true);
    744 # endif
    745 #else
    746     RT_NOREF(pVCpu);
    747 #endif
    748 }
    749 
    750 
    751 /**
    752  * Invalidates non-global the IEM TLB entries.
    753  *
    754  * This is called internally as well as by PGM when moving GC mappings.
    755  *
    756  * @param   pVCpu       The cross context virtual CPU structure of the calling
    757  *                      thread.
    758  */
    759 VMM_INT_DECL(void) IEMTlbInvalidateAll(PVMCPUCC pVCpu)
    760 {
    761     iemTlbInvalidateAll<false>(pVCpu);
    762 }
    763 
    764 
    765 /**
    766  * Invalidates all the IEM TLB entries.
    767  *
    768  * This is called internally as well as by PGM when moving GC mappings.
    769  *
    770  * @param   pVCpu       The cross context virtual CPU structure of the calling
    771  *                      thread.
    772  */
    773 VMM_INT_DECL(void) IEMTlbInvalidateAllGlobal(PVMCPUCC pVCpu)
    774 {
    775     iemTlbInvalidateAll<true>(pVCpu);
    776 }
    777 
    778 
    779 #if defined(IEM_WITH_CODE_TLB) || defined(IEM_WITH_DATA_TLB)
    780 
    781 /** @todo graduate this to cdefs.h or asm-mem.h.   */
    782 # ifdef RT_ARCH_ARM64              /** @todo RT_CACHELINE_SIZE is wrong for M1 */
    783 #  undef RT_CACHELINE_SIZE
    784 #  define RT_CACHELINE_SIZE 128
    785 # endif
    786 
    787 # if defined(_MM_HINT_T0) && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86))
    788 #  define MY_PREFETCH(a_pvAddr)     _mm_prefetch((const char *)(a_pvAddr), _MM_HINT_T0)
    789 # elif defined(_MSC_VER) && (defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32))
    790 #  define MY_PREFETCH(a_pvAddr)     __prefetch((a_pvAddr))
    791 # elif defined(__GNUC__) || RT_CLANG_HAS_FEATURE(__builtin_prefetch)
    792 #  define MY_PREFETCH(a_pvAddr)     __builtin_prefetch((a_pvAddr), 0 /*rw*/, 3 /*locality*/)
    793 # else
    794 #  define MY_PREFETCH(a_pvAddr)     ((void)0)
    795 # endif
    796 # if 0
    797 #  undef  MY_PREFETCH
    798 #  define MY_PREFETCH(a_pvAddr)     ((void)0)
    799 # endif
    800 
    801 /** @def MY_PREFETCH_64
    802  * 64 byte prefetch hint, could be more depending on cache line size. */
    803 /** @def MY_PREFETCH_128
    804  * 128 byte prefetch hint. */
    805 /** @def MY_PREFETCH_256
    806  * 256 byte prefetch hint. */
    807 # if RT_CACHELINE_SIZE >= 128
    808     /* 128 byte cache lines */
    809 #  define MY_PREFETCH_64(a_pvAddr)  MY_PREFETCH(a_pvAddr)
    810 #  define MY_PREFETCH_128(a_pvAddr) MY_PREFETCH(a_pvAddr)
    811 #  define MY_PREFETCH_256(a_pvAddr) do { \
    812         MY_PREFETCH(a_pvAddr); \
    813         MY_PREFETCH((uint8_t const *)a_pvAddr + 128); \
    814     } while (0)
    815 # else
    816     /* 64 byte cache lines */
    817 #  define MY_PREFETCH_64(a_pvAddr)  MY_PREFETCH(a_pvAddr)
    818 #  define MY_PREFETCH_128(a_pvAddr) do { \
    819         MY_PREFETCH(a_pvAddr); \
    820         MY_PREFETCH((uint8_t const *)a_pvAddr + 64); \
    821     } while (0)
    822 #  define MY_PREFETCH_256(a_pvAddr) do { \
    823         MY_PREFETCH(a_pvAddr); \
    824         MY_PREFETCH((uint8_t const *)a_pvAddr + 64); \
    825         MY_PREFETCH((uint8_t const *)a_pvAddr + 128); \
    826         MY_PREFETCH((uint8_t const *)a_pvAddr + 192); \
    827     } while (0)
    828 # endif
    829 
    830 template<bool const a_fDataTlb, bool const a_f2MbLargePage, bool const a_fGlobal, bool const a_fNonGlobal>
    831 DECLINLINE(void) iemTlbInvalidateLargePageWorkerInner(PVMCPUCC pVCpu, IEMTLB *pTlb, RTGCPTR GCPtrTag,
    832                                                       RTGCPTR GCPtrInstrBufPcTag) RT_NOEXCEPT
    833 {
    834     IEMTLBTRACE_LARGE_SCAN(pVCpu, a_fGlobal, a_fNonGlobal, a_fDataTlb);
    835     AssertCompile(IEMTLB_ENTRY_COUNT >= 16); /* prefetching + unroll assumption */
    836 
    837     if (a_fGlobal)
    838         pTlb->cTlbInvlPgLargeGlobal += 1;
    839     if (a_fNonGlobal)
    840         pTlb->cTlbInvlPgLargeNonGlobal += 1;
    841 
    842     /*
    843      * Set up the scan.
    844      *
    845      * GCPtrTagMask: A 2MB page consists of 512 4K pages, so a 256 TLB will map
    846      * offset zero and offset 1MB to the same slot pair.  Our GCPtrTag[Globl]
    847      * values are for the range 0-1MB, or slots 0-256.  So, we construct a mask
    848      * that fold large page offsets 1MB-2MB into the 0-1MB range.
    849      *
    850      * For our example with 2MB pages and a 256 entry TLB: 0xfffffffffffffeff
    851      *
    852      * MY_PREFETCH: Hope that prefetching 256 bytes at the time is okay for
    853      * relevant host architectures.
    854      */
    855     /** @todo benchmark this code from the guest side. */
    856     bool const      fPartialScan = IEMTLB_ENTRY_COUNT > (a_f2MbLargePage ? 512 : 1024);
    857 #ifdef IEMTLB_WITH_LARGE_PAGE_BITMAP
    858     uintptr_t       idxBitmap    = fPartialScan ? IEMTLB_TAG_TO_EVEN_INDEX(GCPtrTag) / 64 : 0;
    859     uintptr_t const idxBitmapEnd = fPartialScan ? idxBitmap + ((a_f2MbLargePage ? 512 : 1024) * 2) / 64
    860                                                 : IEMTLB_ENTRY_COUNT * 2 / 64;
    861 #else
    862     uintptr_t       idxEven      = fPartialScan ? IEMTLB_TAG_TO_EVEN_INDEX(GCPtrTag) : 0;
    863     MY_PREFETCH_256(&pTlb->aEntries[idxEven + !a_fNonGlobal]);
    864     uintptr_t const idxEvenEnd   = fPartialScan ? idxEven + ((a_f2MbLargePage ? 512 : 1024) * 2) : IEMTLB_ENTRY_COUNT * 2;
    865 #endif
    866     RTGCPTR const   GCPtrTagMask = fPartialScan ? ~(RTGCPTR)0
    867                                  : ~(RTGCPTR)(  (RT_BIT_32(a_f2MbLargePage ? 9 : 10) - 1U)
    868                                               & ~(uint32_t)(RT_BIT_32(IEMTLB_ENTRY_COUNT_AS_POWER_OF_TWO) - 1U));
    869 
    870     /*
    871      * Set cbInstrBufTotal to zero if GCPtrInstrBufPcTag is within any of the tag ranges.
    872      * We make ASSUMPTIONS about IEMTLB_CALC_TAG_NO_REV here.
    873      */
    874     AssertCompile(IEMTLB_CALC_TAG_NO_REV((RTGCPTR)0x8731U << GUEST_PAGE_SHIFT) == 0x8731U);
    875     if (   !a_fDataTlb
    876         && GCPtrInstrBufPcTag - GCPtrTag < (a_f2MbLargePage ? 512U : 1024U))
    877         pVCpu->iem.s.cbInstrBufTotal = 0;
    878 
    879     /*
    880      * Combine TAG values with the TLB revisions.
    881      */
    882     RTGCPTR GCPtrTagGlob = a_fGlobal ? GCPtrTag | pTlb->uTlbRevisionGlobal : 0;
    883     if (a_fNonGlobal)
    884         GCPtrTag |= pTlb->uTlbRevision;
    885 
    886     /*
    887      * Do the scanning.
    888      */
    889 #ifdef IEMTLB_WITH_LARGE_PAGE_BITMAP
    890     uint64_t const bmMask  = a_fGlobal && a_fNonGlobal ? UINT64_MAX
    891                            : a_fGlobal ? UINT64_C(0xaaaaaaaaaaaaaaaa) : UINT64_C(0x5555555555555555);
    892     /* Scan bitmap entries (64 bits at the time): */
    893     for (;;)
    894     {
    895 # if 1
    896         uint64_t bmEntry = pTlb->bmLargePage[idxBitmap] & bmMask;
    897         if (bmEntry)
    898         {
    899             /* Scan the non-zero 64-bit value in groups of 8 bits: */
    900             uint64_t  bmToClear = 0;
    901             uintptr_t idxEven   = idxBitmap * 64;
    902             uint32_t  idxTag    = 0;
    903             for (;;)
    904             {
    905                 if (bmEntry & 0xff)
    906                 {
    907 #  define ONE_PAIR(a_idxTagIter, a_idxEvenIter, a_bmNonGlobal, a_bmGlobal) \
    908                         if (a_fNonGlobal) \
    909                         { \
    910                             if (bmEntry & a_bmNonGlobal) \
    911                             { \
    912                                 Assert(pTlb->aEntries[a_idxEvenIter].fFlagsAndPhysRev & IEMTLBE_F_PT_LARGE_PAGE); \
    913                                 if ((pTlb->aEntries[a_idxEvenIter].uTag & GCPtrTagMask) == (GCPtrTag + a_idxTagIter)) \
    914                                 { \
    915                                     IEMTLBTRACE_LARGE_EVICT_SLOT(pVCpu, GCPtrTag + a_idxTagIter, \
    916                                                                  pTlb->aEntries[a_idxEvenIter].GCPhys, \
    917                                                                  a_idxEvenIter, a_fDataTlb); \
    918                                     pTlb->aEntries[a_idxEvenIter].uTag = 0; \
    919                                     bmToClearSub8 |= a_bmNonGlobal; \
    920                                 } \
    921                             } \
    922                             else \
    923                                 Assert(   !(pTlb->aEntries[a_idxEvenIter].fFlagsAndPhysRev & IEMTLBE_F_PT_LARGE_PAGE)\
    924                                        ||    (pTlb->aEntries[a_idxEvenIter].uTag & IEMTLB_REVISION_MASK) \
    925                                           != (GCPtrTag & IEMTLB_REVISION_MASK)); \
    926                         } \
    927                         if (a_fGlobal) \
    928                         { \
    929                             if (bmEntry & a_bmGlobal) \
    930                             {  \
    931                                 Assert(pTlb->aEntries[a_idxEvenIter + 1].fFlagsAndPhysRev & IEMTLBE_F_PT_LARGE_PAGE); \
    932                                 if ((pTlb->aEntries[a_idxEvenIter + 1].uTag & GCPtrTagMask) == (GCPtrTagGlob + a_idxTagIter)) \
    933                                 { \
    934                                     IEMTLBTRACE_LARGE_EVICT_SLOT(pVCpu, GCPtrTagGlob + a_idxTagIter, \
    935                                                                  pTlb->aEntries[a_idxEvenIter + 1].GCPhys, \
    936                                                                  a_idxEvenIter + 1, a_fDataTlb); \
    937                                     pTlb->aEntries[a_idxEvenIter + 1].uTag = 0; \
    938                                     bmToClearSub8 |= a_bmGlobal; \
    939                                 } \
    940                             } \
    941                             else \
    942                                 Assert(   !(pTlb->aEntries[a_idxEvenIter + 1].fFlagsAndPhysRev & IEMTLBE_F_PT_LARGE_PAGE)\
    943                                        ||    (pTlb->aEntries[a_idxEvenIter + 1].uTag & IEMTLB_REVISION_MASK) \
    944                                           != (GCPtrTagGlob & IEMTLB_REVISION_MASK)); \
    945                         }
    946                     uint64_t bmToClearSub8 = 0;
    947                     ONE_PAIR(idxTag + 0, idxEven + 0, 0x01, 0x02)
    948                     ONE_PAIR(idxTag + 1, idxEven + 2, 0x04, 0x08)
    949                     ONE_PAIR(idxTag + 2, idxEven + 4, 0x10, 0x20)
    950                     ONE_PAIR(idxTag + 3, idxEven + 6, 0x40, 0x80)
    951                     bmToClear |= bmToClearSub8 << (idxTag * 2);
    952 #  undef ONE_PAIR
    953                 }
    954 
    955                 /* advance to the next 8 bits. */
    956                 bmEntry >>= 8;
    957                 if (!bmEntry)
    958                     break;
    959                 idxEven  += 8;
    960                 idxTag   += 4;
    961             }
    962 
    963             /* Clear the large page flags we covered. */
    964             pTlb->bmLargePage[idxBitmap] &= ~bmToClear;
    965         }
    966 # else
    967         uint64_t const bmEntry = pTlb->bmLargePage[idxBitmap] & bmMask;
    968         if (bmEntry)
    969         {
    970             /* Scan the non-zero 64-bit value completely unrolled: */
    971             uintptr_t const idxEven   = idxBitmap * 64;
    972             uint64_t        bmToClear = 0;
    973 #  define ONE_PAIR(a_idxTagIter, a_idxEvenIter, a_bmNonGlobal, a_bmGlobal) \
    974                 if (a_fNonGlobal) \
    975                 { \
    976                     if (bmEntry & a_bmNonGlobal) \
    977                     { \
    978                         Assert(pTlb->aEntries[a_idxEvenIter].fFlagsAndPhysRev & IEMTLBE_F_PT_LARGE_PAGE); \
    979                         if ((pTlb->aEntries[a_idxEvenIter].uTag & GCPtrTagMask) == (GCPtrTag + a_idxTagIter)) \
    980                         { \
    981                             IEMTLBTRACE_LARGE_EVICT_SLOT(pVCpu, GCPtrTag + a_idxTagIter, \
    982                                                          pTlb->aEntries[a_idxEvenIter].GCPhys, \
    983                                                          a_idxEvenIter, a_fDataTlb); \
    984                             pTlb->aEntries[a_idxEvenIter].uTag = 0; \
    985                             bmToClear |= a_bmNonGlobal; \
    986                         } \
    987                     } \
    988                     else \
    989                         Assert(   !(pTlb->aEntriqes[a_idxEvenIter].fFlagsAndPhysRev & IEMTLBE_F_PT_LARGE_PAGE)\
    990                                ||    (pTlb->aEntries[a_idxEvenIter].uTag & IEMTLB_REVISION_MASK) \
    991                                   != (GCPtrTag & IEMTLB_REVISION_MASK)); \
    992                 } \
    993                 if (a_fGlobal) \
    994                 { \
    995                     if (bmEntry & a_bmGlobal) \
    996                     {  \
    997                         Assert(pTlb->aEntries[a_idxEvenIter + 1].fFlagsAndPhysRev & IEMTLBE_F_PT_LARGE_PAGE); \
    998                         if ((pTlb->aEntries[a_idxEvenIter + 1].uTag & GCPtrTagMask) == (GCPtrTagGlob + a_idxTagIter)) \
    999                         { \
    1000                             IEMTLBTRACE_LARGE_EVICT_SLOT(pVCpu, GCPtrTagGlob + a_idxTagIter, \
    1001                                                          pTlb->aEntries[a_idxEvenIter + 1].GCPhys, \
    1002                                                          a_idxEvenIter + 1, a_fDataTlb); \
    1003                             pTlb->aEntries[a_idxEvenIter + 1].uTag = 0; \
    1004                             bmToClear |= a_bmGlobal; \
    1005                         } \
    1006                     } \
    1007                     else \
    1008                         Assert(   !(pTlb->aEntries[a_idxEvenIter + 1].fFlagsAndPhysRev & IEMTLBE_F_PT_LARGE_PAGE)\
    1009                                ||    (pTlb->aEntries[a_idxEvenIter + 1].uTag & IEMTLB_REVISION_MASK) \
    1010                                   != (GCPtrTagGlob & IEMTLB_REVISION_MASK)); \
    1011                 } ((void)0)
    1012 #  define FOUR_PAIRS(a_iByte, a_cShift) \
    1013                 ONE_PAIR(0 + a_iByte * 4, idxEven + 0 + a_iByte * 8, UINT64_C(0x01) << a_cShift, UINT64_C(0x02) << a_cShift); \
    1014                 ONE_PAIR(1 + a_iByte * 4, idxEven + 2 + a_iByte * 8, UINT64_C(0x04) << a_cShift, UINT64_C(0x08) << a_cShift); \
    1015                 ONE_PAIR(2 + a_iByte * 4, idxEven + 4 + a_iByte * 8, UINT64_C(0x10) << a_cShift, UINT64_C(0x20) << a_cShift); \
    1016                 ONE_PAIR(3 + a_iByte * 4, idxEven + 6 + a_iByte * 8, UINT64_C(0x40) << a_cShift, UINT64_C(0x80) << a_cShift)
    1017             if (bmEntry & (uint32_t)UINT16_MAX)
    1018             {
    1019                 FOUR_PAIRS(0,  0);
    1020                 FOUR_PAIRS(1,  8);
    1021             }
    1022             if (bmEntry & ((uint32_t)UINT16_MAX << 16))
    1023             {
    1024                 FOUR_PAIRS(2, 16);
    1025                 FOUR_PAIRS(3, 24);
    1026             }
    1027             if (bmEntry & ((uint64_t)UINT16_MAX << 32))
    1028             {
    1029                 FOUR_PAIRS(4, 32);
    1030                 FOUR_PAIRS(5, 40);
    1031             }
    1032             if (bmEntry & ((uint64_t)UINT16_MAX << 16))
    1033             {
    1034                 FOUR_PAIRS(6, 48);
    1035                 FOUR_PAIRS(7, 56);
    1036             }
    1037 #  undef FOUR_PAIRS
    1038 
    1039             /* Clear the large page flags we covered. */
    1040             pTlb->bmLargePage[idxBitmap] &= ~bmToClear;
    1041         }
    1042 # endif
    1043 
    1044         /* advance */
    1045         idxBitmap++;
    1046         if (idxBitmap >= idxBitmapEnd)
    1047             break;
    1048         if (a_fNonGlobal)
    1049             GCPtrTag     += 32;
    1050         if (a_fGlobal)
    1051             GCPtrTagGlob += 32;
    1052     }
    1053 
    1054 #else  /* !IEMTLB_WITH_LARGE_PAGE_BITMAP */
    1055 
    1056     for (; idxEven < idxEvenEnd; idxEven += 8)
    1057     {
    1058 # define ONE_ITERATION(a_idxEvenIter) \
    1059             if (a_fNonGlobal)  \
    1060             { \
    1061                 if ((pTlb->aEntries[a_idxEvenIter].uTag & GCPtrTagMask) == GCPtrTag) \
    1062                 { \
    1063                     if (pTlb->aEntries[a_idxEvenIter].fFlagsAndPhysRev & IEMTLBE_F_PT_LARGE_PAGE) \
    1064                     { \
    1065                         IEMTLBTRACE_LARGE_EVICT_SLOT(pVCpu, GCPtrTag, pTlb->aEntries[a_idxEvenIter].GCPhys, \
    1066                                                      a_idxEvenIter, a_fDataTlb); \
    1067                         pTlb->aEntries[a_idxEvenIter].uTag = 0; \
    1068                     } \
    1069                 } \
    1070                 GCPtrTag++; \
    1071             } \
    1072             \
    1073             if (a_fGlobal) \
    1074             { \
    1075                 if ((pTlb->aEntries[a_idxEvenIter + 1].uTag & GCPtrTagMask) == GCPtrTagGlob) \
    1076                 { \
    1077                     if (pTlb->aEntries[a_idxEvenIter + 1].fFlagsAndPhysRev & IEMTLBE_F_PT_LARGE_PAGE) \
    1078                     { \
    1079                         IEMTLBTRACE_LARGE_EVICT_SLOT(pVCpu, GCPtrTag, pTlb->aEntries[a_idxEvenIter + 1].GCPhys, \
    1080                                                      a_idxEvenIter + 1, a_fDataTlb); \
    1081                         pTlb->aEntries[a_idxEvenIter + 1].uTag = 0; \
    1082                     } \
    1083                 } \
    1084                 GCPtrTagGlob++; \
    1085             }
    1086         if (idxEven < idxEvenEnd - 4)
    1087             MY_PREFETCH_256(&pTlb->aEntries[idxEven +  8 + !a_fNonGlobal]);
    1088         ONE_ITERATION(idxEven)
    1089         ONE_ITERATION(idxEven + 2)
    1090         ONE_ITERATION(idxEven + 4)
    1091         ONE_ITERATION(idxEven + 6)
    1092 # undef ONE_ITERATION
    1093     }
    1094 #endif /* !IEMTLB_WITH_LARGE_PAGE_BITMAP */
    1095 }
    1096 
    1097 template<bool const a_fDataTlb, bool const a_f2MbLargePage>
    1098 DECLINLINE(void) iemTlbInvalidateLargePageWorker(PVMCPUCC pVCpu, IEMTLB *pTlb, RTGCPTR GCPtrTag,
    1099                                                  RTGCPTR GCPtrInstrBufPcTag) RT_NOEXCEPT
    1100 {
    1101     AssertCompile(IEMTLB_CALC_TAG_NO_REV((RTGCPTR)0x8731U << GUEST_PAGE_SHIFT) == 0x8731U);
    1102 
    1103     GCPtrTag &= ~(RTGCPTR)(RT_BIT_64((a_f2MbLargePage ? 21 : 22) - GUEST_PAGE_SHIFT) - 1U);
    1104     if (   GCPtrTag >= pTlb->GlobalLargePageRange.uFirstTag
    1105         && GCPtrTag <= pTlb->GlobalLargePageRange.uLastTag)
    1106     {
    1107         if (   GCPtrTag < pTlb->NonGlobalLargePageRange.uFirstTag
    1108             || GCPtrTag > pTlb->NonGlobalLargePageRange.uLastTag)
    1109             iemTlbInvalidateLargePageWorkerInner<a_fDataTlb, a_f2MbLargePage, true, false>(pVCpu, pTlb, GCPtrTag, GCPtrInstrBufPcTag);
    1110         else
    1111             iemTlbInvalidateLargePageWorkerInner<a_fDataTlb, a_f2MbLargePage, true, true>(pVCpu, pTlb, GCPtrTag, GCPtrInstrBufPcTag);
    1112     }
    1113     else if (   GCPtrTag < pTlb->NonGlobalLargePageRange.uFirstTag
    1114              || GCPtrTag > pTlb->NonGlobalLargePageRange.uLastTag)
    1115     {
    1116         /* Large pages aren't as likely in the non-global TLB half. */
    1117         IEMTLBTRACE_LARGE_SCAN(pVCpu, false, false, a_fDataTlb);
    1118     }
    1119     else
    1120         iemTlbInvalidateLargePageWorkerInner<a_fDataTlb, a_f2MbLargePage, false, true>(pVCpu, pTlb, GCPtrTag, GCPtrInstrBufPcTag);
    1121 }
    1122 
    1123 template<bool const a_fDataTlb>
    1124 DECLINLINE(void) iemTlbInvalidatePageWorker(PVMCPUCC pVCpu, IEMTLB *pTlb, RTGCPTR GCPtrTag, uintptr_t idxEven) RT_NOEXCEPT
    1125 {
    1126     pTlb->cTlbInvlPg += 1;
    1127 
    1128     /*
    1129      * Flush the entry pair.
    1130      */
    1131     if (pTlb->aEntries[idxEven].uTag == (GCPtrTag | pTlb->uTlbRevision))
    1132     {
    1133         IEMTLBTRACE_EVICT_SLOT(pVCpu, GCPtrTag, pTlb->aEntries[idxEven].GCPhys, idxEven, a_fDataTlb);
    1134         pTlb->aEntries[idxEven].uTag = 0;
    1135         if (!a_fDataTlb && GCPtrTag == IEMTLB_CALC_TAG_NO_REV(pVCpu->iem.s.uInstrBufPc))
    1136             pVCpu->iem.s.cbInstrBufTotal = 0;
    1137     }
    1138     if (pTlb->aEntries[idxEven + 1].uTag == (GCPtrTag | pTlb->uTlbRevisionGlobal))
    1139     {
    1140         IEMTLBTRACE_EVICT_SLOT(pVCpu, GCPtrTag, pTlb->aEntries[idxEven + 1].GCPhys, idxEven + 1, a_fDataTlb);
    1141         pTlb->aEntries[idxEven + 1].uTag = 0;
    1142         if (!a_fDataTlb && GCPtrTag == IEMTLB_CALC_TAG_NO_REV(pVCpu->iem.s.uInstrBufPc))
    1143             pVCpu->iem.s.cbInstrBufTotal = 0;
    1144     }
    1145 
    1146     /*
    1147      * If there are (or has been) large pages in the TLB, we must check if the
    1148      * address being flushed may involve one of those, as then we'd have to
    1149      * scan for entries relating to the same page and flush those as well.
    1150      */
    1151 # if 0 /** @todo do accurate counts or currently loaded large stuff and we can use those  */
    1152     if (pTlb->cTlbGlobalLargePageCurLoads || pTlb->cTlbNonGlobalLargePageCurLoads)
    1153 # else
    1154     if (pTlb->GlobalLargePageRange.uLastTag || pTlb->NonGlobalLargePageRange.uLastTag)
    1155 # endif
    1156     {
    1157         RTGCPTR const GCPtrInstrBufPcTag = a_fDataTlb ? 0 : IEMTLB_CALC_TAG_NO_REV(pVCpu->iem.s.uInstrBufPc);
    1158         if (pVCpu->cpum.GstCtx.cr4 & X86_CR4_PAE)
    1159             iemTlbInvalidateLargePageWorker<a_fDataTlb, true>(pVCpu, pTlb, GCPtrTag, GCPtrInstrBufPcTag);
    1160         else
    1161             iemTlbInvalidateLargePageWorker<a_fDataTlb, false>(pVCpu, pTlb, GCPtrTag, GCPtrInstrBufPcTag);
    1162     }
    1163 }
    1164 
    1165 #endif /* defined(IEM_WITH_CODE_TLB) || defined(IEM_WITH_DATA_TLB) */
    1166 
    1167 /**
    1168  * Invalidates a page in the TLBs.
    1169  *
    1170  * @param   pVCpu       The cross context virtual CPU structure of the calling
    1171  *                      thread.
    1172  * @param   GCPtr       The address of the page to invalidate
    1173  * @thread EMT(pVCpu)
    1174  */
    1175 VMM_INT_DECL(void) IEMTlbInvalidatePage(PVMCPUCC pVCpu, RTGCPTR GCPtr)
    1176 {
    1177     IEMTLBTRACE_INVLPG(pVCpu, GCPtr);
    1178 #if defined(IEM_WITH_CODE_TLB) || defined(IEM_WITH_DATA_TLB)
    1179     Log10(("IEMTlbInvalidatePage: GCPtr=%RGv\n", GCPtr));
    1180     GCPtr = IEMTLB_CALC_TAG_NO_REV(GCPtr);
    1181     Assert(!(GCPtr >> (48 - X86_PAGE_SHIFT)));
    1182     uintptr_t const idxEven = IEMTLB_TAG_TO_EVEN_INDEX(GCPtr);
    1183 
    1184 # ifdef IEM_WITH_CODE_TLB
    1185     iemTlbInvalidatePageWorker<false>(pVCpu, &pVCpu->iem.s.CodeTlb, GCPtr, idxEven);
    1186 # endif
    1187 # ifdef IEM_WITH_DATA_TLB
    1188     iemTlbInvalidatePageWorker<true>(pVCpu, &pVCpu->iem.s.DataTlb, GCPtr, idxEven);
    1189 # endif
    1190 #else
    1191     NOREF(pVCpu); NOREF(GCPtr);
    1192 #endif
    1193 }
    1194 
    1195 
    1196 #if defined(IEM_WITH_CODE_TLB) || defined(IEM_WITH_DATA_TLB)
    1197 /**
    1198  * Invalid both TLBs slow fashion following a rollover.
    1199  *
    1200  * Worker for IEMTlbInvalidateAllPhysical,
    1201  * IEMTlbInvalidateAllPhysicalAllCpus, iemOpcodeFetchBytesJmp, iemMemMap,
    1202  * iemMemMapJmp and others.
    1203  *
    1204  * @thread EMT(pVCpu)
    1205  */
    1206 static void IEMTlbInvalidateAllPhysicalSlow(PVMCPUCC pVCpu)
    1207 {
    1208     Log10(("IEMTlbInvalidateAllPhysicalSlow\n"));
    1209     ASMAtomicWriteU64(&pVCpu->iem.s.CodeTlb.uTlbPhysRev, IEMTLB_PHYS_REV_INCR * 2);
    1210     ASMAtomicWriteU64(&pVCpu->iem.s.DataTlb.uTlbPhysRev, IEMTLB_PHYS_REV_INCR * 2);
    1211 
    1212     unsigned i;
    1213 # ifdef IEM_WITH_CODE_TLB
    1214     i = RT_ELEMENTS(pVCpu->iem.s.CodeTlb.aEntries);
    1215     while (i-- > 0)
    1216     {
    1217         pVCpu->iem.s.CodeTlb.aEntries[i].pbMappingR3       = NULL;
    1218         pVCpu->iem.s.CodeTlb.aEntries[i].fFlagsAndPhysRev &= ~(  IEMTLBE_F_PG_NO_WRITE   | IEMTLBE_F_PG_NO_READ
    1219                                                                | IEMTLBE_F_PG_UNASSIGNED | IEMTLBE_F_PHYS_REV);
    1220     }
    1221     pVCpu->iem.s.CodeTlb.cTlbPhysRevRollovers++;
    1222     pVCpu->iem.s.CodeTlb.cTlbPhysRevFlushes++;
    1223 # endif
    1224 # ifdef IEM_WITH_DATA_TLB
    1225     i = RT_ELEMENTS(pVCpu->iem.s.DataTlb.aEntries);
    1226     while (i-- > 0)
    1227     {
    1228         pVCpu->iem.s.DataTlb.aEntries[i].pbMappingR3       = NULL;
    1229         pVCpu->iem.s.DataTlb.aEntries[i].fFlagsAndPhysRev &= ~(  IEMTLBE_F_PG_NO_WRITE   | IEMTLBE_F_PG_NO_READ
    1230                                                                | IEMTLBE_F_PG_UNASSIGNED | IEMTLBE_F_PHYS_REV);
    1231     }
    1232     pVCpu->iem.s.DataTlb.cTlbPhysRevRollovers++;
    1233     pVCpu->iem.s.DataTlb.cTlbPhysRevFlushes++;
    1234 # endif
    1235 
    1236 }
    1237 #endif
    1238 
    1239 
    1240 /**
    1241  * Invalidates the host physical aspects of the IEM TLBs.
    1242  *
    1243  * This is called internally as well as by PGM when moving GC mappings.
    1244  *
    1245  * @param   pVCpu       The cross context virtual CPU structure of the calling
    1246  *                      thread.
    1247  * @note    Currently not used.
    1248  */
    1249 VMM_INT_DECL(void) IEMTlbInvalidateAllPhysical(PVMCPUCC pVCpu)
    1250 {
    1251 #if defined(IEM_WITH_CODE_TLB) || defined(IEM_WITH_DATA_TLB)
    1252     /* Note! This probably won't end up looking exactly like this, but it give an idea... */
    1253     Log10(("IEMTlbInvalidateAllPhysical\n"));
    1254 
    1255 # ifdef IEM_WITH_CODE_TLB
    1256     pVCpu->iem.s.cbInstrBufTotal = 0;
    1257 # endif
    1258     uint64_t uTlbPhysRev = pVCpu->iem.s.CodeTlb.uTlbPhysRev + IEMTLB_PHYS_REV_INCR;
    1259     if (RT_LIKELY(uTlbPhysRev > IEMTLB_PHYS_REV_INCR * 2))
    1260     {
    1261         pVCpu->iem.s.CodeTlb.uTlbPhysRev = uTlbPhysRev;
    1262         pVCpu->iem.s.CodeTlb.cTlbPhysRevFlushes++;
    1263         pVCpu->iem.s.DataTlb.uTlbPhysRev = uTlbPhysRev;
    1264         pVCpu->iem.s.DataTlb.cTlbPhysRevFlushes++;
    1265     }
    1266     else
    1267         IEMTlbInvalidateAllPhysicalSlow(pVCpu);
    1268 #else
    1269     NOREF(pVCpu);
    1270 #endif
    1271 }
    1272 
    1273 
    1274 /**
    1275  * Invalidates the host physical aspects of the IEM TLBs.
    1276  *
    1277  * This is called internally as well as by PGM when moving GC mappings.
    1278  *
    1279  * @param   pVM         The cross context VM structure.
    1280  * @param   idCpuCaller The ID of the calling EMT if available to the caller,
    1281  *                      otherwise NIL_VMCPUID.
    1282  * @param   enmReason   The reason we're called.
    1283  *
    1284  * @remarks Caller holds the PGM lock.
    1285  */
    1286 VMM_INT_DECL(void) IEMTlbInvalidateAllPhysicalAllCpus(PVMCC pVM, VMCPUID idCpuCaller, IEMTLBPHYSFLUSHREASON enmReason)
    1287 {
    1288 #if defined(IEM_WITH_CODE_TLB) || defined(IEM_WITH_DATA_TLB)
    1289     PVMCPUCC const pVCpuCaller = idCpuCaller >= pVM->cCpus ? VMMGetCpu(pVM) : VMMGetCpuById(pVM, idCpuCaller);
    1290     if (pVCpuCaller)
    1291         VMCPU_ASSERT_EMT(pVCpuCaller);
    1292     Log10(("IEMTlbInvalidateAllPhysicalAllCpus: %d\n", enmReason)); RT_NOREF(enmReason);
    1293 
    1294     VMCC_FOR_EACH_VMCPU(pVM)
    1295     {
    1296 # ifdef IEM_WITH_CODE_TLB
    1297         if (pVCpuCaller == pVCpu)
    1298             pVCpu->iem.s.cbInstrBufTotal = 0;
    1299 # endif
    1300 
    1301         uint64_t const uTlbPhysRevPrev = ASMAtomicUoReadU64(&pVCpu->iem.s.CodeTlb.uTlbPhysRev);
    1302         uint64_t       uTlbPhysRevNew  = uTlbPhysRevPrev + IEMTLB_PHYS_REV_INCR;
    1303         if (RT_LIKELY(uTlbPhysRevNew > IEMTLB_PHYS_REV_INCR * 2))
    1304         { /* likely */}
    1305         else if (pVCpuCaller != pVCpu)
    1306             uTlbPhysRevNew = IEMTLB_PHYS_REV_INCR;
    1307         else
    1308         {
    1309             IEMTlbInvalidateAllPhysicalSlow(pVCpu);
    1310             continue;
    1311         }
    1312         if (ASMAtomicCmpXchgU64(&pVCpu->iem.s.CodeTlb.uTlbPhysRev, uTlbPhysRevNew, uTlbPhysRevPrev))
    1313             pVCpu->iem.s.CodeTlb.cTlbPhysRevFlushes++;
    1314 
    1315         if (ASMAtomicCmpXchgU64(&pVCpu->iem.s.DataTlb.uTlbPhysRev, uTlbPhysRevNew, uTlbPhysRevPrev))
    1316             pVCpu->iem.s.DataTlb.cTlbPhysRevFlushes++;
    1317     }
    1318     VMCC_FOR_EACH_VMCPU_END(pVM);
    1319 
    1320 #else
    1321     RT_NOREF(pVM, idCpuCaller, enmReason);
    1322 #endif
    1323 }
    1324 
    1325 
    1326 /**
    1327  * Flushes the prefetch buffer, light version.
    1328  */
    1329 void iemOpcodeFlushLight(PVMCPUCC pVCpu, uint8_t cbInstr)
    1330 {
    1331 #ifndef IEM_WITH_CODE_TLB
    1332     pVCpu->iem.s.cbOpcode = cbInstr;
    1333 #else
    1334     RT_NOREF(pVCpu, cbInstr);
    1335 #endif
    1336 }
    1337 
    1338 
    1339 /**
    1340  * Flushes the prefetch buffer, heavy version.
    1341  */
    1342 void iemOpcodeFlushHeavy(PVMCPUCC pVCpu, uint8_t cbInstr)
    1343 {
    1344 #ifndef IEM_WITH_CODE_TLB
    1345     pVCpu->iem.s.cbOpcode = cbInstr; /* Note! SVM and VT-x may set this to zero on exit, rather than the instruction length. */
    1346 #elif 1
    1347     pVCpu->iem.s.cbInstrBufTotal = 0;
    1348     RT_NOREF(cbInstr);
    1349 #else
    1350     RT_NOREF(pVCpu, cbInstr);
    1351 #endif
    1352 }
    1353 
    1354 
    1355 
    1356 #ifdef IEM_WITH_CODE_TLB
    1357 
    1358 /**
    1359  * Tries to fetches @a cbDst opcode bytes, raise the appropriate exception on
    1360  * failure and jumps.
    1361  *
    1362  * We end up here for a number of reasons:
    1363  *      - pbInstrBuf isn't yet initialized.
    1364  *      - Advancing beyond the buffer boundrary (e.g. cross page).
    1365  *      - Advancing beyond the CS segment limit.
    1366  *      - Fetching from non-mappable page (e.g. MMIO).
    1367  *      - TLB loading in the recompiler (@a pvDst = NULL, @a cbDst = 0).
    1368  *
    1369  * @param   pVCpu               The cross context virtual CPU structure of the
    1370  *                              calling thread.
    1371  * @param   pvDst               Where to return the bytes.
    1372  * @param   cbDst               Number of bytes to read.  A value of zero is
    1373  *                              allowed for initializing pbInstrBuf (the
    1374  *                              recompiler does this).  In this case it is best
    1375  *                              to set pbInstrBuf to NULL prior to the call.
    1376  */
    1377 void iemOpcodeFetchBytesJmp(PVMCPUCC pVCpu, size_t cbDst, void *pvDst) IEM_NOEXCEPT_MAY_LONGJMP
    1378 {
    1379 # ifdef IN_RING3
    1380     for (;;)
    1381     {
    1382         Assert(cbDst <= 8);
    1383         uint32_t offBuf = pVCpu->iem.s.offInstrNextByte;
    1384 
    1385         /*
    1386          * We might have a partial buffer match, deal with that first to make the
    1387          * rest simpler.  This is the first part of the cross page/buffer case.
    1388          */
    1389         uint8_t const * const pbInstrBuf = pVCpu->iem.s.pbInstrBuf;
    1390         if (pbInstrBuf != NULL)
    1391         {
    1392             Assert(cbDst != 0); /* pbInstrBuf shall be NULL in case of a TLB load */
    1393             uint32_t const cbInstrBuf = pVCpu->iem.s.cbInstrBuf;
    1394             if (offBuf < cbInstrBuf)
    1395             {
    1396                 Assert(offBuf + cbDst > cbInstrBuf);
    1397                 uint32_t const cbCopy = cbInstrBuf - offBuf;
    1398                 memcpy(pvDst, &pbInstrBuf[offBuf], cbCopy);
    1399 
    1400                 cbDst  -= cbCopy;
    1401                 pvDst   = (uint8_t *)pvDst + cbCopy;
    1402                 offBuf += cbCopy;
    1403             }
    1404         }
    1405 
    1406         /*
    1407          * Check segment limit, figuring how much we're allowed to access at this point.
    1408          *
    1409          * We will fault immediately if RIP is past the segment limit / in non-canonical
    1410          * territory.  If we do continue, there are one or more bytes to read before we
    1411          * end up in trouble and we need to do that first before faulting.
    1412          */
    1413         RTGCPTR  GCPtrFirst;
    1414         uint32_t cbMaxRead;
    1415         if (IEM_IS_64BIT_CODE(pVCpu))
    1416         {
    1417             GCPtrFirst = pVCpu->cpum.GstCtx.rip + (offBuf - (uint32_t)(int32_t)pVCpu->iem.s.offCurInstrStart);
    1418             if (RT_LIKELY(IEM_IS_CANONICAL(GCPtrFirst)))
    1419             { /* likely */ }
    1420             else
    1421                 iemRaiseGeneralProtectionFault0Jmp(pVCpu);
    1422             cbMaxRead = X86_PAGE_SIZE - ((uint32_t)GCPtrFirst & X86_PAGE_OFFSET_MASK);
    1423         }
    1424         else
    1425         {
    1426             GCPtrFirst = pVCpu->cpum.GstCtx.eip + (offBuf - (uint32_t)(int32_t)pVCpu->iem.s.offCurInstrStart);
    1427             /* Assert(!(GCPtrFirst & ~(uint32_t)UINT16_MAX) || IEM_IS_32BIT_CODE(pVCpu)); - this is allowed */
    1428             if (RT_LIKELY((uint32_t)GCPtrFirst <= pVCpu->cpum.GstCtx.cs.u32Limit))
    1429             { /* likely */ }
    1430             else /** @todo For CPUs older than the 386, we should not necessarily generate \#GP here but wrap around! */
    1431                 iemRaiseSelectorBoundsJmp(pVCpu, X86_SREG_CS, IEM_ACCESS_INSTRUCTION);
    1432             cbMaxRead = pVCpu->cpum.GstCtx.cs.u32Limit - (uint32_t)GCPtrFirst + 1;
    1433             if (cbMaxRead != 0)
    1434             { /* likely */ }
    1435             else
    1436             {
    1437                 /* Overflowed because address is 0 and limit is max. */
    1438                 Assert(GCPtrFirst == 0); Assert(pVCpu->cpum.GstCtx.cs.u32Limit == UINT32_MAX);
    1439                 cbMaxRead = X86_PAGE_SIZE;
    1440             }
    1441             GCPtrFirst = (uint32_t)GCPtrFirst + (uint32_t)pVCpu->cpum.GstCtx.cs.u64Base;
    1442             uint32_t cbMaxRead2 = X86_PAGE_SIZE - ((uint32_t)GCPtrFirst & X86_PAGE_OFFSET_MASK);
    1443             if (cbMaxRead2 < cbMaxRead)
    1444                 cbMaxRead = cbMaxRead2;
    1445             /** @todo testcase: unreal modes, both huge 16-bit and 32-bit. */
    1446         }
    1447 
    1448         /*
    1449          * Get the TLB entry for this piece of code.
    1450          */
    1451         uint64_t const uTagNoRev = IEMTLB_CALC_TAG_NO_REV(GCPtrFirst);
    1452         PIEMTLBENTRY   pTlbe     = IEMTLB_TAG_TO_EVEN_ENTRY(&pVCpu->iem.s.CodeTlb, uTagNoRev);
    1453         if (   pTlbe->uTag               == (uTagNoRev | pVCpu->iem.s.CodeTlb.uTlbRevision)
    1454             || (pTlbe = pTlbe + 1)->uTag == (uTagNoRev | pVCpu->iem.s.CodeTlb.uTlbRevisionGlobal))
    1455         {
    1456             /* likely when executing lots of code, otherwise unlikely */
    1457 #  ifdef IEM_WITH_TLB_STATISTICS
    1458             pVCpu->iem.s.CodeTlb.cTlbCoreHits++;
    1459 #  endif
    1460             Assert(!(pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PT_NO_ACCESSED));
    1461 
    1462             /* Check TLB page table level access flags. */
    1463             if (pTlbe->fFlagsAndPhysRev & (IEMTLBE_F_PT_NO_USER | IEMTLBE_F_PT_NO_EXEC))
    1464             {
    1465                 if ((pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PT_NO_USER) && IEM_GET_CPL(pVCpu) == 3)
    1466                 {
    1467                     Log(("iemOpcodeFetchBytesJmp: %RGv - supervisor page\n", GCPtrFirst));
    1468                     iemRaisePageFaultJmp(pVCpu, GCPtrFirst, 1, IEM_ACCESS_INSTRUCTION, VERR_ACCESS_DENIED);
    1469                 }
    1470                 if ((pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PT_NO_EXEC) && (pVCpu->cpum.GstCtx.msrEFER & MSR_K6_EFER_NXE))
    1471                 {
    1472                     Log(("iemOpcodeFetchMoreBytes: %RGv - NX\n", GCPtrFirst));
    1473                     iemRaisePageFaultJmp(pVCpu, GCPtrFirst, 1, IEM_ACCESS_INSTRUCTION, VERR_ACCESS_DENIED);
    1474                 }
    1475             }
    1476 
    1477             /* Look up the physical page info if necessary. */
    1478             if ((pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PHYS_REV) == pVCpu->iem.s.CodeTlb.uTlbPhysRev)
    1479             { /* not necessary */ }
    1480             else
    1481             {
    1482                 if (RT_LIKELY(pVCpu->iem.s.CodeTlb.uTlbPhysRev > IEMTLB_PHYS_REV_INCR))
    1483                 { /* likely */ }
    1484                 else
    1485                     IEMTlbInvalidateAllPhysicalSlow(pVCpu);
    1486                 pTlbe->fFlagsAndPhysRev &= ~IEMTLBE_GCPHYS2PTR_MASK;
    1487                 int rc = PGMPhysIemGCPhys2PtrNoLock(pVCpu->CTX_SUFF(pVM), pVCpu, pTlbe->GCPhys, &pVCpu->iem.s.CodeTlb.uTlbPhysRev,
    1488                                                     &pTlbe->pbMappingR3, &pTlbe->fFlagsAndPhysRev);
    1489                 AssertRCStmt(rc, IEM_DO_LONGJMP(pVCpu, rc));
    1490             }
    1491         }
    1492         else
    1493         {
    1494             pVCpu->iem.s.CodeTlb.cTlbCoreMisses++;
    1495 
    1496             /* This page table walking will set A bits as required by the access while performing the walk.
    1497                ASSUMES these are set when the address is translated rather than on commit... */
    1498             /** @todo testcase: check when A bits are actually set by the CPU for code.  */
    1499             PGMPTWALKFAST WalkFast;
    1500             int rc = PGMGstQueryPageFast(pVCpu, GCPtrFirst,
    1501                                          IEM_GET_CPL(pVCpu) == 3 ? PGMQPAGE_F_EXECUTE | PGMQPAGE_F_USER_MODE : PGMQPAGE_F_EXECUTE,
    1502                                          &WalkFast);
    1503             if (RT_SUCCESS(rc))
    1504                 Assert((WalkFast.fInfo & PGM_WALKINFO_SUCCEEDED) && WalkFast.fFailed == PGM_WALKFAIL_SUCCESS);
    1505             else
    1506             {
    1507 #  ifdef VBOX_WITH_NESTED_HWVIRT_VMX_EPT
    1508                 /** @todo Nested VMX: Need to handle EPT violation/misconfig here?  OF COURSE! */
    1509                 Assert(!(Walk.fFailed & PGM_WALKFAIL_EPT));
    1510 #  endif
    1511                 Log(("iemOpcodeFetchMoreBytes: %RGv - rc=%Rrc\n", GCPtrFirst, rc));
    1512                 iemRaisePageFaultJmp(pVCpu, GCPtrFirst, 1, IEM_ACCESS_INSTRUCTION, rc);
    1513             }
    1514 
    1515             AssertCompile(IEMTLBE_F_PT_NO_EXEC == 1);
    1516             if (   !(WalkFast.fEffective & PGM_PTATTRS_G_MASK)
    1517                 || IEM_GET_CPL(pVCpu) != 0) /* optimization: Only use the PTE.G=1 entries in ring-0. */
    1518             {
    1519                 pTlbe--;
    1520                 pTlbe->uTag         = uTagNoRev | pVCpu->iem.s.CodeTlb.uTlbRevision;
    1521                 if (WalkFast.fInfo & PGM_WALKINFO_BIG_PAGE)
    1522                     iemTlbLoadedLargePage<false>(pVCpu, &pVCpu->iem.s.CodeTlb, uTagNoRev, RT_BOOL(pVCpu->cpum.GstCtx.cr4 & X86_CR4_PAE));
    1523 #  ifdef IEMTLB_WITH_LARGE_PAGE_BITMAP
    1524                 else
    1525                     ASMBitClear(pVCpu->iem.s.CodeTlb.bmLargePage, IEMTLB_TAG_TO_EVEN_INDEX(uTagNoRev));
    1526 #  endif
    1527             }
    1528             else
    1529             {
    1530                 pVCpu->iem.s.CodeTlb.cTlbCoreGlobalLoads++;
    1531                 pTlbe->uTag         = uTagNoRev | pVCpu->iem.s.CodeTlb.uTlbRevisionGlobal;
    1532                 if (WalkFast.fInfo & PGM_WALKINFO_BIG_PAGE)
    1533                     iemTlbLoadedLargePage<true>(pVCpu, &pVCpu->iem.s.CodeTlb, uTagNoRev, RT_BOOL(pVCpu->cpum.GstCtx.cr4 & X86_CR4_PAE));
    1534 #  ifdef IEMTLB_WITH_LARGE_PAGE_BITMAP
    1535                 else
    1536                     ASMBitClear(pVCpu->iem.s.CodeTlb.bmLargePage, IEMTLB_TAG_TO_EVEN_INDEX(uTagNoRev) + 1);
    1537 #  endif
    1538             }
    1539             pTlbe->fFlagsAndPhysRev = (~WalkFast.fEffective & (X86_PTE_US | X86_PTE_RW | X86_PTE_D | X86_PTE_A))
    1540                                     | (WalkFast.fEffective >> X86_PTE_PAE_BIT_NX) /*IEMTLBE_F_PT_NO_EXEC*/
    1541                                     | (WalkFast.fInfo & PGM_WALKINFO_BIG_PAGE);
    1542             RTGCPHYS const GCPhysPg = WalkFast.GCPhys & ~(RTGCPHYS)GUEST_PAGE_OFFSET_MASK;
    1543             pTlbe->GCPhys           = GCPhysPg;
    1544             pTlbe->pbMappingR3      = NULL;
    1545             Assert(!(pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PT_NO_EXEC) || !(pVCpu->cpum.GstCtx.msrEFER & MSR_K6_EFER_NXE));
    1546             Assert(!(pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PT_NO_USER) || IEM_GET_CPL(pVCpu) != 3);
    1547             Assert(!(pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PT_NO_ACCESSED));
    1548 
    1549             if (!((uintptr_t)pTlbe & (sizeof(*pTlbe) * 2 - 1)))
    1550                 IEMTLBTRACE_LOAD(       pVCpu, GCPtrFirst, pTlbe->GCPhys, (uint32_t)pTlbe->fFlagsAndPhysRev, false);
    1551             else
    1552                 IEMTLBTRACE_LOAD_GLOBAL(pVCpu, GCPtrFirst, pTlbe->GCPhys, (uint32_t)pTlbe->fFlagsAndPhysRev, false);
    1553 
    1554             /* Resolve the physical address. */
    1555             if (RT_LIKELY(pVCpu->iem.s.CodeTlb.uTlbPhysRev > IEMTLB_PHYS_REV_INCR))
    1556             { /* likely */ }
    1557             else
    1558                 IEMTlbInvalidateAllPhysicalSlow(pVCpu);
    1559             Assert(!(pTlbe->fFlagsAndPhysRev & IEMTLBE_GCPHYS2PTR_MASK));
    1560             rc = PGMPhysIemGCPhys2PtrNoLock(pVCpu->CTX_SUFF(pVM), pVCpu, GCPhysPg, &pVCpu->iem.s.CodeTlb.uTlbPhysRev,
    1561                                             &pTlbe->pbMappingR3, &pTlbe->fFlagsAndPhysRev);
    1562             AssertRCStmt(rc, IEM_DO_LONGJMP(pVCpu, rc));
    1563         }
    1564 
    1565 # if defined(IN_RING3) || defined(IN_RING0) /** @todo fixme */
    1566         /*
    1567          * Try do a direct read using the pbMappingR3 pointer.
    1568          * Note! Do not recheck the physical TLB revision number here as we have the
    1569          *       wrong response to changes in the else case.  If someone is updating
    1570          *       pVCpu->iem.s.CodeTlb.uTlbPhysRev in parallel to us, we should be fine
    1571          *       pretending we always won the race.
    1572          */
    1573         if (    (pTlbe->fFlagsAndPhysRev & (/*IEMTLBE_F_PHYS_REV |*/ IEMTLBE_F_NO_MAPPINGR3 | IEMTLBE_F_PG_NO_READ))
    1574              == /*pVCpu->iem.s.CodeTlb.uTlbPhysRev*/ 0U)
    1575         {
    1576             uint32_t const offPg = (GCPtrFirst & X86_PAGE_OFFSET_MASK);
    1577             pVCpu->iem.s.cbInstrBufTotal = offPg + cbMaxRead;
    1578             if (offBuf == (uint32_t)(int32_t)pVCpu->iem.s.offCurInstrStart)
    1579             {
    1580                 pVCpu->iem.s.cbInstrBuf       = offPg + RT_MIN(15, cbMaxRead);
    1581                 pVCpu->iem.s.offCurInstrStart = (int16_t)offPg;
    1582             }
    1583             else
    1584             {
    1585                 uint32_t const cbInstr = offBuf - (uint32_t)(int32_t)pVCpu->iem.s.offCurInstrStart;
    1586                 if (cbInstr + (uint32_t)cbDst <= 15)
    1587                 {
    1588                     pVCpu->iem.s.cbInstrBuf       = offPg + RT_MIN(cbMaxRead + cbInstr, 15) - cbInstr;
    1589                     pVCpu->iem.s.offCurInstrStart = (int16_t)(offPg - cbInstr);
    1590                 }
    1591                 else
    1592                 {
    1593                     Log(("iemOpcodeFetchMoreBytes: %04x:%08RX64 LB %#x + %#zx -> #GP(0)\n",
    1594                          pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, cbInstr, cbDst));
    1595                     iemRaiseGeneralProtectionFault0Jmp(pVCpu);
    1596                 }
    1597             }
    1598             if (cbDst <= cbMaxRead)
    1599             {
    1600                 pVCpu->iem.s.fTbCrossedPage     |= offPg == 0 || pVCpu->iem.s.fTbBranched != 0; /** @todo Spurious load effect on branch handling? */
    1601 #  if 0 /* unused */
    1602                 pVCpu->iem.s.GCPhysInstrBufPrev  = pVCpu->iem.s.GCPhysInstrBuf;
    1603 #  endif
    1604                 pVCpu->iem.s.offInstrNextByte = offPg + (uint32_t)cbDst;
    1605                 pVCpu->iem.s.uInstrBufPc      = GCPtrFirst & ~(RTGCPTR)X86_PAGE_OFFSET_MASK;
    1606                 pVCpu->iem.s.GCPhysInstrBuf   = pTlbe->GCPhys;
    1607                 pVCpu->iem.s.pbInstrBuf       = pTlbe->pbMappingR3;
    1608                 if (cbDst > 0) /* To make ASAN happy in the TLB load case. */
    1609                     memcpy(pvDst, &pTlbe->pbMappingR3[offPg], cbDst);
    1610                 else
    1611                     Assert(!pvDst);
    1612                 return;
    1613             }
    1614             pVCpu->iem.s.pbInstrBuf = NULL;
    1615 
    1616             memcpy(pvDst, &pTlbe->pbMappingR3[offPg], cbMaxRead);
    1617             pVCpu->iem.s.offInstrNextByte = offPg + cbMaxRead;
    1618         }
    1619 # else
    1620 #  error "refactor as needed"
    1621         /*
    1622          * If there is no special read handling, so we can read a bit more and
    1623          * put it in the prefetch buffer.
    1624          */
    1625         if (   cbDst < cbMaxRead
    1626             && (pTlbe->fFlagsAndPhysRev & (IEMTLBE_F_PHYS_REV | IEMTLBE_F_PG_NO_READ)) == pVCpu->iem.s.CodeTlb.uTlbPhysRev)
    1627         {
    1628             VBOXSTRICTRC rcStrict = PGMPhysRead(pVCpu->CTX_SUFF(pVM), pTlbe->GCPhys,
    1629                                                 &pVCpu->iem.s.abOpcode[0], cbToTryRead, PGMACCESSORIGIN_IEM);
    1630             if (RT_LIKELY(rcStrict == VINF_SUCCESS))
    1631             { /* likely */ }
    1632             else if (PGM_PHYS_RW_IS_SUCCESS(rcStrict))
    1633             {
    1634                 Log(("iemOpcodeFetchMoreBytes: %RGv/%RGp LB %#x - read status -  rcStrict=%Rrc\n",
    1635                      GCPtrNext, GCPhys, VBOXSTRICTRC_VAL(rcStrict), cbToTryRead));
    1636                 rcStrict = iemSetPassUpStatus(pVCpu, rcStrict);
    1637                 AssertStmt(rcStrict == VINF_SUCCESS, IEM_DO_LONGJMP(pVCpu, VBOXSTRICRC_VAL(rcStrict)));
    1638             }
    1639             else
    1640             {
    1641                 Log((RT_SUCCESS(rcStrict)
    1642                      ? "iemOpcodeFetchMoreBytes: %RGv/%RGp LB %#x - read status - rcStrict=%Rrc\n"
    1643                      : "iemOpcodeFetchMoreBytes: %RGv/%RGp LB %#x - read error - rcStrict=%Rrc (!!)\n",
    1644                      GCPtrNext, GCPhys, VBOXSTRICTRC_VAL(rcStrict), cbToTryRead));
    1645                 IEM_DO_LONGJMP(pVCpu, VBOXSTRICTRC_VAL(rcStrict));
    1646             }
    1647         }
    1648 # endif
    1649         /*
    1650          * Special read handling, so only read exactly what's needed.
    1651          * This is a highly unlikely scenario.
    1652          */
    1653         else
    1654         {
    1655             pVCpu->iem.s.CodeTlb.cTlbSlowCodeReadPath++;
    1656 
    1657             /* Check instruction length. */
    1658             uint32_t const cbInstr = offBuf - (uint32_t)(int32_t)pVCpu->iem.s.offCurInstrStart;
    1659             if (RT_LIKELY(cbInstr + cbDst <= 15))
    1660             { /* likely */ }
    1661             else
    1662             {
    1663                 Log(("iemOpcodeFetchMoreBytes: %04x:%08RX64 LB %#x + %#zx -> #GP(0) [slow]\n",
    1664                      pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, cbInstr, cbDst));
    1665                 iemRaiseGeneralProtectionFault0Jmp(pVCpu);
    1666             }
    1667 
    1668             /* Do the reading. */
    1669             uint32_t const cbToRead = RT_MIN((uint32_t)cbDst, cbMaxRead);
    1670             if (cbToRead > 0)
    1671             {
    1672                 VBOXSTRICTRC rcStrict = PGMPhysRead(pVCpu->CTX_SUFF(pVM), pTlbe->GCPhys + (GCPtrFirst & X86_PAGE_OFFSET_MASK),
    1673                                                     pvDst, cbToRead, PGMACCESSORIGIN_IEM);
    1674                 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
    1675                 { /* likely */ }
    1676                 else if (PGM_PHYS_RW_IS_SUCCESS(rcStrict))
    1677                 {
    1678                     Log(("iemOpcodeFetchMoreBytes: %RGv/%RGp LB %#x - read status -  rcStrict=%Rrc\n",
    1679                          GCPtrFirst, pTlbe->GCPhys + (GCPtrFirst & X86_PAGE_OFFSET_MASK), VBOXSTRICTRC_VAL(rcStrict), cbToRead));
    1680                     rcStrict = iemSetPassUpStatus(pVCpu, rcStrict);
    1681                     AssertStmt(rcStrict == VINF_SUCCESS, IEM_DO_LONGJMP(pVCpu, VBOXSTRICTRC_VAL(rcStrict)));
    1682                 }
    1683                 else
    1684                 {
    1685                     Log((RT_SUCCESS(rcStrict)
    1686                          ? "iemOpcodeFetchMoreBytes: %RGv/%RGp LB %#x - read status - rcStrict=%Rrc\n"
    1687                          : "iemOpcodeFetchMoreBytes: %RGv/%RGp LB %#x - read error - rcStrict=%Rrc (!!)\n",
    1688                          GCPtrFirst, pTlbe->GCPhys + (GCPtrFirst & X86_PAGE_OFFSET_MASK), VBOXSTRICTRC_VAL(rcStrict), cbToRead));
    1689                     IEM_DO_LONGJMP(pVCpu, VBOXSTRICTRC_VAL(rcStrict));
    1690                 }
    1691             }
    1692 
    1693             /* Update the state and probably return. */
    1694             uint32_t const offPg = (GCPtrFirst & X86_PAGE_OFFSET_MASK);
    1695             pVCpu->iem.s.fTbCrossedPage     |= offPg == 0 || pVCpu->iem.s.fTbBranched != 0;
    1696 #  if 0 /* unused */
    1697             pVCpu->iem.s.GCPhysInstrBufPrev  = pVCpu->iem.s.GCPhysInstrBuf;
    1698 #  endif
    1699             pVCpu->iem.s.offCurInstrStart = (int16_t)(offPg - cbInstr);
    1700             pVCpu->iem.s.offInstrNextByte = offPg + cbInstr + cbToRead;
    1701             pVCpu->iem.s.cbInstrBuf       = offPg + RT_MIN(15, cbMaxRead + cbInstr) - cbToRead - cbInstr;
    1702             pVCpu->iem.s.cbInstrBufTotal  = X86_PAGE_SIZE; /** @todo ??? */
    1703             pVCpu->iem.s.GCPhysInstrBuf   = pTlbe->GCPhys;
    1704             pVCpu->iem.s.uInstrBufPc      = GCPtrFirst & ~(RTGCPTR)X86_PAGE_OFFSET_MASK;
    1705             pVCpu->iem.s.pbInstrBuf       = NULL;
    1706             if (cbToRead == cbDst)
    1707                 return;
    1708             Assert(cbToRead == cbMaxRead);
    1709         }
    1710 
    1711         /*
    1712          * More to read, loop.
    1713          */
    1714         cbDst -= cbMaxRead;
    1715         pvDst  = (uint8_t *)pvDst + cbMaxRead;
    1716     }
    1717 # else  /* !IN_RING3 */
    1718     RT_NOREF(pvDst, cbDst);
    1719     if (pvDst || cbDst)
    1720         IEM_DO_LONGJMP(pVCpu, VERR_INTERNAL_ERROR);
    1721 # endif /* !IN_RING3 */
    1722 }
    1723 
    1724 #else /* !IEM_WITH_CODE_TLB */
    1725 
    1726 /**
    1727  * Try fetch at least @a cbMin bytes more opcodes, raise the appropriate
    1728  * exception if it fails.
    1729  *
    1730  * @returns Strict VBox status code.
    1731  * @param   pVCpu               The cross context virtual CPU structure of the
    1732  *                              calling thread.
    1733  * @param   cbMin               The minimum number of bytes relative offOpcode
    1734  *                              that must be read.
    1735  */
    1736 VBOXSTRICTRC iemOpcodeFetchMoreBytes(PVMCPUCC pVCpu, size_t cbMin) RT_NOEXCEPT
    1737 {
    1738     /*
    1739      * What we're doing here is very similar to iemMemMap/iemMemBounceBufferMap.
    1740      *
    1741      * First translate CS:rIP to a physical address.
    1742      */
    1743     uint8_t const   cbOpcode  = pVCpu->iem.s.cbOpcode;
    1744     uint8_t const   offOpcode = pVCpu->iem.s.offOpcode;
    1745     uint8_t const   cbLeft    = cbOpcode - offOpcode;
    1746     Assert(cbLeft < cbMin);
    1747     Assert(cbOpcode <= sizeof(pVCpu->iem.s.abOpcode));
    1748 
    1749     uint32_t        cbToTryRead;
    1750     RTGCPTR         GCPtrNext;
    1751     if (IEM_IS_64BIT_CODE(pVCpu))
    1752     {
    1753         GCPtrNext   = pVCpu->cpum.GstCtx.rip + cbOpcode;
    1754         if (!IEM_IS_CANONICAL(GCPtrNext))
    1755             return iemRaiseGeneralProtectionFault0(pVCpu);
    1756         cbToTryRead = GUEST_PAGE_SIZE - (GCPtrNext & GUEST_PAGE_OFFSET_MASK);
    1757     }
    1758     else
    1759     {
    1760         uint32_t GCPtrNext32 = pVCpu->cpum.GstCtx.eip;
    1761         /* Assert(!(GCPtrNext32 & ~(uint32_t)UINT16_MAX) || IEM_IS_32BIT_CODE(pVCpu)); - this is allowed */
    1762         GCPtrNext32 += cbOpcode;
    1763         if (GCPtrNext32 > pVCpu->cpum.GstCtx.cs.u32Limit)
    1764             /** @todo For CPUs older than the 386, we should not generate \#GP here but wrap around! */
    1765             return iemRaiseSelectorBounds(pVCpu, X86_SREG_CS, IEM_ACCESS_INSTRUCTION);
    1766         cbToTryRead = pVCpu->cpum.GstCtx.cs.u32Limit - GCPtrNext32 + 1;
    1767         if (!cbToTryRead) /* overflowed */
    1768         {
    1769             Assert(GCPtrNext32 == 0); Assert(pVCpu->cpum.GstCtx.cs.u32Limit == UINT32_MAX);
    1770             cbToTryRead = UINT32_MAX;
    1771             /** @todo check out wrapping around the code segment.  */
    1772         }
    1773         if (cbToTryRead < cbMin - cbLeft)
    1774             return iemRaiseSelectorBounds(pVCpu, X86_SREG_CS, IEM_ACCESS_INSTRUCTION);
    1775         GCPtrNext = (uint32_t)pVCpu->cpum.GstCtx.cs.u64Base + GCPtrNext32;
    1776 
    1777         uint32_t cbLeftOnPage = GUEST_PAGE_SIZE - (GCPtrNext & GUEST_PAGE_OFFSET_MASK);
    1778         if (cbToTryRead > cbLeftOnPage)
    1779             cbToTryRead = cbLeftOnPage;
    1780     }
    1781 
    1782     /* Restrict to opcode buffer space.
    1783 
    1784        We're making ASSUMPTIONS here based on work done previously in
    1785        iemInitDecoderAndPrefetchOpcodes, where bytes from the first page will
    1786        be fetched in case of an instruction crossing two pages. */
    1787     if (cbToTryRead > sizeof(pVCpu->iem.s.abOpcode) - cbOpcode)
    1788         cbToTryRead = sizeof(pVCpu->iem.s.abOpcode) - cbOpcode;
    1789     if (RT_LIKELY(cbToTryRead + cbLeft >= cbMin))
    1790     { /* likely */ }
    1791     else
    1792     {
    1793         Log(("iemOpcodeFetchMoreBytes: %04x:%08RX64 LB %#x + %#zx -> #GP(0)\n",
    1794              pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, offOpcode, cbMin));
    1795         return iemRaiseGeneralProtectionFault0(pVCpu);
    1796     }
    1797 
    1798     PGMPTWALKFAST WalkFast;
    1799     int rc = PGMGstQueryPageFast(pVCpu, GCPtrNext,
    1800                                  IEM_GET_CPL(pVCpu) == 3 ? PGMQPAGE_F_EXECUTE | PGMQPAGE_F_USER_MODE : PGMQPAGE_F_EXECUTE,
    1801                                  &WalkFast);
    1802     if (RT_SUCCESS(rc))
    1803         Assert((WalkFast.fInfo & PGM_WALKINFO_SUCCEEDED) && WalkFast.fFailed == PGM_WALKFAIL_SUCCESS);
    1804     else
    1805     {
    1806         Log(("iemOpcodeFetchMoreBytes: %RGv - rc=%Rrc\n", GCPtrNext, rc));
    1807 #ifdef VBOX_WITH_NESTED_HWVIRT_VMX_EPT
    1808         if (WalkFast.fFailed & PGM_WALKFAIL_EPT)
    1809             IEM_VMX_VMEXIT_EPT_RET(pVCpu, &WalkFast, IEM_ACCESS_INSTRUCTION, IEM_SLAT_FAIL_LINEAR_TO_PHYS_ADDR, 0 /* cbInstr */);
    1810 #endif
    1811         return iemRaisePageFault(pVCpu, GCPtrNext, 1, IEM_ACCESS_INSTRUCTION, rc);
    1812     }
    1813     Assert((WalkFast.fEffective & X86_PTE_US) || IEM_GET_CPL(pVCpu) != 3);
    1814     Assert(!(WalkFast.fEffective & X86_PTE_PAE_NX) || !(pVCpu->cpum.GstCtx.msrEFER & MSR_K6_EFER_NXE));
    1815 
    1816     RTGCPHYS const GCPhys = WalkFast.GCPhys;
    1817     Log5(("GCPtrNext=%RGv GCPhys=%RGp cbOpcodes=%#x\n",  GCPtrNext,  GCPhys, cbOpcode));
    1818 
    1819     /*
    1820      * Read the bytes at this address.
    1821      *
    1822      * We read all unpatched bytes in iemInitDecoderAndPrefetchOpcodes already,
    1823      * and since PATM should only patch the start of an instruction there
    1824      * should be no need to check again here.
    1825      */
    1826     if (!(pVCpu->iem.s.fExec & IEM_F_BYPASS_HANDLERS))
    1827     {
    1828         VBOXSTRICTRC rcStrict = PGMPhysRead(pVCpu->CTX_SUFF(pVM), GCPhys, &pVCpu->iem.s.abOpcode[cbOpcode],
    1829                                             cbToTryRead, PGMACCESSORIGIN_IEM);
    1830         if (RT_LIKELY(rcStrict == VINF_SUCCESS))
    1831         { /* likely */ }
    1832         else if (PGM_PHYS_RW_IS_SUCCESS(rcStrict))
    1833         {
    1834             Log(("iemOpcodeFetchMoreBytes: %RGv/%RGp LB %#x - read status -  rcStrict=%Rrc\n",
    1835                  GCPtrNext, GCPhys, VBOXSTRICTRC_VAL(rcStrict), cbToTryRead));
    1836             rcStrict = iemSetPassUpStatus(pVCpu, rcStrict);
    1837         }
    1838         else
    1839         {
    1840             Log((RT_SUCCESS(rcStrict)
    1841                  ? "iemOpcodeFetchMoreBytes: %RGv/%RGp LB %#x - read status - rcStrict=%Rrc\n"
    1842                  : "iemOpcodeFetchMoreBytes: %RGv/%RGp LB %#x - read error - rcStrict=%Rrc (!!)\n",
    1843                  GCPtrNext, GCPhys, VBOXSTRICTRC_VAL(rcStrict), cbToTryRead));
    1844             return rcStrict;
    1845         }
    1846     }
    1847     else
    1848     {
    1849         rc = PGMPhysSimpleReadGCPhys(pVCpu->CTX_SUFF(pVM), &pVCpu->iem.s.abOpcode[cbOpcode], GCPhys, cbToTryRead);
    1850         if (RT_SUCCESS(rc))
    1851         { /* likely */ }
    1852         else
    1853         {
    1854             Log(("iemOpcodeFetchMoreBytes: %RGv - read error - rc=%Rrc (!!)\n", GCPtrNext, rc));
    1855             return rc;
    1856         }
    1857     }
    1858     pVCpu->iem.s.cbOpcode = cbOpcode + cbToTryRead;
    1859     Log5(("%.*Rhxs\n", pVCpu->iem.s.cbOpcode, pVCpu->iem.s.abOpcode));
    1860 
    1861     return VINF_SUCCESS;
    1862 }
    1863 
    1864 #endif /* !IEM_WITH_CODE_TLB */
    1865 #ifndef IEM_WITH_SETJMP
    1866 
    1867 /**
    1868  * Deals with the problematic cases that iemOpcodeGetNextU8 doesn't like.
    1869  *
    1870  * @returns Strict VBox status code.
    1871  * @param   pVCpu               The cross context virtual CPU structure of the
    1872  *                              calling thread.
    1873  * @param   pb                  Where to return the opcode byte.
    1874  */
    1875 VBOXSTRICTRC iemOpcodeGetNextU8Slow(PVMCPUCC pVCpu, uint8_t *pb) RT_NOEXCEPT
    1876 {
    1877     VBOXSTRICTRC rcStrict = iemOpcodeFetchMoreBytes(pVCpu, 1);
    1878     if (rcStrict == VINF_SUCCESS)
    1879     {
    1880         uint8_t offOpcode = pVCpu->iem.s.offOpcode;
    1881         *pb = pVCpu->iem.s.abOpcode[offOpcode];
    1882         pVCpu->iem.s.offOpcode = offOpcode + 1;
    1883     }
    1884     else
    1885         *pb = 0;
    1886     return rcStrict;
    1887 }
    1888 
    1889 #else  /* IEM_WITH_SETJMP */
    1890 
    1891 /**
    1892  * Deals with the problematic cases that iemOpcodeGetNextU8Jmp doesn't like, longjmp on error.
    1893  *
    1894  * @returns The opcode byte.
    1895  * @param   pVCpu               The cross context virtual CPU structure of the calling thread.
    1896  */
    1897 uint8_t iemOpcodeGetNextU8SlowJmp(PVMCPUCC pVCpu) IEM_NOEXCEPT_MAY_LONGJMP
    1898 {
    1899 # ifdef IEM_WITH_CODE_TLB
    1900     uint8_t u8;
    1901     iemOpcodeFetchBytesJmp(pVCpu, sizeof(u8), &u8);
    1902     return u8;
    1903 # else
    1904     VBOXSTRICTRC rcStrict = iemOpcodeFetchMoreBytes(pVCpu, 1);
    1905     if (rcStrict == VINF_SUCCESS)
    1906         return pVCpu->iem.s.abOpcode[pVCpu->iem.s.offOpcode++];
    1907     IEM_DO_LONGJMP(pVCpu, VBOXSTRICTRC_VAL(rcStrict));
    1908 # endif
    1909 }
    1910 
    1911 #endif /* IEM_WITH_SETJMP */
    1912 
    1913 #ifndef IEM_WITH_SETJMP
    1914 
    1915 /**
    1916  * Deals with the problematic cases that iemOpcodeGetNextS8SxU16 doesn't like.
    1917  *
    1918  * @returns Strict VBox status code.
    1919  * @param   pVCpu               The cross context virtual CPU structure of the calling thread.
    1920  * @param   pu16                Where to return the opcode dword.
    1921  */
    1922 VBOXSTRICTRC iemOpcodeGetNextS8SxU16Slow(PVMCPUCC pVCpu, uint16_t *pu16) RT_NOEXCEPT
    1923 {
    1924     uint8_t      u8;
    1925     VBOXSTRICTRC rcStrict = iemOpcodeGetNextU8Slow(pVCpu, &u8);
    1926     if (rcStrict == VINF_SUCCESS)
    1927         *pu16 = (int8_t)u8;
    1928     return rcStrict;
    1929 }
    1930 
    1931 
    1932 /**
    1933  * Deals with the problematic cases that iemOpcodeGetNextS8SxU32 doesn't like.
    1934  *
    1935  * @returns Strict VBox status code.
    1936  * @param   pVCpu               The cross context virtual CPU structure of the calling thread.
    1937  * @param   pu32                Where to return the opcode dword.
    1938  */
    1939 VBOXSTRICTRC iemOpcodeGetNextS8SxU32Slow(PVMCPUCC pVCpu, uint32_t *pu32) RT_NOEXCEPT
    1940 {
    1941     uint8_t      u8;
    1942     VBOXSTRICTRC rcStrict = iemOpcodeGetNextU8Slow(pVCpu, &u8);
    1943     if (rcStrict == VINF_SUCCESS)
    1944         *pu32 = (int8_t)u8;
    1945     return rcStrict;
    1946 }
    1947 
    1948 
    1949 /**
    1950  * Deals with the problematic cases that iemOpcodeGetNextS8SxU64 doesn't like.
    1951  *
    1952  * @returns Strict VBox status code.
    1953  * @param   pVCpu               The cross context virtual CPU structure of the calling thread.
    1954  * @param   pu64                Where to return the opcode qword.
    1955  */
    1956 VBOXSTRICTRC iemOpcodeGetNextS8SxU64Slow(PVMCPUCC pVCpu, uint64_t *pu64) RT_NOEXCEPT
    1957 {
    1958     uint8_t      u8;
    1959     VBOXSTRICTRC rcStrict = iemOpcodeGetNextU8Slow(pVCpu, &u8);
    1960     if (rcStrict == VINF_SUCCESS)
    1961         *pu64 = (int8_t)u8;
    1962     return rcStrict;
    1963 }
    1964 
    1965 #endif /* !IEM_WITH_SETJMP */
    1966 
    1967 
    1968 #ifndef IEM_WITH_SETJMP
    1969 
    1970 /**
    1971  * Deals with the problematic cases that iemOpcodeGetNextU16 doesn't like.
    1972  *
    1973  * @returns Strict VBox status code.
    1974  * @param   pVCpu               The cross context virtual CPU structure of the calling thread.
    1975  * @param   pu16                Where to return the opcode word.
    1976  */
    1977 VBOXSTRICTRC iemOpcodeGetNextU16Slow(PVMCPUCC pVCpu, uint16_t *pu16) RT_NOEXCEPT
    1978 {
    1979     VBOXSTRICTRC rcStrict = iemOpcodeFetchMoreBytes(pVCpu, 2);
    1980     if (rcStrict == VINF_SUCCESS)
    1981     {
    1982         uint8_t offOpcode = pVCpu->iem.s.offOpcode;
    1983 # ifdef IEM_USE_UNALIGNED_DATA_ACCESS
    1984         *pu16 = *(uint16_t const *)&pVCpu->iem.s.abOpcode[offOpcode];
    1985 # else
    1986         *pu16 = RT_MAKE_U16(pVCpu->iem.s.abOpcode[offOpcode], pVCpu->iem.s.abOpcode[offOpcode + 1]);
    1987 # endif
    1988         pVCpu->iem.s.offOpcode = offOpcode + 2;
    1989     }
    1990     else
    1991         *pu16 = 0;
    1992     return rcStrict;
    1993 }
    1994 
    1995 #else  /* IEM_WITH_SETJMP */
    1996 
    1997 /**
    1998  * Deals with the problematic cases that iemOpcodeGetNextU16Jmp doesn't like, longjmp on error
    1999  *
    2000  * @returns The opcode word.
    2001  * @param   pVCpu               The cross context virtual CPU structure of the calling thread.
    2002  */
    2003 uint16_t iemOpcodeGetNextU16SlowJmp(PVMCPUCC pVCpu) IEM_NOEXCEPT_MAY_LONGJMP
    2004 {
    2005 # ifdef IEM_WITH_CODE_TLB
    2006     uint16_t u16;
    2007     iemOpcodeFetchBytesJmp(pVCpu, sizeof(u16), &u16);
    2008     return u16;
    2009 # else
    2010     VBOXSTRICTRC rcStrict = iemOpcodeFetchMoreBytes(pVCpu, 2);
    2011     if (rcStrict == VINF_SUCCESS)
    2012     {
    2013         uint8_t offOpcode = pVCpu->iem.s.offOpcode;
    2014         pVCpu->iem.s.offOpcode += 2;
    2015 #  ifdef IEM_USE_UNALIGNED_DATA_ACCESS
    2016         return *(uint16_t const *)&pVCpu->iem.s.abOpcode[offOpcode];
    2017 #  else
    2018         return RT_MAKE_U16(pVCpu->iem.s.abOpcode[offOpcode], pVCpu->iem.s.abOpcode[offOpcode + 1]);
    2019 #  endif
    2020     }
    2021     IEM_DO_LONGJMP(pVCpu, VBOXSTRICTRC_VAL(rcStrict));
    2022 # endif
    2023 }
    2024 
    2025 #endif /* IEM_WITH_SETJMP */
    2026 
    2027 #ifndef IEM_WITH_SETJMP
    2028 
    2029 /**
    2030  * Deals with the problematic cases that iemOpcodeGetNextU16ZxU32 doesn't like.
    2031  *
    2032  * @returns Strict VBox status code.
    2033  * @param   pVCpu               The cross context virtual CPU structure of the calling thread.
    2034  * @param   pu32                Where to return the opcode double word.
    2035  */
    2036 VBOXSTRICTRC iemOpcodeGetNextU16ZxU32Slow(PVMCPUCC pVCpu, uint32_t *pu32) RT_NOEXCEPT
    2037 {
    2038     VBOXSTRICTRC rcStrict = iemOpcodeFetchMoreBytes(pVCpu, 2);
    2039     if (rcStrict == VINF_SUCCESS)
    2040     {
    2041         uint8_t offOpcode = pVCpu->iem.s.offOpcode;
    2042         *pu32 = RT_MAKE_U16(pVCpu->iem.s.abOpcode[offOpcode], pVCpu->iem.s.abOpcode[offOpcode + 1]);
    2043         pVCpu->iem.s.offOpcode = offOpcode + 2;
    2044     }
    2045     else
    2046         *pu32 = 0;
    2047     return rcStrict;
    2048 }
    2049 
    2050 
    2051 /**
    2052  * Deals with the problematic cases that iemOpcodeGetNextU16ZxU64 doesn't like.
    2053  *
    2054  * @returns Strict VBox status code.
    2055  * @param   pVCpu               The cross context virtual CPU structure of the calling thread.
    2056  * @param   pu64                Where to return the opcode quad word.
    2057  */
    2058 VBOXSTRICTRC iemOpcodeGetNextU16ZxU64Slow(PVMCPUCC pVCpu, uint64_t *pu64) RT_NOEXCEPT
    2059 {
    2060     VBOXSTRICTRC rcStrict = iemOpcodeFetchMoreBytes(pVCpu, 2);
    2061     if (rcStrict == VINF_SUCCESS)
    2062     {
    2063         uint8_t offOpcode = pVCpu->iem.s.offOpcode;
    2064         *pu64 = RT_MAKE_U16(pVCpu->iem.s.abOpcode[offOpcode], pVCpu->iem.s.abOpcode[offOpcode + 1]);
    2065         pVCpu->iem.s.offOpcode = offOpcode + 2;
    2066     }
    2067     else
    2068         *pu64 = 0;
    2069     return rcStrict;
    2070 }
    2071 
    2072 #endif /* !IEM_WITH_SETJMP */
    2073 
    2074 #ifndef IEM_WITH_SETJMP
    2075 
    2076 /**
    2077  * Deals with the problematic cases that iemOpcodeGetNextU32 doesn't like.
    2078  *
    2079  * @returns Strict VBox status code.
    2080  * @param   pVCpu               The cross context virtual CPU structure of the calling thread.
    2081  * @param   pu32                Where to return the opcode dword.
    2082  */
    2083 VBOXSTRICTRC iemOpcodeGetNextU32Slow(PVMCPUCC pVCpu, uint32_t *pu32) RT_NOEXCEPT
    2084 {
    2085     VBOXSTRICTRC rcStrict = iemOpcodeFetchMoreBytes(pVCpu, 4);
    2086     if (rcStrict == VINF_SUCCESS)
    2087     {
    2088         uint8_t offOpcode = pVCpu->iem.s.offOpcode;
    2089 # ifdef IEM_USE_UNALIGNED_DATA_ACCESS
    2090         *pu32 = *(uint32_t const *)&pVCpu->iem.s.abOpcode[offOpcode];
    2091 # else
    2092         *pu32 = RT_MAKE_U32_FROM_U8(pVCpu->iem.s.abOpcode[offOpcode],
    2093                                     pVCpu->iem.s.abOpcode[offOpcode + 1],
    2094                                     pVCpu->iem.s.abOpcode[offOpcode + 2],
    2095                                     pVCpu->iem.s.abOpcode[offOpcode + 3]);
    2096 # endif
    2097         pVCpu->iem.s.offOpcode = offOpcode + 4;
    2098     }
    2099     else
    2100         *pu32 = 0;
    2101     return rcStrict;
    2102 }
    2103 
    2104 #else  /* IEM_WITH_SETJMP */
    2105 
    2106 /**
    2107  * Deals with the problematic cases that iemOpcodeGetNextU32Jmp doesn't like, longjmp on error.
    2108  *
    2109  * @returns The opcode dword.
    2110  * @param   pVCpu               The cross context virtual CPU structure of the calling thread.
    2111  */
    2112 uint32_t iemOpcodeGetNextU32SlowJmp(PVMCPUCC pVCpu) IEM_NOEXCEPT_MAY_LONGJMP
    2113 {
    2114 # ifdef IEM_WITH_CODE_TLB
    2115     uint32_t u32;
    2116     iemOpcodeFetchBytesJmp(pVCpu, sizeof(u32), &u32);
    2117     return u32;
    2118 # else
    2119     VBOXSTRICTRC rcStrict = iemOpcodeFetchMoreBytes(pVCpu, 4);
    2120     if (rcStrict == VINF_SUCCESS)
    2121     {
    2122         uint8_t offOpcode = pVCpu->iem.s.offOpcode;
    2123         pVCpu->iem.s.offOpcode = offOpcode + 4;
    2124 #  ifdef IEM_USE_UNALIGNED_DATA_ACCESS
    2125         return *(uint32_t const *)&pVCpu->iem.s.abOpcode[offOpcode];
    2126 #  else
    2127         return RT_MAKE_U32_FROM_U8(pVCpu->iem.s.abOpcode[offOpcode],
    2128                                    pVCpu->iem.s.abOpcode[offOpcode + 1],
    2129                                    pVCpu->iem.s.abOpcode[offOpcode + 2],
    2130                                    pVCpu->iem.s.abOpcode[offOpcode + 3]);
    2131 #  endif
    2132     }
    2133     IEM_DO_LONGJMP(pVCpu, VBOXSTRICTRC_VAL(rcStrict));
    2134 # endif
    2135 }
    2136 
    2137 #endif /* IEM_WITH_SETJMP */
    2138 
    2139 #ifndef IEM_WITH_SETJMP
    2140 
    2141 /**
    2142  * Deals with the problematic cases that iemOpcodeGetNextU32ZxU64 doesn't like.
    2143  *
    2144  * @returns Strict VBox status code.
    2145  * @param   pVCpu               The cross context virtual CPU structure of the calling thread.
    2146  * @param   pu64                Where to return the opcode dword.
    2147  */
    2148 VBOXSTRICTRC iemOpcodeGetNextU32ZxU64Slow(PVMCPUCC pVCpu, uint64_t *pu64) RT_NOEXCEPT
    2149 {
    2150     VBOXSTRICTRC rcStrict = iemOpcodeFetchMoreBytes(pVCpu, 4);
    2151     if (rcStrict == VINF_SUCCESS)
    2152     {
    2153         uint8_t offOpcode = pVCpu->iem.s.offOpcode;
    2154         *pu64 = RT_MAKE_U32_FROM_U8(pVCpu->iem.s.abOpcode[offOpcode],
    2155                                     pVCpu->iem.s.abOpcode[offOpcode + 1],
    2156                                     pVCpu->iem.s.abOpcode[offOpcode + 2],
    2157                                     pVCpu->iem.s.abOpcode[offOpcode + 3]);
    2158         pVCpu->iem.s.offOpcode = offOpcode + 4;
    2159     }
    2160     else
    2161         *pu64 = 0;
    2162     return rcStrict;
    2163 }
    2164 
    2165 
    2166 /**
    2167  * Deals with the problematic cases that iemOpcodeGetNextS32SxU64 doesn't like.
    2168  *
    2169  * @returns Strict VBox status code.
    2170  * @param   pVCpu               The cross context virtual CPU structure of the calling thread.
    2171  * @param   pu64                Where to return the opcode qword.
    2172  */
    2173 VBOXSTRICTRC iemOpcodeGetNextS32SxU64Slow(PVMCPUCC pVCpu, uint64_t *pu64) RT_NOEXCEPT
    2174 {
    2175     VBOXSTRICTRC rcStrict = iemOpcodeFetchMoreBytes(pVCpu, 4);
    2176     if (rcStrict == VINF_SUCCESS)
    2177     {
    2178         uint8_t offOpcode = pVCpu->iem.s.offOpcode;
    2179         *pu64 = (int32_t)RT_MAKE_U32_FROM_U8(pVCpu->iem.s.abOpcode[offOpcode],
    2180                                              pVCpu->iem.s.abOpcode[offOpcode + 1],
    2181                                              pVCpu->iem.s.abOpcode[offOpcode + 2],
    2182                                              pVCpu->iem.s.abOpcode[offOpcode + 3]);
    2183         pVCpu->iem.s.offOpcode = offOpcode + 4;
    2184     }
    2185     else
    2186         *pu64 = 0;
    2187     return rcStrict;
    2188 }
    2189 
    2190 #endif /* !IEM_WITH_SETJMP */
    2191 
    2192 #ifndef IEM_WITH_SETJMP
    2193 
    2194 /**
    2195  * Deals with the problematic cases that iemOpcodeGetNextU64 doesn't like.
    2196  *
    2197  * @returns Strict VBox status code.
    2198  * @param   pVCpu               The cross context virtual CPU structure of the calling thread.
    2199  * @param   pu64                Where to return the opcode qword.
    2200  */
    2201 VBOXSTRICTRC iemOpcodeGetNextU64Slow(PVMCPUCC pVCpu, uint64_t *pu64) RT_NOEXCEPT
    2202 {
    2203     VBOXSTRICTRC rcStrict = iemOpcodeFetchMoreBytes(pVCpu, 8);
    2204     if (rcStrict == VINF_SUCCESS)
    2205     {
    2206         uint8_t offOpcode = pVCpu->iem.s.offOpcode;
    2207 # ifdef IEM_USE_UNALIGNED_DATA_ACCESS
    2208         *pu64 = *(uint64_t const *)&pVCpu->iem.s.abOpcode[offOpcode];
    2209 # else
    2210         *pu64 = RT_MAKE_U64_FROM_U8(pVCpu->iem.s.abOpcode[offOpcode],
    2211                                     pVCpu->iem.s.abOpcode[offOpcode + 1],
    2212                                     pVCpu->iem.s.abOpcode[offOpcode + 2],
    2213                                     pVCpu->iem.s.abOpcode[offOpcode + 3],
    2214                                     pVCpu->iem.s.abOpcode[offOpcode + 4],
    2215                                     pVCpu->iem.s.abOpcode[offOpcode + 5],
    2216                                     pVCpu->iem.s.abOpcode[offOpcode + 6],
    2217                                     pVCpu->iem.s.abOpcode[offOpcode + 7]);
    2218 # endif
    2219         pVCpu->iem.s.offOpcode = offOpcode + 8;
    2220     }
    2221     else
    2222         *pu64 = 0;
    2223     return rcStrict;
    2224 }
    2225 
    2226 #else  /* IEM_WITH_SETJMP */
    2227 
    2228 /**
    2229  * Deals with the problematic cases that iemOpcodeGetNextU64Jmp doesn't like, longjmp on error.
    2230  *
    2231  * @returns The opcode qword.
    2232  * @param   pVCpu               The cross context virtual CPU structure of the calling thread.
    2233  */
    2234 uint64_t iemOpcodeGetNextU64SlowJmp(PVMCPUCC pVCpu) IEM_NOEXCEPT_MAY_LONGJMP
    2235 {
    2236 # ifdef IEM_WITH_CODE_TLB
    2237     uint64_t u64;
    2238     iemOpcodeFetchBytesJmp(pVCpu, sizeof(u64), &u64);
    2239     return u64;
    2240 # else
    2241     VBOXSTRICTRC rcStrict = iemOpcodeFetchMoreBytes(pVCpu, 8);
    2242     if (rcStrict == VINF_SUCCESS)
    2243     {
    2244         uint8_t offOpcode = pVCpu->iem.s.offOpcode;
    2245         pVCpu->iem.s.offOpcode = offOpcode + 8;
    2246 #  ifdef IEM_USE_UNALIGNED_DATA_ACCESS
    2247         return *(uint64_t const *)&pVCpu->iem.s.abOpcode[offOpcode];
    2248 #  else
    2249         return RT_MAKE_U64_FROM_U8(pVCpu->iem.s.abOpcode[offOpcode],
    2250                                    pVCpu->iem.s.abOpcode[offOpcode + 1],
    2251                                    pVCpu->iem.s.abOpcode[offOpcode + 2],
    2252                                    pVCpu->iem.s.abOpcode[offOpcode + 3],
    2253                                    pVCpu->iem.s.abOpcode[offOpcode + 4],
    2254                                    pVCpu->iem.s.abOpcode[offOpcode + 5],
    2255                                    pVCpu->iem.s.abOpcode[offOpcode + 6],
    2256                                    pVCpu->iem.s.abOpcode[offOpcode + 7]);
    2257 #  endif
    2258     }
    2259     IEM_DO_LONGJMP(pVCpu, VBOXSTRICTRC_VAL(rcStrict));
    2260 # endif
    2261 }
    2262 
    2263 #endif /* IEM_WITH_SETJMP */
    2264 
    2265 
    2266 
    2267 /** @name   Register Access.
     50#include "IEMAllTlbInline-x86.h"
     51
     52
     53/** @name   Memory access.
     54 *
    226855 * @{
    226956 */
    2270 
    2271 /**
    2272  * Adds a 8-bit signed jump offset to RIP/EIP/IP.
    2273  *
    2274  * May raise a \#GP(0) if the new RIP is non-canonical or outside the code
    2275  * segment limit.
    2276  *
    2277  * @param   pVCpu               The cross context virtual CPU structure of the calling thread.
    2278  * @param   cbInstr             Instruction size.
    2279  * @param   offNextInstr        The offset of the next instruction.
    2280  * @param   enmEffOpSize        Effective operand size.
    2281  */
    2282 VBOXSTRICTRC iemRegRipRelativeJumpS8AndFinishClearingRF(PVMCPUCC pVCpu, uint8_t cbInstr, int8_t offNextInstr,
    2283                                                         IEMMODE enmEffOpSize) RT_NOEXCEPT
    2284 {
    2285     switch (enmEffOpSize)
    2286     {
    2287         case IEMMODE_16BIT:
    2288         {
    2289             uint16_t const uNewIp = pVCpu->cpum.GstCtx.ip + cbInstr + (int16_t)offNextInstr;
    2290             if (RT_LIKELY(   uNewIp <= pVCpu->cpum.GstCtx.cs.u32Limit
    2291                           || IEM_IS_64BIT_CODE(pVCpu) /* no CS limit checks in 64-bit mode */))
    2292                 pVCpu->cpum.GstCtx.rip = uNewIp;
    2293             else
    2294                 return iemRaiseGeneralProtectionFault0(pVCpu);
    2295             break;
    2296         }
    2297 
    2298         case IEMMODE_32BIT:
    2299         {
    2300             Assert(!IEM_IS_64BIT_CODE(pVCpu));
    2301             Assert(pVCpu->cpum.GstCtx.rip <= UINT32_MAX);
    2302 
    2303             uint32_t const uNewEip = pVCpu->cpum.GstCtx.eip + cbInstr + (int32_t)offNextInstr;
    2304             if (RT_LIKELY(uNewEip <= pVCpu->cpum.GstCtx.cs.u32Limit))
    2305                 pVCpu->cpum.GstCtx.rip = uNewEip;
    2306             else
    2307                 return iemRaiseGeneralProtectionFault0(pVCpu);
    2308             break;
    2309         }
    2310 
    2311         case IEMMODE_64BIT:
    2312         {
    2313             Assert(IEM_IS_64BIT_CODE(pVCpu));
    2314 
    2315             uint64_t const uNewRip = pVCpu->cpum.GstCtx.rip + cbInstr + (int64_t)offNextInstr;
    2316             if (RT_LIKELY(IEM_IS_CANONICAL(uNewRip)))
    2317                 pVCpu->cpum.GstCtx.rip = uNewRip;
    2318             else
    2319                 return iemRaiseGeneralProtectionFault0(pVCpu);
    2320             break;
    2321         }
    2322 
    2323         IEM_NOT_REACHED_DEFAULT_CASE_RET();
    2324     }
    2325 
    2326 #ifndef IEM_WITH_CODE_TLB
    2327     /* Flush the prefetch buffer. */
    2328     pVCpu->iem.s.cbOpcode = cbInstr;
    2329 #endif
    2330 
    2331     /*
    2332      * Clear RF and finish the instruction (maybe raise #DB).
    2333      */
    2334     return iemRegFinishClearingRF(pVCpu, VINF_SUCCESS);
    2335 }
    2336 
    2337 
    2338 /**
    2339  * Adds a 16-bit signed jump offset to RIP/EIP/IP.
    2340  *
    2341  * May raise a \#GP(0) if the new RIP is non-canonical or outside the code
    2342  * segment limit.
    2343  *
    2344  * @returns Strict VBox status code.
    2345  * @param   pVCpu               The cross context virtual CPU structure of the calling thread.
    2346  * @param   cbInstr             Instruction size.
    2347  * @param   offNextInstr        The offset of the next instruction.
    2348  */
    2349 VBOXSTRICTRC iemRegRipRelativeJumpS16AndFinishClearingRF(PVMCPUCC pVCpu, uint8_t cbInstr, int16_t offNextInstr) RT_NOEXCEPT
    2350 {
    2351     Assert(pVCpu->iem.s.enmEffOpSize == IEMMODE_16BIT);
    2352 
    2353     uint16_t const uNewIp = pVCpu->cpum.GstCtx.ip + cbInstr + offNextInstr;
    2354     if (RT_LIKELY(   uNewIp <= pVCpu->cpum.GstCtx.cs.u32Limit
    2355                   || IEM_IS_64BIT_CODE(pVCpu) /* no limit checking in 64-bit mode */))
    2356         pVCpu->cpum.GstCtx.rip = uNewIp;
    2357     else
    2358         return iemRaiseGeneralProtectionFault0(pVCpu);
    2359 
    2360 #ifndef IEM_WITH_CODE_TLB
    2361     /* Flush the prefetch buffer. */
    2362     pVCpu->iem.s.cbOpcode = IEM_GET_INSTR_LEN(pVCpu);
    2363 #endif
    2364 
    2365     /*
    2366      * Clear RF and finish the instruction (maybe raise #DB).
    2367      */
    2368     return iemRegFinishClearingRF(pVCpu, VINF_SUCCESS);
    2369 }
    2370 
    2371 
    2372 /**
    2373  * Adds a 32-bit signed jump offset to RIP/EIP/IP.
    2374  *
    2375  * May raise a \#GP(0) if the new RIP is non-canonical or outside the code
    2376  * segment limit.
    2377  *
    2378  * @returns Strict VBox status code.
    2379  * @param   pVCpu               The cross context virtual CPU structure of the calling thread.
    2380  * @param   cbInstr             Instruction size.
    2381  * @param   offNextInstr        The offset of the next instruction.
    2382  * @param   enmEffOpSize        Effective operand size.
    2383  */
    2384 VBOXSTRICTRC iemRegRipRelativeJumpS32AndFinishClearingRF(PVMCPUCC pVCpu, uint8_t cbInstr, int32_t offNextInstr,
    2385                                                          IEMMODE enmEffOpSize) RT_NOEXCEPT
    2386 {
    2387     if (enmEffOpSize == IEMMODE_32BIT)
    2388     {
    2389         Assert(pVCpu->cpum.GstCtx.rip <= UINT32_MAX); Assert(!IEM_IS_64BIT_CODE(pVCpu));
    2390 
    2391         uint32_t const uNewEip = pVCpu->cpum.GstCtx.eip + cbInstr + offNextInstr;
    2392         if (RT_LIKELY(uNewEip <= pVCpu->cpum.GstCtx.cs.u32Limit))
    2393             pVCpu->cpum.GstCtx.rip = uNewEip;
    2394         else
    2395             return iemRaiseGeneralProtectionFault0(pVCpu);
    2396     }
    2397     else
    2398     {
    2399         Assert(enmEffOpSize == IEMMODE_64BIT);
    2400 
    2401         uint64_t const uNewRip = pVCpu->cpum.GstCtx.rip + cbInstr + (int64_t)offNextInstr;
    2402         if (RT_LIKELY(IEM_IS_CANONICAL(uNewRip)))
    2403             pVCpu->cpum.GstCtx.rip = uNewRip;
    2404         else
    2405             return iemRaiseGeneralProtectionFault0(pVCpu);
    2406     }
    2407 
    2408 #ifndef IEM_WITH_CODE_TLB
    2409     /* Flush the prefetch buffer. */
    2410     pVCpu->iem.s.cbOpcode = IEM_GET_INSTR_LEN(pVCpu);
    2411 #endif
    2412 
    2413     /*
    2414      * Clear RF and finish the instruction (maybe raise #DB).
    2415      */
    2416     return iemRegFinishClearingRF(pVCpu, VINF_SUCCESS);
    2417 }
    2418 
    2419 /** @}  */
    2420 
    2421 
    2422 /** @name   Memory access.
    2423  *
    2424  * @{
    2425  */
    2426 
    2427 #undef  LOG_GROUP
    2428 #define LOG_GROUP LOG_GROUP_IEM_MEM
    242957
    243058/**
     
    2612240}
    2613241
    2614 #if 0 /*unused*/
    2615 /**
    2616  * Looks up a memory mapping entry.
    2617  *
    2618  * @returns The mapping index (positive) or VERR_NOT_FOUND (negative).
    2619  * @param   pVCpu           The cross context virtual CPU structure of the calling thread.
    2620  * @param   pvMem           The memory address.
    2621  * @param   fAccess         The access to.
    2622  */
    2623 DECLINLINE(int) iemMapLookup(PVMCPUCC pVCpu, void *pvMem, uint32_t fAccess)
    2624 {
    2625     Assert(pVCpu->iem.s.cActiveMappings <= RT_ELEMENTS(pVCpu->iem.s.aMemMappings));
    2626     fAccess &= IEM_ACCESS_WHAT_MASK | IEM_ACCESS_TYPE_MASK;
    2627     if (   pVCpu->iem.s.aMemMappings[0].pv == pvMem
    2628         && (pVCpu->iem.s.aMemMappings[0].fAccess & (IEM_ACCESS_WHAT_MASK | IEM_ACCESS_TYPE_MASK)) == fAccess)
    2629         return 0;
    2630     if (   pVCpu->iem.s.aMemMappings[1].pv == pvMem
    2631         && (pVCpu->iem.s.aMemMappings[1].fAccess & (IEM_ACCESS_WHAT_MASK | IEM_ACCESS_TYPE_MASK)) == fAccess)
    2632         return 1;
    2633     if (   pVCpu->iem.s.aMemMappings[2].pv == pvMem
    2634         && (pVCpu->iem.s.aMemMappings[2].fAccess & (IEM_ACCESS_WHAT_MASK | IEM_ACCESS_TYPE_MASK)) == fAccess)
    2635         return 2;
    2636     return VERR_NOT_FOUND;
    2637 }
    2638 #endif
    2639242
    2640243/**
     
    2667270
    2668271/**
    2669  * Commits a bounce buffer that needs writing back and unmaps it.
    2670  *
    2671  * @returns Strict VBox status code.
    2672  * @param   pVCpu           The cross context virtual CPU structure of the calling thread.
    2673  * @param   iMemMap         The index of the buffer to commit.
    2674  * @param   fPostponeFail   Whether we can postpone writer failures to ring-3.
    2675  *                          Always false in ring-3, obviously.
    2676  */
    2677 static VBOXSTRICTRC iemMemBounceBufferCommitAndUnmap(PVMCPUCC pVCpu, unsigned iMemMap, bool fPostponeFail)
    2678 {
    2679     Assert(pVCpu->iem.s.aMemMappings[iMemMap].fAccess & IEM_ACCESS_BOUNCE_BUFFERED);
    2680     Assert(pVCpu->iem.s.aMemMappings[iMemMap].fAccess & IEM_ACCESS_TYPE_WRITE);
    2681 #ifdef IN_RING3
    2682     Assert(!fPostponeFail);
    2683     RT_NOREF_PV(fPostponeFail);
    2684 #endif
    2685 
    2686     /*
    2687      * Do the writing.
    2688      */
    2689     PVMCC pVM = pVCpu->CTX_SUFF(pVM);
    2690     if (!pVCpu->iem.s.aMemBbMappings[iMemMap].fUnassigned)
    2691     {
    2692         uint16_t const  cbFirst  = pVCpu->iem.s.aMemBbMappings[iMemMap].cbFirst;
    2693         uint16_t const  cbSecond = pVCpu->iem.s.aMemBbMappings[iMemMap].cbSecond;
    2694         uint8_t const  *pbBuf    = &pVCpu->iem.s.aBounceBuffers[iMemMap].ab[0];
    2695         if (!(pVCpu->iem.s.fExec & IEM_F_BYPASS_HANDLERS))
    2696         {
    2697             /*
    2698              * Carefully and efficiently dealing with access handler return
    2699              * codes make this a little bloated.
    2700              */
    2701             VBOXSTRICTRC rcStrict = PGMPhysWrite(pVM,
    2702                                                  pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysFirst,
    2703                                                  pbBuf,
    2704                                                  cbFirst,
    2705                                                  PGMACCESSORIGIN_IEM);
    2706             if (rcStrict == VINF_SUCCESS)
    2707             {
    2708                 if (cbSecond)
    2709                 {
    2710                     rcStrict = PGMPhysWrite(pVM,
    2711                                             pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysSecond,
    2712                                             pbBuf + cbFirst,
    2713                                             cbSecond,
    2714                                             PGMACCESSORIGIN_IEM);
    2715                     if (rcStrict == VINF_SUCCESS)
    2716                     { /* nothing */ }
    2717                     else if (PGM_PHYS_RW_IS_SUCCESS(rcStrict))
    2718                     {
    2719                         LogEx(LOG_GROUP_IEM,
    2720                               ("iemMemBounceBufferCommitAndUnmap: PGMPhysWrite GCPhysFirst=%RGp/%#x GCPhysSecond=%RGp/%#x %Rrc\n",
    2721                               pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysFirst, cbFirst,
    2722                               pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysSecond, cbSecond, VBOXSTRICTRC_VAL(rcStrict) ));
    2723                         rcStrict = iemSetPassUpStatus(pVCpu, rcStrict);
    2724                     }
    2725 #ifndef IN_RING3
    2726                     else if (fPostponeFail)
    2727                     {
    2728                         LogEx(LOG_GROUP_IEM,
    2729                               ("iemMemBounceBufferCommitAndUnmap: PGMPhysWrite GCPhysFirst=%RGp/%#x GCPhysSecond=%RGp/%#x %Rrc (postponed)\n",
    2730                                pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysFirst, cbFirst,
    2731                                pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysSecond, cbSecond, VBOXSTRICTRC_VAL(rcStrict) ));
    2732                         pVCpu->iem.s.aMemMappings[iMemMap].fAccess |= IEM_ACCESS_PENDING_R3_WRITE_2ND;
    2733                         VMCPU_FF_SET(pVCpu, VMCPU_FF_IEM);
    2734                         return iemSetPassUpStatus(pVCpu, rcStrict);
    2735                     }
    2736 #endif
    2737                     else
    2738                     {
    2739                         LogEx(LOG_GROUP_IEM,
    2740                               ("iemMemBounceBufferCommitAndUnmap: PGMPhysWrite GCPhysFirst=%RGp/%#x GCPhysSecond=%RGp/%#x %Rrc (!!)\n",
    2741                                pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysFirst, cbFirst,
    2742                                pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysSecond, cbSecond, VBOXSTRICTRC_VAL(rcStrict) ));
    2743                         return rcStrict;
    2744                     }
    2745                 }
    2746             }
    2747             else if (PGM_PHYS_RW_IS_SUCCESS(rcStrict))
    2748             {
    2749                 if (!cbSecond)
    2750                 {
    2751                     LogEx(LOG_GROUP_IEM,
    2752                           ("iemMemBounceBufferCommitAndUnmap: PGMPhysWrite GCPhysFirst=%RGp/%#x %Rrc\n",
    2753                            pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysFirst, cbFirst, VBOXSTRICTRC_VAL(rcStrict) ));
    2754                     rcStrict = iemSetPassUpStatus(pVCpu, rcStrict);
    2755                 }
    2756                 else
    2757                 {
    2758                     VBOXSTRICTRC rcStrict2 = PGMPhysWrite(pVM,
    2759                                                           pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysSecond,
    2760                                                           pbBuf + cbFirst,
    2761                                                           cbSecond,
    2762                                                           PGMACCESSORIGIN_IEM);
    2763                     if (rcStrict2 == VINF_SUCCESS)
    2764                     {
    2765                         LogEx(LOG_GROUP_IEM,
    2766                               ("iemMemBounceBufferCommitAndUnmap: PGMPhysWrite GCPhysFirst=%RGp/%#x %Rrc GCPhysSecond=%RGp/%#x\n",
    2767                                pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysFirst, cbFirst, VBOXSTRICTRC_VAL(rcStrict),
    2768                                pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysSecond, cbSecond));
    2769                         rcStrict = iemSetPassUpStatus(pVCpu, rcStrict);
    2770                     }
    2771                     else if (PGM_PHYS_RW_IS_SUCCESS(rcStrict2))
    2772                     {
    2773                         LogEx(LOG_GROUP_IEM,
    2774                               ("iemMemBounceBufferCommitAndUnmap: PGMPhysWrite GCPhysFirst=%RGp/%#x %Rrc GCPhysSecond=%RGp/%#x %Rrc\n",
    2775                                pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysFirst, cbFirst, VBOXSTRICTRC_VAL(rcStrict),
    2776                                pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysSecond, cbSecond, VBOXSTRICTRC_VAL(rcStrict2) ));
    2777                         PGM_PHYS_RW_DO_UPDATE_STRICT_RC(rcStrict, rcStrict2);
    2778                         rcStrict = iemSetPassUpStatus(pVCpu, rcStrict);
    2779                     }
    2780 #ifndef IN_RING3
    2781                     else if (fPostponeFail)
    2782                     {
    2783                         LogEx(LOG_GROUP_IEM,
    2784                               ("iemMemBounceBufferCommitAndUnmap: PGMPhysWrite GCPhysFirst=%RGp/%#x GCPhysSecond=%RGp/%#x %Rrc (postponed)\n",
    2785                                pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysFirst, cbFirst,
    2786                                pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysSecond, cbSecond, VBOXSTRICTRC_VAL(rcStrict) ));
    2787                         pVCpu->iem.s.aMemMappings[iMemMap].fAccess |= IEM_ACCESS_PENDING_R3_WRITE_2ND;
    2788                         VMCPU_FF_SET(pVCpu, VMCPU_FF_IEM);
    2789                         return iemSetPassUpStatus(pVCpu, rcStrict);
    2790                     }
    2791 #endif
    2792                     else
    2793                     {
    2794                         LogEx(LOG_GROUP_IEM,
    2795                               ("iemMemBounceBufferCommitAndUnmap: PGMPhysWrite GCPhysFirst=%RGp/%#x %Rrc GCPhysSecond=%RGp/%#x %Rrc (!!)\n",
    2796                                pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysFirst, cbFirst, VBOXSTRICTRC_VAL(rcStrict),
    2797                                pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysSecond, cbSecond, VBOXSTRICTRC_VAL(rcStrict2) ));
    2798                         return rcStrict2;
    2799                     }
    2800                 }
    2801             }
    2802 #ifndef IN_RING3
    2803             else if (fPostponeFail)
    2804             {
    2805                 LogEx(LOG_GROUP_IEM,
    2806                       ("iemMemBounceBufferCommitAndUnmap: PGMPhysWrite GCPhysFirst=%RGp/%#x GCPhysSecond=%RGp/%#x %Rrc (postponed)\n",
    2807                        pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysFirst, cbFirst,
    2808                        pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysSecond, cbSecond, VBOXSTRICTRC_VAL(rcStrict) ));
    2809                 if (!cbSecond)
    2810                     pVCpu->iem.s.aMemMappings[iMemMap].fAccess |= IEM_ACCESS_PENDING_R3_WRITE_1ST;
    2811                 else
    2812                     pVCpu->iem.s.aMemMappings[iMemMap].fAccess |= IEM_ACCESS_PENDING_R3_WRITE_1ST | IEM_ACCESS_PENDING_R3_WRITE_2ND;
    2813                 VMCPU_FF_SET(pVCpu, VMCPU_FF_IEM);
    2814                 return iemSetPassUpStatus(pVCpu, rcStrict);
    2815             }
    2816 #endif
    2817             else
    2818             {
    2819                 LogEx(LOG_GROUP_IEM,
    2820                       ("iemMemBounceBufferCommitAndUnmap: PGMPhysWrite GCPhysFirst=%RGp/%#x %Rrc [GCPhysSecond=%RGp/%#x] (!!)\n",
    2821                        pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysFirst, cbFirst, VBOXSTRICTRC_VAL(rcStrict),
    2822                        pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysSecond, cbSecond));
    2823                 return rcStrict;
    2824             }
    2825         }
    2826         else
    2827         {
    2828             /*
    2829              * No access handlers, much simpler.
    2830              */
    2831             int rc = PGMPhysSimpleWriteGCPhys(pVM, pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysFirst, pbBuf, cbFirst);
    2832             if (RT_SUCCESS(rc))
    2833             {
    2834                 if (cbSecond)
    2835                 {
    2836                     rc = PGMPhysSimpleWriteGCPhys(pVM, pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysSecond, pbBuf + cbFirst, cbSecond);
    2837                     if (RT_SUCCESS(rc))
    2838                     { /* likely */ }
    2839                     else
    2840                     {
    2841                         LogEx(LOG_GROUP_IEM,
    2842                               ("iemMemBounceBufferCommitAndUnmap: PGMPhysSimpleWriteGCPhys GCPhysFirst=%RGp/%#x GCPhysSecond=%RGp/%#x %Rrc (!!)\n",
    2843                                pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysFirst, cbFirst,
    2844                                pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysSecond, cbSecond, rc));
    2845                         return rc;
    2846                     }
    2847                 }
    2848             }
    2849             else
    2850             {
    2851                 LogEx(LOG_GROUP_IEM,
    2852                       ("iemMemBounceBufferCommitAndUnmap: PGMPhysSimpleWriteGCPhys GCPhysFirst=%RGp/%#x %Rrc [GCPhysSecond=%RGp/%#x] (!!)\n",
    2853                        pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysFirst, cbFirst, rc,
    2854                        pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysSecond, cbSecond));
    2855                 return rc;
    2856             }
    2857         }
    2858     }
    2859 
    2860 #if defined(IEM_LOG_MEMORY_WRITES)
    2861     Log5(("IEM Wrote %RGp: %.*Rhxs\n", pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysFirst,
    2862           RT_MAX(RT_MIN(pVCpu->iem.s.aMemBbMappings[iMemMap].cbFirst, 64), 1), &pVCpu->iem.s.aBounceBuffers[iMemMap].ab[0]));
    2863     if (pVCpu->iem.s.aMemBbMappings[iMemMap].cbSecond)
    2864         Log5(("IEM Wrote %RGp: %.*Rhxs [2nd page]\n", pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysSecond,
    2865               RT_MIN(pVCpu->iem.s.aMemBbMappings[iMemMap].cbSecond, 64),
    2866               &pVCpu->iem.s.aBounceBuffers[iMemMap].ab[pVCpu->iem.s.aMemBbMappings[iMemMap].cbFirst]));
    2867 
    2868     size_t cbWrote = pVCpu->iem.s.aMemBbMappings[iMemMap].cbFirst + pVCpu->iem.s.aMemBbMappings[iMemMap].cbSecond;
    2869     g_cbIemWrote = cbWrote;
    2870     memcpy(g_abIemWrote, &pVCpu->iem.s.aBounceBuffers[iMemMap].ab[0], RT_MIN(cbWrote, sizeof(g_abIemWrote)));
    2871 #endif
    2872 
    2873     /*
    2874      * Free the mapping entry.
    2875      */
    2876     pVCpu->iem.s.aMemMappings[iMemMap].fAccess = IEM_ACCESS_INVALID;
    2877     Assert(pVCpu->iem.s.cActiveMappings != 0);
    2878     pVCpu->iem.s.cActiveMappings--;
    2879     return VINF_SUCCESS;
    2880 }
    2881 
    2882 
    2883 /**
    2884272 * Helper for iemMemMap, iemMemMapJmp and iemMemBounceBufferMapCrossPage.
     273 * @todo duplicated
    2885274 */
    2886275DECL_FORCE_INLINE(uint32_t)
     
    2892281    return DBGFBpCheckDataRead(pVM, pVCpu, GCPtrMem, (uint32_t)cbMem, fSysAccess);
    2893282}
    2894 
    2895 
    2896 /**
    2897  * iemMemMap worker that deals with a request crossing pages.
    2898  */
    2899 static VBOXSTRICTRC
    2900 iemMemBounceBufferMapCrossPage(PVMCPUCC pVCpu, int iMemMap, void **ppvMem, uint8_t *pbUnmapInfo,
    2901                                size_t cbMem, RTGCPTR GCPtrFirst, uint32_t fAccess)
    2902 {
    2903     STAM_COUNTER_INC(&pVCpu->iem.s.StatMemBounceBufferCrossPage);
    2904     Assert(cbMem <= GUEST_PAGE_SIZE);
    2905 
    2906     /*
    2907      * Do the address translations.
    2908      */
    2909     uint32_t const cbFirstPage  = GUEST_PAGE_SIZE - (uint32_t)(GCPtrFirst & GUEST_PAGE_OFFSET_MASK);
    2910     RTGCPHYS GCPhysFirst;
    2911     VBOXSTRICTRC rcStrict = iemMemPageTranslateAndCheckAccess(pVCpu, GCPtrFirst, cbFirstPage, fAccess, &GCPhysFirst);
    2912     if (rcStrict != VINF_SUCCESS)
    2913         return rcStrict;
    2914     Assert((GCPhysFirst & GUEST_PAGE_OFFSET_MASK) == (GCPtrFirst & GUEST_PAGE_OFFSET_MASK));
    2915 
    2916     uint32_t const cbSecondPage = (uint32_t)cbMem - cbFirstPage;
    2917     RTGCPHYS GCPhysSecond;
    2918     rcStrict = iemMemPageTranslateAndCheckAccess(pVCpu, (GCPtrFirst + (cbMem - 1)) & ~(RTGCPTR)GUEST_PAGE_OFFSET_MASK,
    2919                                                  cbSecondPage, fAccess, &GCPhysSecond);
    2920     if (rcStrict != VINF_SUCCESS)
    2921         return rcStrict;
    2922     Assert((GCPhysSecond & GUEST_PAGE_OFFSET_MASK) == 0);
    2923     GCPhysSecond &= ~(RTGCPHYS)GUEST_PAGE_OFFSET_MASK; /** @todo why? */
    2924 
    2925     PVMCC pVM = pVCpu->CTX_SUFF(pVM);
    2926 
    2927     /*
    2928      * Check for data breakpoints.
    2929      */
    2930     if (RT_LIKELY(!(pVCpu->iem.s.fExec & IEM_F_PENDING_BRK_DATA)))
    2931     { /* likely */ }
    2932     else
    2933     {
    2934         uint32_t fDataBps = iemMemCheckDataBreakpoint(pVM, pVCpu, GCPtrFirst, cbFirstPage, fAccess);
    2935         fDataBps         |= iemMemCheckDataBreakpoint(pVM, pVCpu, (GCPtrFirst + (cbMem - 1)) & ~(RTGCPTR)GUEST_PAGE_OFFSET_MASK,
    2936                                                       cbSecondPage, fAccess);
    2937         pVCpu->cpum.GstCtx.eflags.uBoth |= fDataBps & (CPUMCTX_DBG_HIT_DRX_MASK | CPUMCTX_DBG_DBGF_MASK);
    2938         if (fDataBps > 1)
    2939             LogEx(LOG_GROUP_IEM, ("iemMemBounceBufferMapCrossPage: Data breakpoint: fDataBps=%#x for %RGv LB %zx; fAccess=%#x cs:rip=%04x:%08RX64\n",
    2940                                   fDataBps, GCPtrFirst, cbMem, fAccess, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
    2941     }
    2942 
    2943     /*
    2944      * Read in the current memory content if it's a read, execute or partial
    2945      * write access.
    2946      */
    2947     uint8_t * const pbBuf = &pVCpu->iem.s.aBounceBuffers[iMemMap].ab[0];
    2948 
    2949     if (fAccess & (IEM_ACCESS_TYPE_READ | IEM_ACCESS_TYPE_EXEC | IEM_ACCESS_PARTIAL_WRITE))
    2950     {
    2951         if (!(pVCpu->iem.s.fExec & IEM_F_BYPASS_HANDLERS))
    2952         {
    2953             /*
    2954              * Must carefully deal with access handler status codes here,
    2955              * makes the code a bit bloated.
    2956              */
    2957             rcStrict = PGMPhysRead(pVM, GCPhysFirst, pbBuf, cbFirstPage, PGMACCESSORIGIN_IEM);
    2958             if (rcStrict == VINF_SUCCESS)
    2959             {
    2960                 rcStrict = PGMPhysRead(pVM, GCPhysSecond, pbBuf + cbFirstPage, cbSecondPage, PGMACCESSORIGIN_IEM);
    2961                 if (rcStrict == VINF_SUCCESS)
    2962                 { /*likely */ }
    2963                 else if (PGM_PHYS_RW_IS_SUCCESS(rcStrict))
    2964                     rcStrict = iemSetPassUpStatus(pVCpu, rcStrict);
    2965                 else
    2966                 {
    2967                     LogEx(LOG_GROUP_IEM, ("iemMemBounceBufferMapPhys: PGMPhysRead GCPhysSecond=%RGp rcStrict2=%Rrc (!!)\n",
    2968                                           GCPhysSecond, VBOXSTRICTRC_VAL(rcStrict) ));
    2969                     return rcStrict;
    2970                 }
    2971             }
    2972             else if (PGM_PHYS_RW_IS_SUCCESS(rcStrict))
    2973             {
    2974                 VBOXSTRICTRC rcStrict2 = PGMPhysRead(pVM, GCPhysSecond, pbBuf + cbFirstPage, cbSecondPage, PGMACCESSORIGIN_IEM);
    2975                 if (PGM_PHYS_RW_IS_SUCCESS(rcStrict2))
    2976                 {
    2977                     PGM_PHYS_RW_DO_UPDATE_STRICT_RC(rcStrict, rcStrict2);
    2978                     rcStrict = iemSetPassUpStatus(pVCpu, rcStrict);
    2979                 }
    2980                 else
    2981                 {
    2982                     LogEx(LOG_GROUP_IEM,
    2983                           ("iemMemBounceBufferMapPhys: PGMPhysRead GCPhysSecond=%RGp rcStrict2=%Rrc (rcStrict=%Rrc) (!!)\n",
    2984                            GCPhysSecond, VBOXSTRICTRC_VAL(rcStrict2), VBOXSTRICTRC_VAL(rcStrict2) ));
    2985                     return rcStrict2;
    2986                 }
    2987             }
    2988             else
    2989             {
    2990                 LogEx(LOG_GROUP_IEM, ("iemMemBounceBufferMapPhys: PGMPhysRead GCPhysFirst=%RGp rcStrict=%Rrc (!!)\n",
    2991                                       GCPhysFirst, VBOXSTRICTRC_VAL(rcStrict) ));
    2992                 return rcStrict;
    2993             }
    2994         }
    2995         else
    2996         {
    2997             /*
    2998              * No informational status codes here, much more straight forward.
    2999              */
    3000             int rc = PGMPhysSimpleReadGCPhys(pVM, pbBuf, GCPhysFirst, cbFirstPage);
    3001             if (RT_SUCCESS(rc))
    3002             {
    3003                 Assert(rc == VINF_SUCCESS);
    3004                 rc = PGMPhysSimpleReadGCPhys(pVM, pbBuf + cbFirstPage, GCPhysSecond, cbSecondPage);
    3005                 if (RT_SUCCESS(rc))
    3006                     Assert(rc == VINF_SUCCESS);
    3007                 else
    3008                 {
    3009                     LogEx(LOG_GROUP_IEM,
    3010                           ("iemMemBounceBufferMapPhys: PGMPhysSimpleReadGCPhys GCPhysSecond=%RGp rc=%Rrc (!!)\n", GCPhysSecond, rc));
    3011                     return rc;
    3012                 }
    3013             }
    3014             else
    3015             {
    3016                 LogEx(LOG_GROUP_IEM,
    3017                       ("iemMemBounceBufferMapPhys: PGMPhysSimpleReadGCPhys GCPhysFirst=%RGp rc=%Rrc (!!)\n", GCPhysFirst, rc));
    3018                 return rc;
    3019             }
    3020         }
    3021     }
    3022 #ifdef VBOX_STRICT
    3023     else
    3024         memset(pbBuf, 0xcc, cbMem);
    3025     if (cbMem < sizeof(pVCpu->iem.s.aBounceBuffers[iMemMap].ab))
    3026         memset(pbBuf + cbMem, 0xaa, sizeof(pVCpu->iem.s.aBounceBuffers[iMemMap].ab) - cbMem);
    3027 #endif
    3028     AssertCompileMemberAlignment(VMCPU, iem.s.aBounceBuffers, 64);
    3029 
    3030     /*
    3031      * Commit the bounce buffer entry.
    3032      */
    3033     pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysFirst    = GCPhysFirst;
    3034     pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysSecond   = GCPhysSecond;
    3035     pVCpu->iem.s.aMemBbMappings[iMemMap].cbFirst        = (uint16_t)cbFirstPage;
    3036     pVCpu->iem.s.aMemBbMappings[iMemMap].cbSecond       = (uint16_t)cbSecondPage;
    3037     pVCpu->iem.s.aMemBbMappings[iMemMap].fUnassigned    = false;
    3038     pVCpu->iem.s.aMemMappings[iMemMap].pv               = pbBuf;
    3039     pVCpu->iem.s.aMemMappings[iMemMap].fAccess          = fAccess | IEM_ACCESS_BOUNCE_BUFFERED;
    3040     pVCpu->iem.s.iNextMapping = iMemMap + 1;
    3041     pVCpu->iem.s.cActiveMappings++;
    3042 
    3043     *ppvMem = pbBuf;
    3044     *pbUnmapInfo = iMemMap | 0x08 | ((fAccess & IEM_ACCESS_TYPE_MASK) << 4);
    3045     return VINF_SUCCESS;
    3046 }
    3047 
    3048 
    3049 /**
    3050  * iemMemMap woker that deals with iemMemPageMap failures.
    3051  */
    3052 static VBOXSTRICTRC iemMemBounceBufferMapPhys(PVMCPUCC pVCpu, unsigned iMemMap, void **ppvMem, uint8_t *pbUnmapInfo, size_t cbMem,
    3053                                               RTGCPHYS GCPhysFirst, uint32_t fAccess, VBOXSTRICTRC rcMap)
    3054 {
    3055     STAM_COUNTER_INC(&pVCpu->iem.s.StatMemBounceBufferMapPhys);
    3056 
    3057     /*
    3058      * Filter out conditions we can handle and the ones which shouldn't happen.
    3059      */
    3060     if (   rcMap != VERR_PGM_PHYS_TLB_CATCH_WRITE
    3061         && rcMap != VERR_PGM_PHYS_TLB_CATCH_ALL
    3062         && rcMap != VERR_PGM_PHYS_TLB_UNASSIGNED)
    3063     {
    3064         AssertReturn(RT_FAILURE_NP(rcMap), VERR_IEM_IPE_8);
    3065         return rcMap;
    3066     }
    3067     pVCpu->iem.s.cPotentialExits++;
    3068 
    3069     /*
    3070      * Read in the current memory content if it's a read, execute or partial
    3071      * write access.
    3072      */
    3073     uint8_t *pbBuf = &pVCpu->iem.s.aBounceBuffers[iMemMap].ab[0];
    3074     if (fAccess & (IEM_ACCESS_TYPE_READ | IEM_ACCESS_TYPE_EXEC | IEM_ACCESS_PARTIAL_WRITE))
    3075     {
    3076         if (rcMap == VERR_PGM_PHYS_TLB_UNASSIGNED)
    3077             memset(pbBuf, 0xff, cbMem);
    3078         else
    3079         {
    3080             int rc;
    3081             if (!(pVCpu->iem.s.fExec & IEM_F_BYPASS_HANDLERS))
    3082             {
    3083                 VBOXSTRICTRC rcStrict = PGMPhysRead(pVCpu->CTX_SUFF(pVM), GCPhysFirst, pbBuf, cbMem, PGMACCESSORIGIN_IEM);
    3084                 if (rcStrict == VINF_SUCCESS)
    3085                 { /* nothing */ }
    3086                 else if (PGM_PHYS_RW_IS_SUCCESS(rcStrict))
    3087                     rcStrict = iemSetPassUpStatus(pVCpu, rcStrict);
    3088                 else
    3089                 {
    3090                     LogEx(LOG_GROUP_IEM, ("iemMemBounceBufferMapPhys: PGMPhysRead GCPhysFirst=%RGp rcStrict=%Rrc (!!)\n",
    3091                                           GCPhysFirst, VBOXSTRICTRC_VAL(rcStrict) ));
    3092                     return rcStrict;
    3093                 }
    3094             }
    3095             else
    3096             {
    3097                 rc = PGMPhysSimpleReadGCPhys(pVCpu->CTX_SUFF(pVM), pbBuf, GCPhysFirst, cbMem);
    3098                 if (RT_SUCCESS(rc))
    3099                 { /* likely */ }
    3100                 else
    3101                 {
    3102                     LogEx(LOG_GROUP_IEM, ("iemMemBounceBufferMapPhys: PGMPhysSimpleReadGCPhys GCPhysFirst=%RGp rcStrict=%Rrc (!!)\n",
    3103                                           GCPhysFirst, rc));
    3104                     return rc;
    3105                 }
    3106             }
    3107         }
    3108     }
    3109 #ifdef VBOX_STRICT
    3110     else
    3111         memset(pbBuf, 0xcc, cbMem);
    3112 #endif
    3113 #ifdef VBOX_STRICT
    3114     if (cbMem < sizeof(pVCpu->iem.s.aBounceBuffers[iMemMap].ab))
    3115         memset(pbBuf + cbMem, 0xaa, sizeof(pVCpu->iem.s.aBounceBuffers[iMemMap].ab) - cbMem);
    3116 #endif
    3117 
    3118     /*
    3119      * Commit the bounce buffer entry.
    3120      */
    3121     pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysFirst    = GCPhysFirst;
    3122     pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysSecond   = NIL_RTGCPHYS;
    3123     pVCpu->iem.s.aMemBbMappings[iMemMap].cbFirst        = (uint16_t)cbMem;
    3124     pVCpu->iem.s.aMemBbMappings[iMemMap].cbSecond       = 0;
    3125     pVCpu->iem.s.aMemBbMappings[iMemMap].fUnassigned    = rcMap == VERR_PGM_PHYS_TLB_UNASSIGNED;
    3126     pVCpu->iem.s.aMemMappings[iMemMap].pv               = pbBuf;
    3127     pVCpu->iem.s.aMemMappings[iMemMap].fAccess          = fAccess | IEM_ACCESS_BOUNCE_BUFFERED;
    3128     pVCpu->iem.s.iNextMapping = iMemMap + 1;
    3129     pVCpu->iem.s.cActiveMappings++;
    3130 
    3131     *ppvMem = pbBuf;
    3132     *pbUnmapInfo = iMemMap | 0x08 | ((fAccess & IEM_ACCESS_TYPE_MASK) << 4);
    3133     return VINF_SUCCESS;
    3134 }
    3135 
    3136283
    3137284
     
    3328475            { /* likely */ }
    3329476            else
    3330                 IEMTlbInvalidateAllPhysicalSlow(pVCpu);
     477                iemTlbInvalidateAllPhysicalSlow(pVCpu);
    3331478            pTlbe->pbMappingR3       = NULL;
    3332479            pTlbe->fFlagsAndPhysRev &= ~IEMTLBE_GCPHYS2PTR_MASK;
     
    3509656
    3510657    return VINF_SUCCESS;
    3511 }
    3512 
    3513 
    3514 /**
    3515  * Commits the guest memory if bounce buffered and unmaps it.
    3516  *
    3517  * @returns Strict VBox status code.
    3518  * @param   pVCpu               The cross context virtual CPU structure of the calling thread.
    3519  * @param   bUnmapInfo          Unmap info set by iemMemMap.
    3520  */
    3521 VBOXSTRICTRC iemMemCommitAndUnmap(PVMCPUCC pVCpu, uint8_t bUnmapInfo) RT_NOEXCEPT
    3522 {
    3523     uintptr_t const iMemMap = bUnmapInfo & 0x7;
    3524     AssertMsgReturn(   (bUnmapInfo & 0x08)
    3525                     && iMemMap < RT_ELEMENTS(pVCpu->iem.s.aMemMappings)
    3526                     && (pVCpu->iem.s.aMemMappings[iMemMap].fAccess & (IEM_ACCESS_TYPE_MASK | 0xf)) == ((unsigned)bUnmapInfo >> 4),
    3527                     ("%#x fAccess=%#x\n", bUnmapInfo, pVCpu->iem.s.aMemMappings[iMemMap].fAccess),
    3528                     VERR_NOT_FOUND);
    3529 
    3530     /* If it's bounce buffered, we may need to write back the buffer. */
    3531     if (pVCpu->iem.s.aMemMappings[iMemMap].fAccess & IEM_ACCESS_BOUNCE_BUFFERED)
    3532     {
    3533         if (pVCpu->iem.s.aMemMappings[iMemMap].fAccess & IEM_ACCESS_TYPE_WRITE)
    3534             return iemMemBounceBufferCommitAndUnmap(pVCpu, iMemMap, false /*fPostponeFail*/);
    3535     }
    3536     /* Otherwise unlock it. */
    3537     else if (!(pVCpu->iem.s.aMemMappings[iMemMap].fAccess & IEM_ACCESS_NOT_LOCKED))
    3538         PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), &pVCpu->iem.s.aMemMappingLocks[iMemMap].Lock);
    3539 
    3540     /* Free the entry. */
    3541     pVCpu->iem.s.aMemMappings[iMemMap].fAccess = IEM_ACCESS_INVALID;
    3542     Assert(pVCpu->iem.s.cActiveMappings != 0);
    3543     pVCpu->iem.s.cActiveMappings--;
    3544     return VINF_SUCCESS;
    3545 }
    3546 
    3547 
    3548 /**
    3549  * Rolls back the guest memory (conceptually only) and unmaps it.
    3550  *
    3551  * @param   pVCpu               The cross context virtual CPU structure of the calling thread.
    3552  * @param   bUnmapInfo          Unmap info set by iemMemMap.
    3553  */
    3554 void iemMemRollbackAndUnmap(PVMCPUCC pVCpu, uint8_t bUnmapInfo) RT_NOEXCEPT
    3555 {
    3556     uintptr_t const iMemMap = bUnmapInfo & 0x7;
    3557     AssertMsgReturnVoid(   (bUnmapInfo & 0x08)
    3558                         && iMemMap < RT_ELEMENTS(pVCpu->iem.s.aMemMappings)
    3559                         &&    (pVCpu->iem.s.aMemMappings[iMemMap].fAccess & (IEM_ACCESS_TYPE_MASK | 0xf))
    3560                            == ((unsigned)bUnmapInfo >> 4),
    3561                         ("%#x fAccess=%#x\n", bUnmapInfo, pVCpu->iem.s.aMemMappings[iMemMap].fAccess));
    3562 
    3563     /* Unlock it if necessary. */
    3564     if (!(pVCpu->iem.s.aMemMappings[iMemMap].fAccess & IEM_ACCESS_NOT_LOCKED))
    3565         PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), &pVCpu->iem.s.aMemMappingLocks[iMemMap].Lock);
    3566 
    3567     /* Free the entry. */
    3568     pVCpu->iem.s.aMemMappings[iMemMap].fAccess = IEM_ACCESS_INVALID;
    3569     Assert(pVCpu->iem.s.cActiveMappings != 0);
    3570     pVCpu->iem.s.cActiveMappings--;
    3571658}
    3572659
     
    40111098}
    40121099
    4013 
    4014 /**
    4015  * Commits the guest memory if bounce buffered and unmaps it, longjmp on error.
    4016  *
    4017  * @param   pVCpu               The cross context virtual CPU structure of the calling thread.
    4018  * @param   pvMem               The mapping.
    4019  * @param   fAccess             The kind of access.
    4020  */
    4021 void iemMemCommitAndUnmapJmp(PVMCPUCC pVCpu, uint8_t bUnmapInfo) IEM_NOEXCEPT_MAY_LONGJMP
    4022 {
    4023     uintptr_t const iMemMap = bUnmapInfo & 0x7;
    4024     AssertMsgReturnVoid(   (bUnmapInfo & 0x08)
    4025                         && iMemMap < RT_ELEMENTS(pVCpu->iem.s.aMemMappings)
    4026                         &&    (pVCpu->iem.s.aMemMappings[iMemMap].fAccess & (IEM_ACCESS_TYPE_MASK | 0xf))
    4027                            == ((unsigned)bUnmapInfo >> 4),
    4028                         ("%#x fAccess=%#x\n", bUnmapInfo, pVCpu->iem.s.aMemMappings[iMemMap].fAccess));
    4029 
    4030     /* If it's bounce buffered, we may need to write back the buffer. */
    4031     if (pVCpu->iem.s.aMemMappings[iMemMap].fAccess & IEM_ACCESS_BOUNCE_BUFFERED)
    4032     {
    4033         if (pVCpu->iem.s.aMemMappings[iMemMap].fAccess & IEM_ACCESS_TYPE_WRITE)
    4034         {
    4035             VBOXSTRICTRC rcStrict = iemMemBounceBufferCommitAndUnmap(pVCpu, iMemMap, false /*fPostponeFail*/);
    4036             if (rcStrict == VINF_SUCCESS)
    4037                 return;
    4038             IEM_DO_LONGJMP(pVCpu, VBOXSTRICTRC_VAL(rcStrict));
    4039         }
    4040     }
    4041     /* Otherwise unlock it. */
    4042     else if (!(pVCpu->iem.s.aMemMappings[iMemMap].fAccess & IEM_ACCESS_NOT_LOCKED))
    4043         PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), &pVCpu->iem.s.aMemMappingLocks[iMemMap].Lock);
    4044 
    4045     /* Free the entry. */
    4046     pVCpu->iem.s.aMemMappings[iMemMap].fAccess = IEM_ACCESS_INVALID;
    4047     Assert(pVCpu->iem.s.cActiveMappings != 0);
    4048     pVCpu->iem.s.cActiveMappings--;
    4049 }
    4050 
    4051 
    4052 /** Fallback for iemMemCommitAndUnmapRwJmp.  */
    4053 void iemMemCommitAndUnmapRwSafeJmp(PVMCPUCC pVCpu, uint8_t bUnmapInfo) IEM_NOEXCEPT_MAY_LONGJMP
    4054 {
    4055     Assert(((bUnmapInfo >> 4) & IEM_ACCESS_TYPE_MASK) == (IEM_ACCESS_TYPE_READ | IEM_ACCESS_TYPE_WRITE));
    4056     iemMemCommitAndUnmapJmp(pVCpu, bUnmapInfo);
    4057 }
    4058 
    4059 
    4060 /** Fallback for iemMemCommitAndUnmapAtJmp.  */
    4061 void iemMemCommitAndUnmapAtSafeJmp(PVMCPUCC pVCpu, uint8_t bUnmapInfo) IEM_NOEXCEPT_MAY_LONGJMP
    4062 {
    4063     Assert(((bUnmapInfo >> 4) & IEM_ACCESS_TYPE_MASK) == (IEM_ACCESS_TYPE_READ | IEM_ACCESS_TYPE_WRITE));
    4064     iemMemCommitAndUnmapJmp(pVCpu, bUnmapInfo);
    4065 }
    4066 
    4067 
    4068 /** Fallback for iemMemCommitAndUnmapWoJmp.  */
    4069 void iemMemCommitAndUnmapWoSafeJmp(PVMCPUCC pVCpu, uint8_t bUnmapInfo) IEM_NOEXCEPT_MAY_LONGJMP
    4070 {
    4071     Assert(((bUnmapInfo >> 4) & IEM_ACCESS_TYPE_MASK) == IEM_ACCESS_TYPE_WRITE);
    4072     iemMemCommitAndUnmapJmp(pVCpu, bUnmapInfo);
    4073 }
    4074 
    4075 
    4076 /** Fallback for iemMemCommitAndUnmapRoJmp.  */
    4077 void iemMemCommitAndUnmapRoSafeJmp(PVMCPUCC pVCpu, uint8_t bUnmapInfo) IEM_NOEXCEPT_MAY_LONGJMP
    4078 {
    4079     Assert(((bUnmapInfo >> 4) & IEM_ACCESS_TYPE_MASK) == IEM_ACCESS_TYPE_READ);
    4080     iemMemCommitAndUnmapJmp(pVCpu, bUnmapInfo);
    4081 }
    4082 
    4083 
    4084 /** Fallback for iemMemRollbackAndUnmapWo.  */
    4085 void iemMemRollbackAndUnmapWoSafe(PVMCPUCC pVCpu, uint8_t bUnmapInfo) RT_NOEXCEPT
    4086 {
    4087     Assert(((bUnmapInfo >> 4) & IEM_ACCESS_TYPE_MASK) == IEM_ACCESS_TYPE_WRITE);
    4088     iemMemRollbackAndUnmap(pVCpu, bUnmapInfo);
    4089 }
    4090 
    40911100#endif /* IEM_WITH_SETJMP */
    4092 
    4093 #ifndef IN_RING3
    4094 /**
    4095  * Commits the guest memory if bounce buffered and unmaps it, if any bounce
    4096  * buffer part shows trouble it will be postponed to ring-3 (sets FF and stuff).
    4097  *
    4098  * Allows the instruction to be completed and retired, while the IEM user will
    4099  * return to ring-3 immediately afterwards and do the postponed writes there.
    4100  *
    4101  * @returns VBox status code (no strict statuses).  Caller must check
    4102  *          VMCPU_FF_IEM before repeating string instructions and similar stuff.
    4103  * @param   pVCpu               The cross context virtual CPU structure of the calling thread.
    4104  * @param   pvMem               The mapping.
    4105  * @param   fAccess             The kind of access.
    4106  */
    4107 VBOXSTRICTRC iemMemCommitAndUnmapPostponeTroubleToR3(PVMCPUCC pVCpu, uint8_t bUnmapInfo) RT_NOEXCEPT
    4108 {
    4109     uintptr_t const iMemMap = bUnmapInfo & 0x7;
    4110     AssertMsgReturn(   (bUnmapInfo & 0x08)
    4111                     && iMemMap < RT_ELEMENTS(pVCpu->iem.s.aMemMappings)
    4112                     &&    (pVCpu->iem.s.aMemMappings[iMemMap].fAccess & (IEM_ACCESS_TYPE_MASK | 0xf))
    4113                        == ((unsigned)bUnmapInfo >> 4),
    4114                     ("%#x fAccess=%#x\n", bUnmapInfo, pVCpu->iem.s.aMemMappings[iMemMap].fAccess),
    4115                     VERR_NOT_FOUND);
    4116 
    4117     /* If it's bounce buffered, we may need to write back the buffer. */
    4118     if (pVCpu->iem.s.aMemMappings[iMemMap].fAccess & IEM_ACCESS_BOUNCE_BUFFERED)
    4119     {
    4120         if (pVCpu->iem.s.aMemMappings[iMemMap].fAccess & IEM_ACCESS_TYPE_WRITE)
    4121             return iemMemBounceBufferCommitAndUnmap(pVCpu, iMemMap, true /*fPostponeFail*/);
    4122     }
    4123     /* Otherwise unlock it. */
    4124     else if (!(pVCpu->iem.s.aMemMappings[iMemMap].fAccess & IEM_ACCESS_NOT_LOCKED))
    4125         PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), &pVCpu->iem.s.aMemMappingLocks[iMemMap].Lock);
    4126 
    4127     /* Free the entry. */
    4128     pVCpu->iem.s.aMemMappings[iMemMap].fAccess = IEM_ACCESS_INVALID;
    4129     Assert(pVCpu->iem.s.cActiveMappings != 0);
    4130     pVCpu->iem.s.cActiveMappings--;
    4131     return VINF_SUCCESS;
    4132 }
    4133 #endif
    4134 
    4135 
    4136 /**
    4137  * Rollbacks mappings, releasing page locks and such.
    4138  *
    4139  * The caller shall only call this after checking cActiveMappings.
    4140  *
    4141  * @param   pVCpu       The cross context virtual CPU structure of the calling thread.
    4142  */
    4143 void iemMemRollback(PVMCPUCC pVCpu) RT_NOEXCEPT
    4144 {
    4145     Assert(pVCpu->iem.s.cActiveMappings > 0);
    4146 
    4147     uint32_t iMemMap = RT_ELEMENTS(pVCpu->iem.s.aMemMappings);
    4148     while (iMemMap-- > 0)
    4149     {
    4150         uint32_t const fAccess = pVCpu->iem.s.aMemMappings[iMemMap].fAccess;
    4151         if (fAccess != IEM_ACCESS_INVALID)
    4152         {
    4153             AssertMsg(!(fAccess & ~IEM_ACCESS_VALID_MASK) && fAccess != 0, ("%#x\n", fAccess));
    4154             pVCpu->iem.s.aMemMappings[iMemMap].fAccess = IEM_ACCESS_INVALID;
    4155             if (!(fAccess & (IEM_ACCESS_BOUNCE_BUFFERED | IEM_ACCESS_NOT_LOCKED)))
    4156                 PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), &pVCpu->iem.s.aMemMappingLocks[iMemMap].Lock);
    4157             AssertMsg(pVCpu->iem.s.cActiveMappings > 0,
    4158                       ("iMemMap=%u fAccess=%#x pv=%p GCPhysFirst=%RGp GCPhysSecond=%RGp\n",
    4159                        iMemMap, fAccess, pVCpu->iem.s.aMemMappings[iMemMap].pv,
    4160                        pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysFirst, pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysSecond));
    4161             pVCpu->iem.s.cActiveMappings--;
    4162         }
    4163     }
    4164 }
    41651101
    41661102
     
    41741110#define TMPL_MEM_FMT_TYPE   "%#04x"
    41751111#define TMPL_MEM_FMT_DESC   "byte"
    4176 #include "IEMAllMemRWTmpl.cpp.h"
     1112#include "IEMAllMemRWTmpl-x86.cpp.h"
    41771113
    41781114#define TMPL_MEM_TYPE       uint16_t
     
    41801116#define TMPL_MEM_FMT_TYPE   "%#06x"
    41811117#define TMPL_MEM_FMT_DESC   "word"
    4182 #include "IEMAllMemRWTmpl.cpp.h"
     1118#include "IEMAllMemRWTmpl-x86.cpp.h"
    41831119
    41841120#define TMPL_WITH_PUSH_SREG
     
    41871123#define TMPL_MEM_FMT_TYPE   "%#010x"
    41881124#define TMPL_MEM_FMT_DESC   "dword"
    4189 #include "IEMAllMemRWTmpl.cpp.h"
     1125#include "IEMAllMemRWTmpl-x86.cpp.h"
    41901126#undef TMPL_WITH_PUSH_SREG
    41911127
     
    41941130#define TMPL_MEM_FMT_TYPE   "%#018RX64"
    41951131#define TMPL_MEM_FMT_DESC   "qword"
    4196 #include "IEMAllMemRWTmpl.cpp.h"
     1132#include "IEMAllMemRWTmpl-x86.cpp.h"
    41971133
    41981134#undef TMPL_MEM_WITH_STACK
     
    42031139#define TMPL_MEM_FMT_TYPE   "%#010x"
    42041140#define TMPL_MEM_FMT_DESC   "dword"
    4205 #include "IEMAllMemRWTmpl.cpp.h"
     1141#include "IEMAllMemRWTmpl-x86.cpp.h"
    42061142#undef TMPL_WITH_PUSH_SREG
    42071143
     
    42111147#define TMPL_MEM_FMT_TYPE   "%#018RX64"
    42121148#define TMPL_MEM_FMT_DESC   "qword"
    4213 #include "IEMAllMemRWTmpl.cpp.h"
     1149#include "IEMAllMemRWTmpl-x86.cpp.h"
    42141150
    42151151#define TMPL_MEM_TYPE       uint64_t
     
    42181154#define TMPL_MEM_FMT_TYPE   "%#018RX64"
    42191155#define TMPL_MEM_FMT_DESC   "qword"
    4220 #include "IEMAllMemRWTmpl.cpp.h"
     1156#include "IEMAllMemRWTmpl-x86.cpp.h"
    42211157
    42221158/* See IEMAllMemRWTmplInline.cpp.h */
     
    42281164#define TMPL_MEM_FMT_TYPE   "%.10Rhxs"
    42291165#define TMPL_MEM_FMT_DESC   "tword"
    4230 #include "IEMAllMemRWTmpl.cpp.h"
     1166#include "IEMAllMemRWTmpl-x86.cpp.h"
    42311167
    42321168#define TMPL_MEM_TYPE       RTPBCD80U
     
    42351171#define TMPL_MEM_FMT_TYPE   "%.10Rhxs"
    42361172#define TMPL_MEM_FMT_DESC   "tword"
    4237 #include "IEMAllMemRWTmpl.cpp.h"
     1173#include "IEMAllMemRWTmpl-x86.cpp.h"
    42381174
    42391175#define TMPL_MEM_TYPE       RTUINT128U
     
    42421178#define TMPL_MEM_FMT_TYPE   "%.16Rhxs"
    42431179#define TMPL_MEM_FMT_DESC   "dqword"
    4244 #include "IEMAllMemRWTmpl.cpp.h"
     1180#include "IEMAllMemRWTmpl-x86.cpp.h"
    42451181
    42461182#define TMPL_MEM_TYPE           RTUINT128U
     
    42501186#define TMPL_MEM_FMT_TYPE       "%.16Rhxs"
    42511187#define TMPL_MEM_FMT_DESC       "dqword"
    4252 #include "IEMAllMemRWTmpl.cpp.h"
     1188#include "IEMAllMemRWTmpl-x86.cpp.h"
    42531189
    42541190#define TMPL_MEM_TYPE       RTUINT128U
     
    42571193#define TMPL_MEM_FMT_TYPE   "%.16Rhxs"
    42581194#define TMPL_MEM_FMT_DESC   "dqword"
    4259 #include "IEMAllMemRWTmpl.cpp.h"
     1195#include "IEMAllMemRWTmpl-x86.cpp.h"
    42601196
    42611197#define TMPL_MEM_TYPE       RTUINT256U
     
    42641200#define TMPL_MEM_FMT_TYPE   "%.32Rhxs"
    42651201#define TMPL_MEM_FMT_DESC   "qqword"
    4266 #include "IEMAllMemRWTmpl.cpp.h"
     1202#include "IEMAllMemRWTmpl-x86.cpp.h"
    42671203
    42681204#define TMPL_MEM_TYPE           RTUINT256U
     
    42721208#define TMPL_MEM_FMT_TYPE       "%.32Rhxs"
    42731209#define TMPL_MEM_FMT_DESC       "qqword"
    4274 #include "IEMAllMemRWTmpl.cpp.h"
     1210#include "IEMAllMemRWTmpl-x86.cpp.h"
     1211
    42751212
    42761213/**
     
    49351872}
    49361873
    4937 
    4938 #undef  LOG_GROUP
    4939 #define LOG_GROUP LOG_GROUP_IEM
    4940 
    49411874/** @} */
    49421875
    4943 /** @name   Opcode Helpers.
    4944  * @{
    4945  */
    4946 
    4947 /**
    4948  * Calculates the effective address of a ModR/M memory operand.
    4949  *
    4950  * Meant to be used via IEM_MC_CALC_RM_EFF_ADDR.
    4951  *
    4952  * @return  Strict VBox status code.
    4953  * @param   pVCpu               The cross context virtual CPU structure of the calling thread.
    4954  * @param   bRm                 The ModRM byte.
    4955  * @param   cbImmAndRspOffset   - First byte: The size of any immediate
    4956  *                                following the effective address opcode bytes
    4957  *                                (only for RIP relative addressing).
    4958  *                              - Second byte: RSP displacement (for POP [ESP]).
    4959  * @param   pGCPtrEff           Where to return the effective address.
    4960  */
    4961 VBOXSTRICTRC iemOpHlpCalcRmEffAddr(PVMCPUCC pVCpu, uint8_t bRm, uint32_t cbImmAndRspOffset, PRTGCPTR pGCPtrEff) RT_NOEXCEPT
    4962 {
    4963     Log5(("iemOpHlpCalcRmEffAddr: bRm=%#x\n", bRm));
    4964 # define SET_SS_DEF() \
    4965     do \
    4966     { \
    4967         if (!(pVCpu->iem.s.fPrefixes & IEM_OP_PRF_SEG_MASK)) \
    4968             pVCpu->iem.s.iEffSeg = X86_SREG_SS; \
    4969     } while (0)
    4970 
    4971     if (!IEM_IS_64BIT_CODE(pVCpu))
    4972     {
    4973 /** @todo Check the effective address size crap! */
    4974         if (pVCpu->iem.s.enmEffAddrMode == IEMMODE_16BIT)
    4975         {
    4976             uint16_t u16EffAddr;
    4977 
    4978             /* Handle the disp16 form with no registers first. */
    4979             if ((bRm & (X86_MODRM_MOD_MASK | X86_MODRM_RM_MASK)) == 6)
    4980                 IEM_OPCODE_GET_NEXT_U16(&u16EffAddr);
    4981             else
    4982             {
    4983                 /* Get the displacment. */
    4984                 switch ((bRm >> X86_MODRM_MOD_SHIFT) & X86_MODRM_MOD_SMASK)
    4985                 {
    4986                     case 0:  u16EffAddr = 0;                             break;
    4987                     case 1:  IEM_OPCODE_GET_NEXT_S8_SX_U16(&u16EffAddr); break;
    4988                     case 2:  IEM_OPCODE_GET_NEXT_U16(&u16EffAddr);       break;
    4989                     default: AssertFailedReturn(VERR_IEM_IPE_1); /* (caller checked for these) */
    4990                 }
    4991 
    4992                 /* Add the base and index registers to the disp. */
    4993                 switch (bRm & X86_MODRM_RM_MASK)
    4994                 {
    4995                     case 0: u16EffAddr += pVCpu->cpum.GstCtx.bx + pVCpu->cpum.GstCtx.si; break;
    4996                     case 1: u16EffAddr += pVCpu->cpum.GstCtx.bx + pVCpu->cpum.GstCtx.di; break;
    4997                     case 2: u16EffAddr += pVCpu->cpum.GstCtx.bp + pVCpu->cpum.GstCtx.si; SET_SS_DEF(); break;
    4998                     case 3: u16EffAddr += pVCpu->cpum.GstCtx.bp + pVCpu->cpum.GstCtx.di; SET_SS_DEF(); break;
    4999                     case 4: u16EffAddr += pVCpu->cpum.GstCtx.si;            break;
    5000                     case 5: u16EffAddr += pVCpu->cpum.GstCtx.di;            break;
    5001                     case 6: u16EffAddr += pVCpu->cpum.GstCtx.bp;            SET_SS_DEF(); break;
    5002                     case 7: u16EffAddr += pVCpu->cpum.GstCtx.bx;            break;
    5003                 }
    5004             }
    5005 
    5006             *pGCPtrEff = u16EffAddr;
    5007         }
    5008         else
    5009         {
    5010             Assert(pVCpu->iem.s.enmEffAddrMode == IEMMODE_32BIT);
    5011             uint32_t u32EffAddr;
    5012 
    5013             /* Handle the disp32 form with no registers first. */
    5014             if ((bRm & (X86_MODRM_MOD_MASK | X86_MODRM_RM_MASK)) == 5)
    5015                 IEM_OPCODE_GET_NEXT_U32(&u32EffAddr);
    5016             else
    5017             {
    5018                 /* Get the register (or SIB) value. */
    5019                 switch ((bRm & X86_MODRM_RM_MASK))
    5020                 {
    5021                     case 0: u32EffAddr = pVCpu->cpum.GstCtx.eax; break;
    5022                     case 1: u32EffAddr = pVCpu->cpum.GstCtx.ecx; break;
    5023                     case 2: u32EffAddr = pVCpu->cpum.GstCtx.edx; break;
    5024                     case 3: u32EffAddr = pVCpu->cpum.GstCtx.ebx; break;
    5025                     case 4: /* SIB */
    5026                     {
    5027                         uint8_t bSib; IEM_OPCODE_GET_NEXT_U8(&bSib);
    5028 
    5029                         /* Get the index and scale it. */
    5030                         switch ((bSib >> X86_SIB_INDEX_SHIFT) & X86_SIB_INDEX_SMASK)
    5031                         {
    5032                             case 0: u32EffAddr = pVCpu->cpum.GstCtx.eax; break;
    5033                             case 1: u32EffAddr = pVCpu->cpum.GstCtx.ecx; break;
    5034                             case 2: u32EffAddr = pVCpu->cpum.GstCtx.edx; break;
    5035                             case 3: u32EffAddr = pVCpu->cpum.GstCtx.ebx; break;
    5036                             case 4: u32EffAddr = 0; /*none */ break;
    5037                             case 5: u32EffAddr = pVCpu->cpum.GstCtx.ebp; break;
    5038                             case 6: u32EffAddr = pVCpu->cpum.GstCtx.esi; break;
    5039                             case 7: u32EffAddr = pVCpu->cpum.GstCtx.edi; break;
    5040                             IEM_NOT_REACHED_DEFAULT_CASE_RET();
    5041                         }
    5042                         u32EffAddr <<= (bSib >> X86_SIB_SCALE_SHIFT) & X86_SIB_SCALE_SMASK;
    5043 
    5044                         /* add base */
    5045                         switch (bSib & X86_SIB_BASE_MASK)
    5046                         {
    5047                             case 0: u32EffAddr += pVCpu->cpum.GstCtx.eax; break;
    5048                             case 1: u32EffAddr += pVCpu->cpum.GstCtx.ecx; break;
    5049                             case 2: u32EffAddr += pVCpu->cpum.GstCtx.edx; break;
    5050                             case 3: u32EffAddr += pVCpu->cpum.GstCtx.ebx; break;
    5051                             case 4: u32EffAddr += pVCpu->cpum.GstCtx.esp + (cbImmAndRspOffset >> 8); SET_SS_DEF(); break;
    5052                             case 5:
    5053                                 if ((bRm & X86_MODRM_MOD_MASK) != 0)
    5054                                 {
    5055                                     u32EffAddr += pVCpu->cpum.GstCtx.ebp;
    5056                                     SET_SS_DEF();
    5057                                 }
    5058                                 else
    5059                                 {
    5060                                     uint32_t u32Disp;
    5061                                     IEM_OPCODE_GET_NEXT_U32(&u32Disp);
    5062                                     u32EffAddr += u32Disp;
    5063                                 }
    5064                                 break;
    5065                             case 6: u32EffAddr += pVCpu->cpum.GstCtx.esi; break;
    5066                             case 7: u32EffAddr += pVCpu->cpum.GstCtx.edi; break;
    5067                             IEM_NOT_REACHED_DEFAULT_CASE_RET();
    5068                         }
    5069                         break;
    5070                     }
    5071                     case 5: u32EffAddr = pVCpu->cpum.GstCtx.ebp; SET_SS_DEF(); break;
    5072                     case 6: u32EffAddr = pVCpu->cpum.GstCtx.esi; break;
    5073                     case 7: u32EffAddr = pVCpu->cpum.GstCtx.edi; break;
    5074                     IEM_NOT_REACHED_DEFAULT_CASE_RET();
    5075                 }
    5076 
    5077                 /* Get and add the displacement. */
    5078                 switch ((bRm >> X86_MODRM_MOD_SHIFT) & X86_MODRM_MOD_SMASK)
    5079                 {
    5080                     case 0:
    5081                         break;
    5082                     case 1:
    5083                     {
    5084                         int8_t i8Disp; IEM_OPCODE_GET_NEXT_S8(&i8Disp);
    5085                         u32EffAddr += i8Disp;
    5086                         break;
    5087                     }
    5088                     case 2:
    5089                     {
    5090                         uint32_t u32Disp; IEM_OPCODE_GET_NEXT_U32(&u32Disp);
    5091                         u32EffAddr += u32Disp;
    5092                         break;
    5093                     }
    5094                     default:
    5095                         AssertFailedReturn(VERR_IEM_IPE_2); /* (caller checked for these) */
    5096                 }
    5097 
    5098             }
    5099             Assert(pVCpu->iem.s.enmEffAddrMode == IEMMODE_32BIT);
    5100             *pGCPtrEff = u32EffAddr;
    5101         }
    5102     }
    5103     else
    5104     {
    5105         uint64_t u64EffAddr;
    5106 
    5107         /* Handle the rip+disp32 form with no registers first. */
    5108         if ((bRm & (X86_MODRM_MOD_MASK | X86_MODRM_RM_MASK)) == 5)
    5109         {
    5110             IEM_OPCODE_GET_NEXT_S32_SX_U64(&u64EffAddr);
    5111             u64EffAddr += pVCpu->cpum.GstCtx.rip + IEM_GET_INSTR_LEN(pVCpu) + (cbImmAndRspOffset & UINT32_C(0xff));
    5112         }
    5113         else
    5114         {
    5115             /* Get the register (or SIB) value. */
    5116             switch ((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB)
    5117             {
    5118                 case  0: u64EffAddr = pVCpu->cpum.GstCtx.rax; break;
    5119                 case  1: u64EffAddr = pVCpu->cpum.GstCtx.rcx; break;
    5120                 case  2: u64EffAddr = pVCpu->cpum.GstCtx.rdx; break;
    5121                 case  3: u64EffAddr = pVCpu->cpum.GstCtx.rbx; break;
    5122                 case  5: u64EffAddr = pVCpu->cpum.GstCtx.rbp; SET_SS_DEF(); break;
    5123                 case  6: u64EffAddr = pVCpu->cpum.GstCtx.rsi; break;
    5124                 case  7: u64EffAddr = pVCpu->cpum.GstCtx.rdi; break;
    5125                 case  8: u64EffAddr = pVCpu->cpum.GstCtx.r8;  break;
    5126                 case  9: u64EffAddr = pVCpu->cpum.GstCtx.r9;  break;
    5127                 case 10: u64EffAddr = pVCpu->cpum.GstCtx.r10; break;
    5128                 case 11: u64EffAddr = pVCpu->cpum.GstCtx.r11; break;
    5129                 case 13: u64EffAddr = pVCpu->cpum.GstCtx.r13; break;
    5130                 case 14: u64EffAddr = pVCpu->cpum.GstCtx.r14; break;
    5131                 case 15: u64EffAddr = pVCpu->cpum.GstCtx.r15; break;
    5132                 /* SIB */
    5133                 case 4:
    5134                 case 12:
    5135                 {
    5136                     uint8_t bSib; IEM_OPCODE_GET_NEXT_U8(&bSib);
    5137 
    5138                     /* Get the index and scale it. */
    5139                     switch (((bSib >> X86_SIB_INDEX_SHIFT) & X86_SIB_INDEX_SMASK) | pVCpu->iem.s.uRexIndex)
    5140                     {
    5141                         case  0: u64EffAddr = pVCpu->cpum.GstCtx.rax; break;
    5142                         case  1: u64EffAddr = pVCpu->cpum.GstCtx.rcx; break;
    5143                         case  2: u64EffAddr = pVCpu->cpum.GstCtx.rdx; break;
    5144                         case  3: u64EffAddr = pVCpu->cpum.GstCtx.rbx; break;
    5145                         case  4: u64EffAddr = 0; /*none */ break;
    5146                         case  5: u64EffAddr = pVCpu->cpum.GstCtx.rbp; break;
    5147                         case  6: u64EffAddr = pVCpu->cpum.GstCtx.rsi; break;
    5148                         case  7: u64EffAddr = pVCpu->cpum.GstCtx.rdi; break;
    5149                         case  8: u64EffAddr = pVCpu->cpum.GstCtx.r8;  break;
    5150                         case  9: u64EffAddr = pVCpu->cpum.GstCtx.r9;  break;
    5151                         case 10: u64EffAddr = pVCpu->cpum.GstCtx.r10; break;
    5152                         case 11: u64EffAddr = pVCpu->cpum.GstCtx.r11; break;
    5153                         case 12: u64EffAddr = pVCpu->cpum.GstCtx.r12; break;
    5154                         case 13: u64EffAddr = pVCpu->cpum.GstCtx.r13; break;
    5155                         case 14: u64EffAddr = pVCpu->cpum.GstCtx.r14; break;
    5156                         case 15: u64EffAddr = pVCpu->cpum.GstCtx.r15; break;
    5157                         IEM_NOT_REACHED_DEFAULT_CASE_RET();
    5158                     }
    5159                     u64EffAddr <<= (bSib >> X86_SIB_SCALE_SHIFT) & X86_SIB_SCALE_SMASK;
    5160 
    5161                     /* add base */
    5162                     switch ((bSib & X86_SIB_BASE_MASK) | pVCpu->iem.s.uRexB)
    5163                     {
    5164                         case  0: u64EffAddr += pVCpu->cpum.GstCtx.rax; break;
    5165                         case  1: u64EffAddr += pVCpu->cpum.GstCtx.rcx; break;
    5166                         case  2: u64EffAddr += pVCpu->cpum.GstCtx.rdx; break;
    5167                         case  3: u64EffAddr += pVCpu->cpum.GstCtx.rbx; break;
    5168                         case  4: u64EffAddr += pVCpu->cpum.GstCtx.rsp + (cbImmAndRspOffset >> 8); SET_SS_DEF(); break;
    5169                         case  6: u64EffAddr += pVCpu->cpum.GstCtx.rsi; break;
    5170                         case  7: u64EffAddr += pVCpu->cpum.GstCtx.rdi; break;
    5171                         case  8: u64EffAddr += pVCpu->cpum.GstCtx.r8;  break;
    5172                         case  9: u64EffAddr += pVCpu->cpum.GstCtx.r9;  break;
    5173                         case 10: u64EffAddr += pVCpu->cpum.GstCtx.r10; break;
    5174                         case 11: u64EffAddr += pVCpu->cpum.GstCtx.r11; break;
    5175                         case 12: u64EffAddr += pVCpu->cpum.GstCtx.r12; break;
    5176                         case 14: u64EffAddr += pVCpu->cpum.GstCtx.r14; break;
    5177                         case 15: u64EffAddr += pVCpu->cpum.GstCtx.r15; break;
    5178                         /* complicated encodings */
    5179                         case 5:
    5180                         case 13:
    5181                             if ((bRm & X86_MODRM_MOD_MASK) != 0)
    5182                             {
    5183                                 if (!pVCpu->iem.s.uRexB)
    5184                                 {
    5185                                     u64EffAddr += pVCpu->cpum.GstCtx.rbp;
    5186                                     SET_SS_DEF();
    5187                                 }
    5188                                 else
    5189                                     u64EffAddr += pVCpu->cpum.GstCtx.r13;
    5190                             }
    5191                             else
    5192                             {
    5193                                 uint32_t u32Disp;
    5194                                 IEM_OPCODE_GET_NEXT_U32(&u32Disp);
    5195                                 u64EffAddr += (int32_t)u32Disp;
    5196                             }
    5197                             break;
    5198                         IEM_NOT_REACHED_DEFAULT_CASE_RET();
    5199                     }
    5200                     break;
    5201                 }
    5202                 IEM_NOT_REACHED_DEFAULT_CASE_RET();
    5203             }
    5204 
    5205             /* Get and add the displacement. */
    5206             switch ((bRm >> X86_MODRM_MOD_SHIFT) & X86_MODRM_MOD_SMASK)
    5207             {
    5208                 case 0:
    5209                     break;
    5210                 case 1:
    5211                 {
    5212                     int8_t i8Disp;
    5213                     IEM_OPCODE_GET_NEXT_S8(&i8Disp);
    5214                     u64EffAddr += i8Disp;
    5215                     break;
    5216                 }
    5217                 case 2:
    5218                 {
    5219                     uint32_t u32Disp;
    5220                     IEM_OPCODE_GET_NEXT_U32(&u32Disp);
    5221                     u64EffAddr += (int32_t)u32Disp;
    5222                     break;
    5223                 }
    5224                 IEM_NOT_REACHED_DEFAULT_CASE_RET(); /* (caller checked for these) */
    5225             }
    5226 
    5227         }
    5228 
    5229         if (pVCpu->iem.s.enmEffAddrMode == IEMMODE_64BIT)
    5230             *pGCPtrEff = u64EffAddr;
    5231         else
    5232         {
    5233             Assert(pVCpu->iem.s.enmEffAddrMode == IEMMODE_32BIT);
    5234             *pGCPtrEff = u64EffAddr & UINT32_MAX;
    5235         }
    5236     }
    5237 
    5238     Log5(("iemOpHlpCalcRmEffAddr: EffAddr=%#010RGv\n", *pGCPtrEff));
    5239     return VINF_SUCCESS;
    5240 }
    5241 
    5242 
    5243 #ifdef IEM_WITH_SETJMP
    5244 /**
    5245  * Calculates the effective address of a ModR/M memory operand.
    5246  *
    5247  * Meant to be used via IEM_MC_CALC_RM_EFF_ADDR.
    5248  *
    5249  * May longjmp on internal error.
    5250  *
    5251  * @return  The effective address.
    5252  * @param   pVCpu               The cross context virtual CPU structure of the calling thread.
    5253  * @param   bRm                 The ModRM byte.
    5254  * @param   cbImmAndRspOffset   - First byte: The size of any immediate
    5255  *                                following the effective address opcode bytes
    5256  *                                (only for RIP relative addressing).
    5257  *                              - Second byte: RSP displacement (for POP [ESP]).
    5258  */
    5259 RTGCPTR iemOpHlpCalcRmEffAddrJmp(PVMCPUCC pVCpu, uint8_t bRm, uint32_t cbImmAndRspOffset) IEM_NOEXCEPT_MAY_LONGJMP
    5260 {
    5261     Log5(("iemOpHlpCalcRmEffAddrJmp: bRm=%#x\n", bRm));
    5262 # define SET_SS_DEF() \
    5263     do \
    5264     { \
    5265         if (!(pVCpu->iem.s.fPrefixes & IEM_OP_PRF_SEG_MASK)) \
    5266             pVCpu->iem.s.iEffSeg = X86_SREG_SS; \
    5267     } while (0)
    5268 
    5269     if (!IEM_IS_64BIT_CODE(pVCpu))
    5270     {
    5271 /** @todo Check the effective address size crap! */
    5272         if (pVCpu->iem.s.enmEffAddrMode == IEMMODE_16BIT)
    5273         {
    5274             uint16_t u16EffAddr;
    5275 
    5276             /* Handle the disp16 form with no registers first. */
    5277             if ((bRm & (X86_MODRM_MOD_MASK | X86_MODRM_RM_MASK)) == 6)
    5278                 IEM_OPCODE_GET_NEXT_U16(&u16EffAddr);
    5279             else
    5280             {
    5281                 /* Get the displacment. */
    5282                 switch ((bRm >> X86_MODRM_MOD_SHIFT) & X86_MODRM_MOD_SMASK)
    5283                 {
    5284                     case 0:  u16EffAddr = 0;                             break;
    5285                     case 1:  IEM_OPCODE_GET_NEXT_S8_SX_U16(&u16EffAddr); break;
    5286                     case 2:  IEM_OPCODE_GET_NEXT_U16(&u16EffAddr);       break;
    5287                     default: AssertFailedStmt(IEM_DO_LONGJMP(pVCpu, VERR_IEM_IPE_1)); /* (caller checked for these) */
    5288                 }
    5289 
    5290                 /* Add the base and index registers to the disp. */
    5291                 switch (bRm & X86_MODRM_RM_MASK)
    5292                 {
    5293                     case 0: u16EffAddr += pVCpu->cpum.GstCtx.bx + pVCpu->cpum.GstCtx.si; break;
    5294                     case 1: u16EffAddr += pVCpu->cpum.GstCtx.bx + pVCpu->cpum.GstCtx.di; break;
    5295                     case 2: u16EffAddr += pVCpu->cpum.GstCtx.bp + pVCpu->cpum.GstCtx.si; SET_SS_DEF(); break;
    5296                     case 3: u16EffAddr += pVCpu->cpum.GstCtx.bp + pVCpu->cpum.GstCtx.di; SET_SS_DEF(); break;
    5297                     case 4: u16EffAddr += pVCpu->cpum.GstCtx.si;            break;
    5298                     case 5: u16EffAddr += pVCpu->cpum.GstCtx.di;            break;
    5299                     case 6: u16EffAddr += pVCpu->cpum.GstCtx.bp;            SET_SS_DEF(); break;
    5300                     case 7: u16EffAddr += pVCpu->cpum.GstCtx.bx;            break;
    5301                 }
    5302             }
    5303 
    5304             Log5(("iemOpHlpCalcRmEffAddrJmp: EffAddr=%#06RX16\n", u16EffAddr));
    5305             return u16EffAddr;
    5306         }
    5307 
    5308         Assert(pVCpu->iem.s.enmEffAddrMode == IEMMODE_32BIT);
    5309         uint32_t u32EffAddr;
    5310 
    5311         /* Handle the disp32 form with no registers first. */
    5312         if ((bRm & (X86_MODRM_MOD_MASK | X86_MODRM_RM_MASK)) == 5)
    5313             IEM_OPCODE_GET_NEXT_U32(&u32EffAddr);
    5314         else
    5315         {
    5316             /* Get the register (or SIB) value. */
    5317             switch ((bRm & X86_MODRM_RM_MASK))
    5318             {
    5319                 case 0: u32EffAddr = pVCpu->cpum.GstCtx.eax; break;
    5320                 case 1: u32EffAddr = pVCpu->cpum.GstCtx.ecx; break;
    5321                 case 2: u32EffAddr = pVCpu->cpum.GstCtx.edx; break;
    5322                 case 3: u32EffAddr = pVCpu->cpum.GstCtx.ebx; break;
    5323                 case 4: /* SIB */
    5324                 {
    5325                     uint8_t bSib; IEM_OPCODE_GET_NEXT_U8(&bSib);
    5326 
    5327                     /* Get the index and scale it. */
    5328                     switch ((bSib >> X86_SIB_INDEX_SHIFT) & X86_SIB_INDEX_SMASK)
    5329                     {
    5330                         case 0: u32EffAddr = pVCpu->cpum.GstCtx.eax; break;
    5331                         case 1: u32EffAddr = pVCpu->cpum.GstCtx.ecx; break;
    5332                         case 2: u32EffAddr = pVCpu->cpum.GstCtx.edx; break;
    5333                         case 3: u32EffAddr = pVCpu->cpum.GstCtx.ebx; break;
    5334                         case 4: u32EffAddr = 0; /*none */ break;
    5335                         case 5: u32EffAddr = pVCpu->cpum.GstCtx.ebp; break;
    5336                         case 6: u32EffAddr = pVCpu->cpum.GstCtx.esi; break;
    5337                         case 7: u32EffAddr = pVCpu->cpum.GstCtx.edi; break;
    5338                         IEM_NOT_REACHED_DEFAULT_CASE_RET2(RTGCPTR_MAX);
    5339                     }
    5340                     u32EffAddr <<= (bSib >> X86_SIB_SCALE_SHIFT) & X86_SIB_SCALE_SMASK;
    5341 
    5342                     /* add base */
    5343                     switch (bSib & X86_SIB_BASE_MASK)
    5344                     {
    5345                         case 0: u32EffAddr += pVCpu->cpum.GstCtx.eax; break;
    5346                         case 1: u32EffAddr += pVCpu->cpum.GstCtx.ecx; break;
    5347                         case 2: u32EffAddr += pVCpu->cpum.GstCtx.edx; break;
    5348                         case 3: u32EffAddr += pVCpu->cpum.GstCtx.ebx; break;
    5349                         case 4: u32EffAddr += pVCpu->cpum.GstCtx.esp + (cbImmAndRspOffset >> 8); SET_SS_DEF(); break;
    5350                         case 5:
    5351                             if ((bRm & X86_MODRM_MOD_MASK) != 0)
    5352                             {
    5353                                 u32EffAddr += pVCpu->cpum.GstCtx.ebp;
    5354                                 SET_SS_DEF();
    5355                             }
    5356                             else
    5357                             {
    5358                                 uint32_t u32Disp;
    5359                                 IEM_OPCODE_GET_NEXT_U32(&u32Disp);
    5360                                 u32EffAddr += u32Disp;
    5361                             }
    5362                             break;
    5363                         case 6: u32EffAddr += pVCpu->cpum.GstCtx.esi; break;
    5364                         case 7: u32EffAddr += pVCpu->cpum.GstCtx.edi; break;
    5365                         IEM_NOT_REACHED_DEFAULT_CASE_RET2(RTGCPTR_MAX);
    5366                     }
    5367                     break;
    5368                 }
    5369                 case 5: u32EffAddr = pVCpu->cpum.GstCtx.ebp; SET_SS_DEF(); break;
    5370                 case 6: u32EffAddr = pVCpu->cpum.GstCtx.esi; break;
    5371                 case 7: u32EffAddr = pVCpu->cpum.GstCtx.edi; break;
    5372                 IEM_NOT_REACHED_DEFAULT_CASE_RET2(RTGCPTR_MAX);
    5373             }
    5374 
    5375             /* Get and add the displacement. */
    5376             switch ((bRm >> X86_MODRM_MOD_SHIFT) & X86_MODRM_MOD_SMASK)
    5377             {
    5378                 case 0:
    5379                     break;
    5380                 case 1:
    5381                 {
    5382                     int8_t i8Disp; IEM_OPCODE_GET_NEXT_S8(&i8Disp);
    5383                     u32EffAddr += i8Disp;
    5384                     break;
    5385                 }
    5386                 case 2:
    5387                 {
    5388                     uint32_t u32Disp; IEM_OPCODE_GET_NEXT_U32(&u32Disp);
    5389                     u32EffAddr += u32Disp;
    5390                     break;
    5391                 }
    5392                 default:
    5393                     AssertFailedStmt(IEM_DO_LONGJMP(pVCpu, VERR_IEM_IPE_2)); /* (caller checked for these) */
    5394             }
    5395         }
    5396 
    5397         Assert(pVCpu->iem.s.enmEffAddrMode == IEMMODE_32BIT);
    5398         Log5(("iemOpHlpCalcRmEffAddrJmp: EffAddr=%#010RX32\n", u32EffAddr));
    5399         return u32EffAddr;
    5400     }
    5401 
    5402     uint64_t u64EffAddr;
    5403 
    5404     /* Handle the rip+disp32 form with no registers first. */
    5405     if ((bRm & (X86_MODRM_MOD_MASK | X86_MODRM_RM_MASK)) == 5)
    5406     {
    5407         IEM_OPCODE_GET_NEXT_S32_SX_U64(&u64EffAddr);
    5408         u64EffAddr += pVCpu->cpum.GstCtx.rip + IEM_GET_INSTR_LEN(pVCpu) + (cbImmAndRspOffset & UINT32_C(0xff));
    5409     }
    5410     else
    5411     {
    5412         /* Get the register (or SIB) value. */
    5413         switch ((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB)
    5414         {
    5415             case  0: u64EffAddr = pVCpu->cpum.GstCtx.rax; break;
    5416             case  1: u64EffAddr = pVCpu->cpum.GstCtx.rcx; break;
    5417             case  2: u64EffAddr = pVCpu->cpum.GstCtx.rdx; break;
    5418             case  3: u64EffAddr = pVCpu->cpum.GstCtx.rbx; break;
    5419             case  5: u64EffAddr = pVCpu->cpum.GstCtx.rbp; SET_SS_DEF(); break;
    5420             case  6: u64EffAddr = pVCpu->cpum.GstCtx.rsi; break;
    5421             case  7: u64EffAddr = pVCpu->cpum.GstCtx.rdi; break;
    5422             case  8: u64EffAddr = pVCpu->cpum.GstCtx.r8;  break;
    5423             case  9: u64EffAddr = pVCpu->cpum.GstCtx.r9;  break;
    5424             case 10: u64EffAddr = pVCpu->cpum.GstCtx.r10; break;
    5425             case 11: u64EffAddr = pVCpu->cpum.GstCtx.r11; break;
    5426             case 13: u64EffAddr = pVCpu->cpum.GstCtx.r13; break;
    5427             case 14: u64EffAddr = pVCpu->cpum.GstCtx.r14; break;
    5428             case 15: u64EffAddr = pVCpu->cpum.GstCtx.r15; break;
    5429             /* SIB */
    5430             case 4:
    5431             case 12:
    5432             {
    5433                 uint8_t bSib; IEM_OPCODE_GET_NEXT_U8(&bSib);
    5434 
    5435                 /* Get the index and scale it. */
    5436                 switch (((bSib >> X86_SIB_INDEX_SHIFT) & X86_SIB_INDEX_SMASK) | pVCpu->iem.s.uRexIndex)
    5437                 {
    5438                     case  0: u64EffAddr = pVCpu->cpum.GstCtx.rax; break;
    5439                     case  1: u64EffAddr = pVCpu->cpum.GstCtx.rcx; break;
    5440                     case  2: u64EffAddr = pVCpu->cpum.GstCtx.rdx; break;
    5441                     case  3: u64EffAddr = pVCpu->cpum.GstCtx.rbx; break;
    5442                     case  4: u64EffAddr = 0; /*none */ break;
    5443                     case  5: u64EffAddr = pVCpu->cpum.GstCtx.rbp; break;
    5444                     case  6: u64EffAddr = pVCpu->cpum.GstCtx.rsi; break;
    5445                     case  7: u64EffAddr = pVCpu->cpum.GstCtx.rdi; break;
    5446                     case  8: u64EffAddr = pVCpu->cpum.GstCtx.r8;  break;
    5447                     case  9: u64EffAddr = pVCpu->cpum.GstCtx.r9;  break;
    5448                     case 10: u64EffAddr = pVCpu->cpum.GstCtx.r10; break;
    5449                     case 11: u64EffAddr = pVCpu->cpum.GstCtx.r11; break;
    5450                     case 12: u64EffAddr = pVCpu->cpum.GstCtx.r12; break;
    5451                     case 13: u64EffAddr = pVCpu->cpum.GstCtx.r13; break;
    5452                     case 14: u64EffAddr = pVCpu->cpum.GstCtx.r14; break;
    5453                     case 15: u64EffAddr = pVCpu->cpum.GstCtx.r15; break;
    5454                     IEM_NOT_REACHED_DEFAULT_CASE_RET2(RTGCPTR_MAX);
    5455                 }
    5456                 u64EffAddr <<= (bSib >> X86_SIB_SCALE_SHIFT) & X86_SIB_SCALE_SMASK;
    5457 
    5458                 /* add base */
    5459                 switch ((bSib & X86_SIB_BASE_MASK) | pVCpu->iem.s.uRexB)
    5460                 {
    5461                     case  0: u64EffAddr += pVCpu->cpum.GstCtx.rax; break;
    5462                     case  1: u64EffAddr += pVCpu->cpum.GstCtx.rcx; break;
    5463                     case  2: u64EffAddr += pVCpu->cpum.GstCtx.rdx; break;
    5464                     case  3: u64EffAddr += pVCpu->cpum.GstCtx.rbx; break;
    5465                     case  4: u64EffAddr += pVCpu->cpum.GstCtx.rsp + (cbImmAndRspOffset >> 8); SET_SS_DEF(); break;
    5466                     case  6: u64EffAddr += pVCpu->cpum.GstCtx.rsi; break;
    5467                     case  7: u64EffAddr += pVCpu->cpum.GstCtx.rdi; break;
    5468                     case  8: u64EffAddr += pVCpu->cpum.GstCtx.r8;  break;
    5469                     case  9: u64EffAddr += pVCpu->cpum.GstCtx.r9;  break;
    5470                     case 10: u64EffAddr += pVCpu->cpum.GstCtx.r10; break;
    5471                     case 11: u64EffAddr += pVCpu->cpum.GstCtx.r11; break;
    5472                     case 12: u64EffAddr += pVCpu->cpum.GstCtx.r12; break;
    5473                     case 14: u64EffAddr += pVCpu->cpum.GstCtx.r14; break;
    5474                     case 15: u64EffAddr += pVCpu->cpum.GstCtx.r15; break;
    5475                     /* complicated encodings */
    5476                     case 5:
    5477                     case 13:
    5478                         if ((bRm & X86_MODRM_MOD_MASK) != 0)
    5479                         {
    5480                             if (!pVCpu->iem.s.uRexB)
    5481                             {
    5482                                 u64EffAddr += pVCpu->cpum.GstCtx.rbp;
    5483                                 SET_SS_DEF();
    5484                             }
    5485                             else
    5486                                 u64EffAddr += pVCpu->cpum.GstCtx.r13;
    5487                         }
    5488                         else
    5489                         {
    5490                             uint32_t u32Disp;
    5491                             IEM_OPCODE_GET_NEXT_U32(&u32Disp);
    5492                             u64EffAddr += (int32_t)u32Disp;
    5493                         }
    5494                         break;
    5495                     IEM_NOT_REACHED_DEFAULT_CASE_RET2(RTGCPTR_MAX);
    5496                 }
    5497                 break;
    5498             }
    5499             IEM_NOT_REACHED_DEFAULT_CASE_RET2(RTGCPTR_MAX);
    5500         }
    5501 
    5502         /* Get and add the displacement. */
    5503         switch ((bRm >> X86_MODRM_MOD_SHIFT) & X86_MODRM_MOD_SMASK)
    5504         {
    5505             case 0:
    5506                 break;
    5507             case 1:
    5508             {
    5509                 int8_t i8Disp;
    5510                 IEM_OPCODE_GET_NEXT_S8(&i8Disp);
    5511                 u64EffAddr += i8Disp;
    5512                 break;
    5513             }
    5514             case 2:
    5515             {
    5516                 uint32_t u32Disp;
    5517                 IEM_OPCODE_GET_NEXT_U32(&u32Disp);
    5518                 u64EffAddr += (int32_t)u32Disp;
    5519                 break;
    5520             }
    5521             IEM_NOT_REACHED_DEFAULT_CASE_RET2(RTGCPTR_MAX); /* (caller checked for these) */
    5522         }
    5523 
    5524     }
    5525 
    5526     if (pVCpu->iem.s.enmEffAddrMode == IEMMODE_64BIT)
    5527     {
    5528         Log5(("iemOpHlpCalcRmEffAddrJmp: EffAddr=%#010RGv\n", u64EffAddr));
    5529         return u64EffAddr;
    5530     }
    5531     Assert(pVCpu->iem.s.enmEffAddrMode == IEMMODE_32BIT);
    5532     Log5(("iemOpHlpCalcRmEffAddrJmp: EffAddr=%#010RGv\n", u64EffAddr & UINT32_MAX));
    5533     return u64EffAddr & UINT32_MAX;
    5534 }
    5535 #endif /* IEM_WITH_SETJMP */
    5536 
    5537 
    5538 /**
    5539  * Calculates the effective address of a ModR/M memory operand, extended version
    5540  * for use in the recompilers.
    5541  *
    5542  * Meant to be used via IEM_MC_CALC_RM_EFF_ADDR.
    5543  *
    5544  * @return  Strict VBox status code.
    5545  * @param   pVCpu               The cross context virtual CPU structure of the calling thread.
    5546  * @param   bRm                 The ModRM byte.
    5547  * @param   cbImmAndRspOffset   - First byte: The size of any immediate
    5548  *                                following the effective address opcode bytes
    5549  *                                (only for RIP relative addressing).
    5550  *                              - Second byte: RSP displacement (for POP [ESP]).
    5551  * @param   pGCPtrEff           Where to return the effective address.
    5552  * @param   puInfo              Extra info: 32-bit displacement (bits 31:0) and
    5553  *                              SIB byte (bits 39:32).
    5554  */
    5555 VBOXSTRICTRC iemOpHlpCalcRmEffAddrEx(PVMCPUCC pVCpu, uint8_t bRm, uint32_t cbImmAndRspOffset, PRTGCPTR pGCPtrEff, uint64_t *puInfo) RT_NOEXCEPT
    5556 {
    5557     Log5(("iemOpHlpCalcRmEffAddr: bRm=%#x\n", bRm));
    5558 # define SET_SS_DEF() \
    5559     do \
    5560     { \
    5561         if (!(pVCpu->iem.s.fPrefixes & IEM_OP_PRF_SEG_MASK)) \
    5562             pVCpu->iem.s.iEffSeg = X86_SREG_SS; \
    5563     } while (0)
    5564 
    5565     uint64_t uInfo;
    5566     if (!IEM_IS_64BIT_CODE(pVCpu))
    5567     {
    5568 /** @todo Check the effective address size crap! */
    5569         if (pVCpu->iem.s.enmEffAddrMode == IEMMODE_16BIT)
    5570         {
    5571             uint16_t u16EffAddr;
    5572 
    5573             /* Handle the disp16 form with no registers first. */
    5574             if ((bRm & (X86_MODRM_MOD_MASK | X86_MODRM_RM_MASK)) == 6)
    5575             {
    5576                 IEM_OPCODE_GET_NEXT_U16(&u16EffAddr);
    5577                 uInfo = u16EffAddr;
    5578             }
    5579             else
    5580             {
    5581                 /* Get the displacment. */
    5582                 switch ((bRm >> X86_MODRM_MOD_SHIFT) & X86_MODRM_MOD_SMASK)
    5583                 {
    5584                     case 0:  u16EffAddr = 0;                             break;
    5585                     case 1:  IEM_OPCODE_GET_NEXT_S8_SX_U16(&u16EffAddr); break;
    5586                     case 2:  IEM_OPCODE_GET_NEXT_U16(&u16EffAddr);       break;
    5587                     default: AssertFailedReturn(VERR_IEM_IPE_1); /* (caller checked for these) */
    5588                 }
    5589                 uInfo = u16EffAddr;
    5590 
    5591                 /* Add the base and index registers to the disp. */
    5592                 switch (bRm & X86_MODRM_RM_MASK)
    5593                 {
    5594                     case 0: u16EffAddr += pVCpu->cpum.GstCtx.bx + pVCpu->cpum.GstCtx.si; break;
    5595                     case 1: u16EffAddr += pVCpu->cpum.GstCtx.bx + pVCpu->cpum.GstCtx.di; break;
    5596                     case 2: u16EffAddr += pVCpu->cpum.GstCtx.bp + pVCpu->cpum.GstCtx.si; SET_SS_DEF(); break;
    5597                     case 3: u16EffAddr += pVCpu->cpum.GstCtx.bp + pVCpu->cpum.GstCtx.di; SET_SS_DEF(); break;
    5598                     case 4: u16EffAddr += pVCpu->cpum.GstCtx.si;            break;
    5599                     case 5: u16EffAddr += pVCpu->cpum.GstCtx.di;            break;
    5600                     case 6: u16EffAddr += pVCpu->cpum.GstCtx.bp;            SET_SS_DEF(); break;
    5601                     case 7: u16EffAddr += pVCpu->cpum.GstCtx.bx;            break;
    5602                 }
    5603             }
    5604 
    5605             *pGCPtrEff = u16EffAddr;
    5606         }
    5607         else
    5608         {
    5609             Assert(pVCpu->iem.s.enmEffAddrMode == IEMMODE_32BIT);
    5610             uint32_t u32EffAddr;
    5611 
    5612             /* Handle the disp32 form with no registers first. */
    5613             if ((bRm & (X86_MODRM_MOD_MASK | X86_MODRM_RM_MASK)) == 5)
    5614             {
    5615                 IEM_OPCODE_GET_NEXT_U32(&u32EffAddr);
    5616                 uInfo = u32EffAddr;
    5617             }
    5618             else
    5619             {
    5620                 /* Get the register (or SIB) value. */
    5621                 uInfo = 0;
    5622                 switch ((bRm & X86_MODRM_RM_MASK))
    5623                 {
    5624                     case 0: u32EffAddr = pVCpu->cpum.GstCtx.eax; break;
    5625                     case 1: u32EffAddr = pVCpu->cpum.GstCtx.ecx; break;
    5626                     case 2: u32EffAddr = pVCpu->cpum.GstCtx.edx; break;
    5627                     case 3: u32EffAddr = pVCpu->cpum.GstCtx.ebx; break;
    5628                     case 4: /* SIB */
    5629                     {
    5630                         uint8_t bSib; IEM_OPCODE_GET_NEXT_U8(&bSib);
    5631                         uInfo = (uint64_t)bSib << 32;
    5632 
    5633                         /* Get the index and scale it. */
    5634                         switch ((bSib >> X86_SIB_INDEX_SHIFT) & X86_SIB_INDEX_SMASK)
    5635                         {
    5636                             case 0: u32EffAddr = pVCpu->cpum.GstCtx.eax; break;
    5637                             case 1: u32EffAddr = pVCpu->cpum.GstCtx.ecx; break;
    5638                             case 2: u32EffAddr = pVCpu->cpum.GstCtx.edx; break;
    5639                             case 3: u32EffAddr = pVCpu->cpum.GstCtx.ebx; break;
    5640                             case 4: u32EffAddr = 0; /*none */ break;
    5641                             case 5: u32EffAddr = pVCpu->cpum.GstCtx.ebp; break;
    5642                             case 6: u32EffAddr = pVCpu->cpum.GstCtx.esi; break;
    5643                             case 7: u32EffAddr = pVCpu->cpum.GstCtx.edi; break;
    5644                             IEM_NOT_REACHED_DEFAULT_CASE_RET();
    5645                         }
    5646                         u32EffAddr <<= (bSib >> X86_SIB_SCALE_SHIFT) & X86_SIB_SCALE_SMASK;
    5647 
    5648                         /* add base */
    5649                         switch (bSib & X86_SIB_BASE_MASK)
    5650                         {
    5651                             case 0: u32EffAddr += pVCpu->cpum.GstCtx.eax; break;
    5652                             case 1: u32EffAddr += pVCpu->cpum.GstCtx.ecx; break;
    5653                             case 2: u32EffAddr += pVCpu->cpum.GstCtx.edx; break;
    5654                             case 3: u32EffAddr += pVCpu->cpum.GstCtx.ebx; break;
    5655                             case 4: u32EffAddr += pVCpu->cpum.GstCtx.esp + (cbImmAndRspOffset >> 8); SET_SS_DEF(); break;
    5656                             case 5:
    5657                                 if ((bRm & X86_MODRM_MOD_MASK) != 0)
    5658                                 {
    5659                                     u32EffAddr += pVCpu->cpum.GstCtx.ebp;
    5660                                     SET_SS_DEF();
    5661                                 }
    5662                                 else
    5663                                 {
    5664                                     uint32_t u32Disp;
    5665                                     IEM_OPCODE_GET_NEXT_U32(&u32Disp);
    5666                                     u32EffAddr += u32Disp;
    5667                                     uInfo      |= u32Disp;
    5668                                 }
    5669                                 break;
    5670                             case 6: u32EffAddr += pVCpu->cpum.GstCtx.esi; break;
    5671                             case 7: u32EffAddr += pVCpu->cpum.GstCtx.edi; break;
    5672                             IEM_NOT_REACHED_DEFAULT_CASE_RET();
    5673                         }
    5674                         break;
    5675                     }
    5676                     case 5: u32EffAddr = pVCpu->cpum.GstCtx.ebp; SET_SS_DEF(); break;
    5677                     case 6: u32EffAddr = pVCpu->cpum.GstCtx.esi; break;
    5678                     case 7: u32EffAddr = pVCpu->cpum.GstCtx.edi; break;
    5679                     IEM_NOT_REACHED_DEFAULT_CASE_RET();
    5680                 }
    5681 
    5682                 /* Get and add the displacement. */
    5683                 switch ((bRm >> X86_MODRM_MOD_SHIFT) & X86_MODRM_MOD_SMASK)
    5684                 {
    5685                     case 0:
    5686                         break;
    5687                     case 1:
    5688                     {
    5689                         int8_t i8Disp; IEM_OPCODE_GET_NEXT_S8(&i8Disp);
    5690                         u32EffAddr += i8Disp;
    5691                         uInfo |= (uint32_t)(int32_t)i8Disp;
    5692                         break;
    5693                     }
    5694                     case 2:
    5695                     {
    5696                         uint32_t u32Disp; IEM_OPCODE_GET_NEXT_U32(&u32Disp);
    5697                         u32EffAddr += u32Disp;
    5698                         uInfo      |= (uint32_t)u32Disp;
    5699                         break;
    5700                     }
    5701                     default:
    5702                         AssertFailedReturn(VERR_IEM_IPE_2); /* (caller checked for these) */
    5703                 }
    5704 
    5705             }
    5706             Assert(pVCpu->iem.s.enmEffAddrMode == IEMMODE_32BIT);
    5707             *pGCPtrEff = u32EffAddr;
    5708         }
    5709     }
    5710     else
    5711     {
    5712         uint64_t u64EffAddr;
    5713 
    5714         /* Handle the rip+disp32 form with no registers first. */
    5715         if ((bRm & (X86_MODRM_MOD_MASK | X86_MODRM_RM_MASK)) == 5)
    5716         {
    5717             IEM_OPCODE_GET_NEXT_S32_SX_U64(&u64EffAddr);
    5718             uInfo = (uint32_t)u64EffAddr;
    5719             u64EffAddr += pVCpu->cpum.GstCtx.rip + IEM_GET_INSTR_LEN(pVCpu) + (cbImmAndRspOffset & UINT32_C(0xff));
    5720         }
    5721         else
    5722         {
    5723             /* Get the register (or SIB) value. */
    5724             uInfo = 0;
    5725             switch ((bRm & X86_MODRM_RM_MASK) | pVCpu->iem.s.uRexB)
    5726             {
    5727                 case  0: u64EffAddr = pVCpu->cpum.GstCtx.rax; break;
    5728                 case  1: u64EffAddr = pVCpu->cpum.GstCtx.rcx; break;
    5729                 case  2: u64EffAddr = pVCpu->cpum.GstCtx.rdx; break;
    5730                 case  3: u64EffAddr = pVCpu->cpum.GstCtx.rbx; break;
    5731                 case  5: u64EffAddr = pVCpu->cpum.GstCtx.rbp; SET_SS_DEF(); break;
    5732                 case  6: u64EffAddr = pVCpu->cpum.GstCtx.rsi; break;
    5733                 case  7: u64EffAddr = pVCpu->cpum.GstCtx.rdi; break;
    5734                 case  8: u64EffAddr = pVCpu->cpum.GstCtx.r8;  break;
    5735                 case  9: u64EffAddr = pVCpu->cpum.GstCtx.r9;  break;
    5736                 case 10: u64EffAddr = pVCpu->cpum.GstCtx.r10; break;
    5737                 case 11: u64EffAddr = pVCpu->cpum.GstCtx.r11; break;
    5738                 case 13: u64EffAddr = pVCpu->cpum.GstCtx.r13; break;
    5739                 case 14: u64EffAddr = pVCpu->cpum.GstCtx.r14; break;
    5740                 case 15: u64EffAddr = pVCpu->cpum.GstCtx.r15; break;
    5741                 /* SIB */
    5742                 case 4:
    5743                 case 12:
    5744                 {
    5745                     uint8_t bSib; IEM_OPCODE_GET_NEXT_U8(&bSib);
    5746                     uInfo = (uint64_t)bSib << 32;
    5747 
    5748                     /* Get the index and scale it. */
    5749                     switch (((bSib >> X86_SIB_INDEX_SHIFT) & X86_SIB_INDEX_SMASK) | pVCpu->iem.s.uRexIndex)
    5750                     {
    5751                         case  0: u64EffAddr = pVCpu->cpum.GstCtx.rax; break;
    5752                         case  1: u64EffAddr = pVCpu->cpum.GstCtx.rcx; break;
    5753                         case  2: u64EffAddr = pVCpu->cpum.GstCtx.rdx; break;
    5754                         case  3: u64EffAddr = pVCpu->cpum.GstCtx.rbx; break;
    5755                         case  4: u64EffAddr = 0; /*none */ break;
    5756                         case  5: u64EffAddr = pVCpu->cpum.GstCtx.rbp; break;
    5757                         case  6: u64EffAddr = pVCpu->cpum.GstCtx.rsi; break;
    5758                         case  7: u64EffAddr = pVCpu->cpum.GstCtx.rdi; break;
    5759                         case  8: u64EffAddr = pVCpu->cpum.GstCtx.r8;  break;
    5760                         case  9: u64EffAddr = pVCpu->cpum.GstCtx.r9;  break;
    5761                         case 10: u64EffAddr = pVCpu->cpum.GstCtx.r10; break;
    5762                         case 11: u64EffAddr = pVCpu->cpum.GstCtx.r11; break;
    5763                         case 12: u64EffAddr = pVCpu->cpum.GstCtx.r12; break;
    5764                         case 13: u64EffAddr = pVCpu->cpum.GstCtx.r13; break;
    5765                         case 14: u64EffAddr = pVCpu->cpum.GstCtx.r14; break;
    5766                         case 15: u64EffAddr = pVCpu->cpum.GstCtx.r15; break;
    5767                         IEM_NOT_REACHED_DEFAULT_CASE_RET();
    5768                     }
    5769                     u64EffAddr <<= (bSib >> X86_SIB_SCALE_SHIFT) & X86_SIB_SCALE_SMASK;
    5770 
    5771                     /* add base */
    5772                     switch ((bSib & X86_SIB_BASE_MASK) | pVCpu->iem.s.uRexB)
    5773                     {
    5774                         case  0: u64EffAddr += pVCpu->cpum.GstCtx.rax; break;
    5775                         case  1: u64EffAddr += pVCpu->cpum.GstCtx.rcx; break;
    5776                         case  2: u64EffAddr += pVCpu->cpum.GstCtx.rdx; break;
    5777                         case  3: u64EffAddr += pVCpu->cpum.GstCtx.rbx; break;
    5778                         case  4: u64EffAddr += pVCpu->cpum.GstCtx.rsp + (cbImmAndRspOffset >> 8); SET_SS_DEF(); break;
    5779                         case  6: u64EffAddr += pVCpu->cpum.GstCtx.rsi; break;
    5780                         case  7: u64EffAddr += pVCpu->cpum.GstCtx.rdi; break;
    5781                         case  8: u64EffAddr += pVCpu->cpum.GstCtx.r8;  break;
    5782                         case  9: u64EffAddr += pVCpu->cpum.GstCtx.r9;  break;
    5783                         case 10: u64EffAddr += pVCpu->cpum.GstCtx.r10; break;
    5784                         case 11: u64EffAddr += pVCpu->cpum.GstCtx.r11; break;
    5785                         case 12: u64EffAddr += pVCpu->cpum.GstCtx.r12; break;
    5786                         case 14: u64EffAddr += pVCpu->cpum.GstCtx.r14; break;
    5787                         case 15: u64EffAddr += pVCpu->cpum.GstCtx.r15; break;
    5788                         /* complicated encodings */
    5789                         case 5:
    5790                         case 13:
    5791                             if ((bRm & X86_MODRM_MOD_MASK) != 0)
    5792                             {
    5793                                 if (!pVCpu->iem.s.uRexB)
    5794                                 {
    5795                                     u64EffAddr += pVCpu->cpum.GstCtx.rbp;
    5796                                     SET_SS_DEF();
    5797                                 }
    5798                                 else
    5799                                     u64EffAddr += pVCpu->cpum.GstCtx.r13;
    5800                             }
    5801                             else
    5802                             {
    5803                                 uint32_t u32Disp;
    5804                                 IEM_OPCODE_GET_NEXT_U32(&u32Disp);
    5805                                 u64EffAddr += (int32_t)u32Disp;
    5806                                 uInfo      |= u32Disp;
    5807                             }
    5808                             break;
    5809                         IEM_NOT_REACHED_DEFAULT_CASE_RET();
    5810                     }
    5811                     break;
    5812                 }
    5813                 IEM_NOT_REACHED_DEFAULT_CASE_RET();
    5814             }
    5815 
    5816             /* Get and add the displacement. */
    5817             switch ((bRm >> X86_MODRM_MOD_SHIFT) & X86_MODRM_MOD_SMASK)
    5818             {
    5819                 case 0:
    5820                     break;
    5821                 case 1:
    5822                 {
    5823                     int8_t i8Disp;
    5824                     IEM_OPCODE_GET_NEXT_S8(&i8Disp);
    5825                     u64EffAddr += i8Disp;
    5826                     uInfo      |= (uint32_t)(int32_t)i8Disp;
    5827                     break;
    5828                 }
    5829                 case 2:
    5830                 {
    5831                     uint32_t u32Disp;
    5832                     IEM_OPCODE_GET_NEXT_U32(&u32Disp);
    5833                     u64EffAddr += (int32_t)u32Disp;
    5834                     uInfo      |= u32Disp;
    5835                     break;
    5836                 }
    5837                 IEM_NOT_REACHED_DEFAULT_CASE_RET(); /* (caller checked for these) */
    5838             }
    5839 
    5840         }
    5841 
    5842         if (pVCpu->iem.s.enmEffAddrMode == IEMMODE_64BIT)
    5843             *pGCPtrEff = u64EffAddr;
    5844         else
    5845         {
    5846             Assert(pVCpu->iem.s.enmEffAddrMode == IEMMODE_32BIT);
    5847             *pGCPtrEff = u64EffAddr & UINT32_MAX;
    5848         }
    5849     }
    5850     *puInfo = uInfo;
    5851 
    5852     Log5(("iemOpHlpCalcRmEffAddrEx: EffAddr=%#010RGv uInfo=%RX64\n", *pGCPtrEff, uInfo));
    5853     return VINF_SUCCESS;
    5854 }
    5855 
    5856 /** @}  */
    5857 
    5858 
    5859 #ifdef LOG_ENABLED
    5860 /**
    5861  * Logs the current instruction.
    5862  * @param   pVCpu       The cross context virtual CPU structure of the calling EMT.
    5863  * @param   fSameCtx    Set if we have the same context information as the VMM,
    5864  *                      clear if we may have already executed an instruction in
    5865  *                      our debug context. When clear, we assume IEMCPU holds
    5866  *                      valid CPU mode info.
    5867  *
    5868  *                      The @a fSameCtx parameter is now misleading and obsolete.
    5869  * @param   pszFunction The IEM function doing the execution.
    5870  */
    5871 static void iemLogCurInstr(PVMCPUCC pVCpu, bool fSameCtx, const char *pszFunction) RT_NOEXCEPT
    5872 {
    5873 # ifdef IN_RING3
    5874     if (LogIs2Enabled())
    5875     {
    5876         char     szInstr[256];
    5877         uint32_t cbInstr = 0;
    5878         if (fSameCtx)
    5879             DBGFR3DisasInstrEx(pVCpu->pVMR3->pUVM, pVCpu->idCpu, 0, 0,
    5880                                DBGF_DISAS_FLAGS_CURRENT_GUEST | DBGF_DISAS_FLAGS_DEFAULT_MODE,
    5881                                szInstr, sizeof(szInstr), &cbInstr);
    5882         else
    5883         {
    5884             uint32_t fFlags = 0;
    5885             switch (IEM_GET_CPU_MODE(pVCpu))
    5886             {
    5887                 case IEMMODE_64BIT: fFlags |= DBGF_DISAS_FLAGS_64BIT_MODE; break;
    5888                 case IEMMODE_32BIT: fFlags |= DBGF_DISAS_FLAGS_32BIT_MODE; break;
    5889                 case IEMMODE_16BIT:
    5890                     if (!(pVCpu->cpum.GstCtx.cr0 & X86_CR0_PE) || pVCpu->cpum.GstCtx.eflags.Bits.u1VM)
    5891                         fFlags |= DBGF_DISAS_FLAGS_16BIT_REAL_MODE;
    5892                     else
    5893                         fFlags |= DBGF_DISAS_FLAGS_16BIT_MODE;
    5894                     break;
    5895             }
    5896             DBGFR3DisasInstrEx(pVCpu->pVMR3->pUVM, pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, fFlags,
    5897                                szInstr, sizeof(szInstr), &cbInstr);
    5898         }
    5899 
    5900         PCX86FXSTATE pFpuCtx = &pVCpu->cpum.GstCtx.XState.x87;
    5901         Log2(("**** %s fExec=%x\n"
    5902               " eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x\n"
    5903               " eip=%08x esp=%08x ebp=%08x iopl=%d tr=%04x\n"
    5904               " cs=%04x ss=%04x ds=%04x es=%04x fs=%04x gs=%04x efl=%08x\n"
    5905               " fsw=%04x fcw=%04x ftw=%02x mxcsr=%04x/%04x\n"
    5906               " %s\n"
    5907               , pszFunction, pVCpu->iem.s.fExec,
    5908               pVCpu->cpum.GstCtx.eax, pVCpu->cpum.GstCtx.ebx, pVCpu->cpum.GstCtx.ecx, pVCpu->cpum.GstCtx.edx, pVCpu->cpum.GstCtx.esi, pVCpu->cpum.GstCtx.edi,
    5909               pVCpu->cpum.GstCtx.eip, pVCpu->cpum.GstCtx.esp, pVCpu->cpum.GstCtx.ebp, pVCpu->cpum.GstCtx.eflags.Bits.u2IOPL, pVCpu->cpum.GstCtx.tr.Sel,
    5910               pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.ss.Sel, pVCpu->cpum.GstCtx.ds.Sel, pVCpu->cpum.GstCtx.es.Sel,
    5911               pVCpu->cpum.GstCtx.fs.Sel, pVCpu->cpum.GstCtx.gs.Sel, pVCpu->cpum.GstCtx.eflags.u,
    5912               pFpuCtx->FSW, pFpuCtx->FCW, pFpuCtx->FTW, pFpuCtx->MXCSR, pFpuCtx->MXCSR_MASK,
    5913               szInstr));
    5914 
    5915         /* This stuff sucks atm. as it fills the log with MSRs. */
    5916         //if (LogIs3Enabled())
    5917         //    DBGFR3InfoEx(pVCpu->pVMR3->pUVM, pVCpu->idCpu, "cpumguest", "verbose", NULL);
    5918     }
    5919     else
    5920 # endif
    5921         LogFlow(("%s: cs:rip=%04x:%08RX64 ss:rsp=%04x:%08RX64 EFL=%06x\n", pszFunction, pVCpu->cpum.GstCtx.cs.Sel,
    5922                  pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.ss.Sel, pVCpu->cpum.GstCtx.rsp, pVCpu->cpum.GstCtx.eflags.u));
    5923     RT_NOREF_PV(pVCpu); RT_NOREF_PV(fSameCtx);
    5924 }
    5925 #endif /* LOG_ENABLED */
    5926 
    5927 
    5928 #ifdef VBOX_WITH_NESTED_HWVIRT_VMX
    5929 /**
    5930  * Deals with VMCPU_FF_VMX_APIC_WRITE, VMCPU_FF_VMX_MTF, VMCPU_FF_VMX_NMI_WINDOW,
    5931  * VMCPU_FF_VMX_PREEMPT_TIMER and VMCPU_FF_VMX_INT_WINDOW.
    5932  *
    5933  * @returns Modified rcStrict.
    5934  * @param   pVCpu       The cross context virtual CPU structure of the calling thread.
    5935  * @param   rcStrict    The instruction execution status.
    5936  */
    5937 static VBOXSTRICTRC iemHandleNestedInstructionBoundaryFFs(PVMCPUCC pVCpu, VBOXSTRICTRC rcStrict) RT_NOEXCEPT
    5938 {
    5939     Assert(CPUMIsGuestInVmxNonRootMode(IEM_GET_CTX(pVCpu)));
    5940     if (!VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_VMX_APIC_WRITE | VMCPU_FF_VMX_MTF))
    5941     {
    5942         /* VMX preemption timer takes priority over NMI-window exits. */
    5943         if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_PREEMPT_TIMER))
    5944         {
    5945             rcStrict = iemVmxVmexitPreemptTimer(pVCpu);
    5946             Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_PREEMPT_TIMER));
    5947         }
    5948         /*
    5949          * Check remaining intercepts.
    5950          *
    5951          * NMI-window and Interrupt-window VM-exits.
    5952          * Interrupt shadow (block-by-STI and Mov SS) inhibits interrupts and may also block NMIs.
    5953          * Event injection during VM-entry takes priority over NMI-window and interrupt-window VM-exits.
    5954          *
    5955          * See Intel spec. 26.7.6 "NMI-Window Exiting".
    5956          * See Intel spec. 26.7.5 "Interrupt-Window Exiting and Virtual-Interrupt Delivery".
    5957          */
    5958         else if (   VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_VMX_NMI_WINDOW | VMCPU_FF_VMX_INT_WINDOW)
    5959                  && !CPUMIsInInterruptShadow(&pVCpu->cpum.GstCtx)
    5960                  && !TRPMHasTrap(pVCpu))
    5961         {
    5962             Assert(CPUMIsGuestVmxInterceptEvents(&pVCpu->cpum.GstCtx));
    5963             if (   VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_NMI_WINDOW)
    5964                 && CPUMIsGuestVmxVirtNmiBlocking(&pVCpu->cpum.GstCtx))
    5965             {
    5966                 rcStrict = iemVmxVmexit(pVCpu, VMX_EXIT_NMI_WINDOW, 0 /* u64ExitQual */);
    5967                 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_NMI_WINDOW));
    5968             }
    5969             else if (   VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_INT_WINDOW)
    5970                      && CPUMIsGuestVmxVirtIntrEnabled(&pVCpu->cpum.GstCtx))
    5971             {
    5972                 rcStrict = iemVmxVmexit(pVCpu, VMX_EXIT_INT_WINDOW, 0 /* u64ExitQual */);
    5973                 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_INT_WINDOW));
    5974             }
    5975         }
    5976     }
    5977     /* TPR-below threshold/APIC write has the highest priority. */
    5978     else  if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_APIC_WRITE))
    5979     {
    5980         rcStrict = iemVmxApicWriteEmulation(pVCpu);
    5981         Assert(!CPUMIsInInterruptShadow(&pVCpu->cpum.GstCtx));
    5982         Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_APIC_WRITE));
    5983     }
    5984     /* MTF takes priority over VMX-preemption timer. */
    5985     else
    5986     {
    5987         rcStrict = iemVmxVmexit(pVCpu, VMX_EXIT_MTF, 0 /* u64ExitQual */);
    5988         Assert(!CPUMIsInInterruptShadow(&pVCpu->cpum.GstCtx));
    5989         Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_MTF));
    5990     }
    5991     return rcStrict;
    5992 }
    5993 #endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
    5994 
    5995 
    5996 /**
    5997  * The actual code execution bits of IEMExecOne, IEMExecOneWithPrefetchedByPC,
    5998  * IEMExecOneBypass and friends.
    5999  *
    6000  * Similar code is found in IEMExecLots.
    6001  *
    6002  * @return  Strict VBox status code.
    6003  * @param   pVCpu       The cross context virtual CPU structure of the calling EMT.
    6004  * @param   fExecuteInhibit     If set, execute the instruction following CLI,
    6005  *                      POP SS and MOV SS,GR.
    6006  * @param   pszFunction The calling function name.
    6007  */
    6008 DECLINLINE(VBOXSTRICTRC) iemExecOneInner(PVMCPUCC pVCpu, bool fExecuteInhibit, const char *pszFunction)
    6009 {
    6010     AssertMsg(pVCpu->iem.s.aMemMappings[0].fAccess == IEM_ACCESS_INVALID, ("0: %#x %RGp\n", pVCpu->iem.s.aMemMappings[0].fAccess, pVCpu->iem.s.aMemBbMappings[0].GCPhysFirst));
    6011     AssertMsg(pVCpu->iem.s.aMemMappings[1].fAccess == IEM_ACCESS_INVALID, ("1: %#x %RGp\n", pVCpu->iem.s.aMemMappings[1].fAccess, pVCpu->iem.s.aMemBbMappings[1].GCPhysFirst));
    6012     AssertMsg(pVCpu->iem.s.aMemMappings[2].fAccess == IEM_ACCESS_INVALID, ("2: %#x %RGp\n", pVCpu->iem.s.aMemMappings[2].fAccess, pVCpu->iem.s.aMemBbMappings[2].GCPhysFirst));
    6013     RT_NOREF_PV(pszFunction);
    6014 
    6015 #ifdef IEM_WITH_SETJMP
    6016     VBOXSTRICTRC rcStrict;
    6017     IEM_TRY_SETJMP(pVCpu, rcStrict)
    6018     {
    6019         uint8_t b; IEM_OPCODE_GET_FIRST_U8(&b);
    6020         rcStrict = FNIEMOP_CALL(g_apfnIemInterpretOnlyOneByteMap[b]);
    6021     }
    6022     IEM_CATCH_LONGJMP_BEGIN(pVCpu, rcStrict);
    6023     {
    6024         pVCpu->iem.s.cLongJumps++;
    6025     }
    6026     IEM_CATCH_LONGJMP_END(pVCpu);
    6027 #else
    6028     uint8_t b; IEM_OPCODE_GET_FIRST_U8(&b);
    6029     VBOXSTRICTRC rcStrict = FNIEMOP_CALL(g_apfnIemInterpretOnlyOneByteMap[b]);
    6030 #endif
    6031     if (rcStrict == VINF_SUCCESS)
    6032         pVCpu->iem.s.cInstructions++;
    6033     if (pVCpu->iem.s.cActiveMappings > 0)
    6034     {
    6035         Assert(rcStrict != VINF_SUCCESS);
    6036         iemMemRollback(pVCpu);
    6037     }
    6038     AssertMsg(pVCpu->iem.s.aMemMappings[0].fAccess == IEM_ACCESS_INVALID, ("0: %#x %RGp\n", pVCpu->iem.s.aMemMappings[0].fAccess, pVCpu->iem.s.aMemBbMappings[0].GCPhysFirst));
    6039     AssertMsg(pVCpu->iem.s.aMemMappings[1].fAccess == IEM_ACCESS_INVALID, ("1: %#x %RGp\n", pVCpu->iem.s.aMemMappings[1].fAccess, pVCpu->iem.s.aMemBbMappings[1].GCPhysFirst));
    6040     AssertMsg(pVCpu->iem.s.aMemMappings[2].fAccess == IEM_ACCESS_INVALID, ("2: %#x %RGp\n", pVCpu->iem.s.aMemMappings[2].fAccess, pVCpu->iem.s.aMemBbMappings[2].GCPhysFirst));
    6041 
    6042 //#ifdef DEBUG
    6043 //    AssertMsg(IEM_GET_INSTR_LEN(pVCpu) == cbInstr || rcStrict != VINF_SUCCESS, ("%u %u\n", IEM_GET_INSTR_LEN(pVCpu), cbInstr));
    6044 //#endif
    6045 
    6046 #ifdef VBOX_WITH_NESTED_HWVIRT_VMX
    6047     /*
    6048      * Perform any VMX nested-guest instruction boundary actions.
    6049      *
    6050      * If any of these causes a VM-exit, we must skip executing the next
    6051      * instruction (would run into stale page tables). A VM-exit makes sure
    6052      * there is no interrupt-inhibition, so that should ensure we don't go
    6053      * to try execute the next instruction. Clearing fExecuteInhibit is
    6054      * problematic because of the setjmp/longjmp clobbering above.
    6055      */
    6056     if (   !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_VMX_APIC_WRITE | VMCPU_FF_VMX_MTF | VMCPU_FF_VMX_PREEMPT_TIMER
    6057                                      | VMCPU_FF_VMX_INT_WINDOW | VMCPU_FF_VMX_NMI_WINDOW)
    6058         || rcStrict != VINF_SUCCESS)
    6059     { /* likely */ }
    6060     else
    6061         rcStrict = iemHandleNestedInstructionBoundaryFFs(pVCpu, rcStrict);
    6062 #endif
    6063 
    6064     /* Execute the next instruction as well if a cli, pop ss or
    6065        mov ss, Gr has just completed successfully. */
    6066     if (   fExecuteInhibit
    6067         && rcStrict == VINF_SUCCESS
    6068         && CPUMIsInInterruptShadow(&pVCpu->cpum.GstCtx))
    6069     {
    6070         rcStrict = iemInitDecoderAndPrefetchOpcodes(pVCpu, pVCpu->iem.s.fExec & (IEM_F_BYPASS_HANDLERS | IEM_F_X86_DISREGARD_LOCK));
    6071         if (rcStrict == VINF_SUCCESS)
    6072         {
    6073 #ifdef LOG_ENABLED
    6074             iemLogCurInstr(pVCpu, false, pszFunction);
    6075 #endif
    6076 #ifdef IEM_WITH_SETJMP
    6077             IEM_TRY_SETJMP_AGAIN(pVCpu, rcStrict)
    6078             {
    6079                 uint8_t b; IEM_OPCODE_GET_FIRST_U8(&b);
    6080                 rcStrict = FNIEMOP_CALL(g_apfnIemInterpretOnlyOneByteMap[b]);
    6081             }
    6082             IEM_CATCH_LONGJMP_BEGIN(pVCpu, rcStrict);
    6083             {
    6084                 pVCpu->iem.s.cLongJumps++;
    6085             }
    6086             IEM_CATCH_LONGJMP_END(pVCpu);
    6087 #else
    6088             IEM_OPCODE_GET_FIRST_U8(&b);
    6089             rcStrict = FNIEMOP_CALL(g_apfnIemInterpretOnlyOneByteMap[b]);
    6090 #endif
    6091             if (rcStrict == VINF_SUCCESS)
    6092             {
    6093                 pVCpu->iem.s.cInstructions++;
    6094 #ifdef VBOX_WITH_NESTED_HWVIRT_VMX
    6095                 if (!VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_VMX_APIC_WRITE | VMCPU_FF_VMX_MTF | VMCPU_FF_VMX_PREEMPT_TIMER
    6096                                               | VMCPU_FF_VMX_INT_WINDOW | VMCPU_FF_VMX_NMI_WINDOW))
    6097                 { /* likely */ }
    6098                 else
    6099                     rcStrict = iemHandleNestedInstructionBoundaryFFs(pVCpu, rcStrict);
    6100 #endif
    6101             }
    6102             if (pVCpu->iem.s.cActiveMappings > 0)
    6103             {
    6104                 Assert(rcStrict != VINF_SUCCESS);
    6105                 iemMemRollback(pVCpu);
    6106             }
    6107             AssertMsg(pVCpu->iem.s.aMemMappings[0].fAccess == IEM_ACCESS_INVALID, ("0: %#x %RGp\n", pVCpu->iem.s.aMemMappings[0].fAccess, pVCpu->iem.s.aMemBbMappings[0].GCPhysFirst));
    6108             AssertMsg(pVCpu->iem.s.aMemMappings[1].fAccess == IEM_ACCESS_INVALID, ("1: %#x %RGp\n", pVCpu->iem.s.aMemMappings[1].fAccess, pVCpu->iem.s.aMemBbMappings[1].GCPhysFirst));
    6109             AssertMsg(pVCpu->iem.s.aMemMappings[2].fAccess == IEM_ACCESS_INVALID, ("2: %#x %RGp\n", pVCpu->iem.s.aMemMappings[2].fAccess, pVCpu->iem.s.aMemBbMappings[2].GCPhysFirst));
    6110         }
    6111         else if (pVCpu->iem.s.cActiveMappings > 0)
    6112             iemMemRollback(pVCpu);
    6113         /** @todo drop this after we bake this change into RIP advancing. */
    6114         CPUMClearInterruptShadow(&pVCpu->cpum.GstCtx); /* hope this is correct for all exceptional cases... */
    6115     }
    6116 
    6117     /*
    6118      * Return value fiddling, statistics and sanity assertions.
    6119      */
    6120     rcStrict = iemExecStatusCodeFiddling(pVCpu, rcStrict);
    6121 
    6122     Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pVCpu->cpum.GstCtx.cs));
    6123     Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pVCpu->cpum.GstCtx.ss));
    6124     return rcStrict;
    6125 }
    6126 
    6127 
    6128 /**
    6129  * Execute one instruction.
    6130  *
    6131  * @return  Strict VBox status code.
    6132  * @param   pVCpu       The cross context virtual CPU structure of the calling EMT.
    6133  */
    6134 VMM_INT_DECL(VBOXSTRICTRC) IEMExecOne(PVMCPUCC pVCpu)
    6135 {
    6136     AssertCompile(sizeof(pVCpu->iem.s) <= sizeof(pVCpu->iem.padding)); /* (tstVMStruct can't do it's job w/o instruction stats) */
    6137 #ifdef LOG_ENABLED
    6138     iemLogCurInstr(pVCpu, true, "IEMExecOne");
    6139 #endif
    6140 
    6141     /*
    6142      * Do the decoding and emulation.
    6143      */
    6144     VBOXSTRICTRC rcStrict = iemInitDecoderAndPrefetchOpcodes(pVCpu, 0 /*fExecOpts*/);
    6145     if (rcStrict == VINF_SUCCESS)
    6146         rcStrict = iemExecOneInner(pVCpu, true, "IEMExecOne");
    6147     else if (pVCpu->iem.s.cActiveMappings > 0)
    6148         iemMemRollback(pVCpu);
    6149 
    6150     if (rcStrict != VINF_SUCCESS)
    6151         LogFlow(("IEMExecOne: cs:rip=%04x:%08RX64 ss:rsp=%04x:%08RX64 EFL=%06x - rcStrict=%Rrc\n",
    6152                  pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.ss.Sel, pVCpu->cpum.GstCtx.rsp, pVCpu->cpum.GstCtx.eflags.u, VBOXSTRICTRC_VAL(rcStrict)));
    6153     return rcStrict;
    6154 }
    6155 
    6156 
    6157 VMM_INT_DECL(VBOXSTRICTRC) IEMExecOneWithPrefetchedByPC(PVMCPUCC pVCpu, uint64_t OpcodeBytesPC,
    6158                                                         const void *pvOpcodeBytes, size_t cbOpcodeBytes)
    6159 {
    6160     VBOXSTRICTRC rcStrict;
    6161     if (   cbOpcodeBytes
    6162         && pVCpu->cpum.GstCtx.rip == OpcodeBytesPC)
    6163     {
    6164         iemInitDecoder(pVCpu, 0 /*fExecOpts*/);
    6165 #ifdef IEM_WITH_CODE_TLB
    6166         pVCpu->iem.s.uInstrBufPc      = OpcodeBytesPC;
    6167         pVCpu->iem.s.pbInstrBuf       = (uint8_t const *)pvOpcodeBytes;
    6168         pVCpu->iem.s.cbInstrBufTotal  = (uint16_t)RT_MIN(X86_PAGE_SIZE, cbOpcodeBytes);
    6169         pVCpu->iem.s.offCurInstrStart = 0;
    6170         pVCpu->iem.s.offInstrNextByte = 0;
    6171         pVCpu->iem.s.GCPhysInstrBuf   = NIL_RTGCPHYS;
    6172 #else
    6173         pVCpu->iem.s.cbOpcode = (uint8_t)RT_MIN(cbOpcodeBytes, sizeof(pVCpu->iem.s.abOpcode));
    6174         memcpy(pVCpu->iem.s.abOpcode, pvOpcodeBytes, pVCpu->iem.s.cbOpcode);
    6175 #endif
    6176         rcStrict = VINF_SUCCESS;
    6177     }
    6178     else
    6179         rcStrict = iemInitDecoderAndPrefetchOpcodes(pVCpu, 0 /*fExecOpts*/);
    6180     if (rcStrict == VINF_SUCCESS)
    6181         rcStrict = iemExecOneInner(pVCpu, true, "IEMExecOneWithPrefetchedByPC");
    6182     else if (pVCpu->iem.s.cActiveMappings > 0)
    6183         iemMemRollback(pVCpu);
    6184 
    6185     return rcStrict;
    6186 }
    6187 
    6188 
    6189 VMM_INT_DECL(VBOXSTRICTRC) IEMExecOneBypass(PVMCPUCC pVCpu)
    6190 {
    6191     VBOXSTRICTRC rcStrict = iemInitDecoderAndPrefetchOpcodes(pVCpu, IEM_F_BYPASS_HANDLERS);
    6192     if (rcStrict == VINF_SUCCESS)
    6193         rcStrict = iemExecOneInner(pVCpu, false, "IEMExecOneBypass");
    6194     else if (pVCpu->iem.s.cActiveMappings > 0)
    6195         iemMemRollback(pVCpu);
    6196 
    6197     return rcStrict;
    6198 }
    6199 
    6200 
    6201 VMM_INT_DECL(VBOXSTRICTRC) IEMExecOneBypassWithPrefetchedByPC(PVMCPUCC pVCpu, uint64_t OpcodeBytesPC,
    6202                                                               const void *pvOpcodeBytes, size_t cbOpcodeBytes)
    6203 {
    6204     VBOXSTRICTRC rcStrict;
    6205     if (   cbOpcodeBytes
    6206         && pVCpu->cpum.GstCtx.rip == OpcodeBytesPC)
    6207     {
    6208         iemInitDecoder(pVCpu, IEM_F_BYPASS_HANDLERS);
    6209 #ifdef IEM_WITH_CODE_TLB
    6210         pVCpu->iem.s.uInstrBufPc      = OpcodeBytesPC;
    6211         pVCpu->iem.s.pbInstrBuf       = (uint8_t const *)pvOpcodeBytes;
    6212         pVCpu->iem.s.cbInstrBufTotal  = (uint16_t)RT_MIN(X86_PAGE_SIZE, cbOpcodeBytes);
    6213         pVCpu->iem.s.offCurInstrStart = 0;
    6214         pVCpu->iem.s.offInstrNextByte = 0;
    6215         pVCpu->iem.s.GCPhysInstrBuf   = NIL_RTGCPHYS;
    6216 #else
    6217         pVCpu->iem.s.cbOpcode = (uint8_t)RT_MIN(cbOpcodeBytes, sizeof(pVCpu->iem.s.abOpcode));
    6218         memcpy(pVCpu->iem.s.abOpcode, pvOpcodeBytes, pVCpu->iem.s.cbOpcode);
    6219 #endif
    6220         rcStrict = VINF_SUCCESS;
    6221     }
    6222     else
    6223         rcStrict = iemInitDecoderAndPrefetchOpcodes(pVCpu, IEM_F_BYPASS_HANDLERS);
    6224     if (rcStrict == VINF_SUCCESS)
    6225         rcStrict = iemExecOneInner(pVCpu, false, "IEMExecOneBypassWithPrefetchedByPC");
    6226     else if (pVCpu->iem.s.cActiveMappings > 0)
    6227         iemMemRollback(pVCpu);
    6228 
    6229     return rcStrict;
    6230 }
    6231 
    6232 
    6233 /**
    6234  * For handling split cacheline lock operations when the host has split-lock
    6235  * detection enabled.
    6236  *
    6237  * This will cause the interpreter to disregard the lock prefix and implicit
    6238  * locking (xchg).
    6239  *
    6240  * @returns Strict VBox status code.
    6241  * @param   pVCpu   The cross context virtual CPU structure of the calling EMT.
    6242  */
    6243 VMM_INT_DECL(VBOXSTRICTRC) IEMExecOneIgnoreLock(PVMCPUCC pVCpu)
    6244 {
    6245     /*
    6246      * Do the decoding and emulation.
    6247      */
    6248     VBOXSTRICTRC rcStrict = iemInitDecoderAndPrefetchOpcodes(pVCpu, IEM_F_X86_DISREGARD_LOCK);
    6249     if (rcStrict == VINF_SUCCESS)
    6250         rcStrict = iemExecOneInner(pVCpu, true, "IEMExecOneIgnoreLock");
    6251     else if (pVCpu->iem.s.cActiveMappings > 0)
    6252         iemMemRollback(pVCpu);
    6253 
    6254     if (rcStrict != VINF_SUCCESS)
    6255         LogFlow(("IEMExecOneIgnoreLock: cs:rip=%04x:%08RX64 ss:rsp=%04x:%08RX64 EFL=%06x - rcStrict=%Rrc\n",
    6256                  pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.ss.Sel, pVCpu->cpum.GstCtx.rsp, pVCpu->cpum.GstCtx.eflags.u, VBOXSTRICTRC_VAL(rcStrict)));
    6257     return rcStrict;
    6258 }
    6259 
    6260 
    6261 /**
    6262  * Code common to IEMExecLots and IEMExecRecompilerThreaded that attempts to
    6263  * inject a pending TRPM trap.
    6264  */
    6265 VBOXSTRICTRC iemExecInjectPendingTrap(PVMCPUCC pVCpu)
    6266 {
    6267     Assert(TRPMHasTrap(pVCpu));
    6268 
    6269     if (   !CPUMIsInInterruptShadow(&pVCpu->cpum.GstCtx)
    6270         && !CPUMAreInterruptsInhibitedByNmi(&pVCpu->cpum.GstCtx))
    6271     {
    6272         /** @todo Can we centralize this under CPUMCanInjectInterrupt()? */
    6273 #if defined(VBOX_WITH_NESTED_HWVIRT_SVM) || defined(VBOX_WITH_NESTED_HWVIRT_VMX)
    6274         bool fIntrEnabled = CPUMGetGuestGif(&pVCpu->cpum.GstCtx);
    6275         if (fIntrEnabled)
    6276         {
    6277             if (!CPUMIsGuestInNestedHwvirtMode(IEM_GET_CTX(pVCpu)))
    6278                 fIntrEnabled = pVCpu->cpum.GstCtx.eflags.Bits.u1IF;
    6279             else if (CPUMIsGuestInVmxNonRootMode(IEM_GET_CTX(pVCpu)))
    6280                 fIntrEnabled = CPUMIsGuestVmxPhysIntrEnabled(IEM_GET_CTX(pVCpu));
    6281             else
    6282             {
    6283                 Assert(CPUMIsGuestInSvmNestedHwVirtMode(IEM_GET_CTX(pVCpu)));
    6284                 fIntrEnabled = CPUMIsGuestSvmPhysIntrEnabled(pVCpu, IEM_GET_CTX(pVCpu));
    6285             }
    6286         }
    6287 #else
    6288         bool fIntrEnabled = pVCpu->cpum.GstCtx.eflags.Bits.u1IF;
    6289 #endif
    6290         if (fIntrEnabled)
    6291         {
    6292             uint8_t     u8TrapNo;
    6293             TRPMEVENT   enmType;
    6294             uint32_t    uErrCode;
    6295             RTGCPTR     uCr2;
    6296             int rc2 = TRPMQueryTrapAll(pVCpu, &u8TrapNo, &enmType, &uErrCode, &uCr2, NULL /*pu8InstLen*/, NULL /*fIcebp*/);
    6297             AssertRC(rc2);
    6298             Assert(enmType == TRPM_HARDWARE_INT);
    6299             VBOXSTRICTRC rcStrict = IEMInjectTrap(pVCpu, u8TrapNo, enmType, (uint16_t)uErrCode, uCr2, 0 /*cbInstr*/);
    6300 
    6301             TRPMResetTrap(pVCpu);
    6302 
    6303 #if defined(VBOX_WITH_NESTED_HWVIRT_SVM) || defined(VBOX_WITH_NESTED_HWVIRT_VMX)
    6304             /* Injecting an event may cause a VM-exit. */
    6305             if (   rcStrict != VINF_SUCCESS
    6306                 && rcStrict != VINF_IEM_RAISED_XCPT)
    6307                 return iemExecStatusCodeFiddling(pVCpu, rcStrict);
    6308 #else
    6309             NOREF(rcStrict);
    6310 #endif
    6311         }
    6312     }
    6313 
    6314     return VINF_SUCCESS;
    6315 }
    6316 
    6317 
    6318 VMM_INT_DECL(VBOXSTRICTRC) IEMExecLots(PVMCPUCC pVCpu, uint32_t cMaxInstructions, uint32_t cPollRate, uint32_t *pcInstructions)
    6319 {
    6320     uint32_t const cInstructionsAtStart = pVCpu->iem.s.cInstructions;
    6321     AssertMsg(RT_IS_POWER_OF_TWO(cPollRate + 1), ("%#x\n", cPollRate));
    6322     Assert(cMaxInstructions > 0);
    6323 
    6324     /*
    6325      * See if there is an interrupt pending in TRPM, inject it if we can.
    6326      */
    6327     /** @todo What if we are injecting an exception and not an interrupt? Is that
    6328      *        possible here? For now we assert it is indeed only an interrupt. */
    6329     if (!TRPMHasTrap(pVCpu))
    6330     { /* likely */ }
    6331     else
    6332     {
    6333         VBOXSTRICTRC rcStrict = iemExecInjectPendingTrap(pVCpu);
    6334         if (RT_LIKELY(rcStrict == VINF_SUCCESS))
    6335         { /*likely */ }
    6336         else
    6337             return rcStrict;
    6338     }
    6339 
    6340     /*
    6341      * Initial decoder init w/ prefetch, then setup setjmp.
    6342      */
    6343     VBOXSTRICTRC rcStrict = iemInitDecoderAndPrefetchOpcodes(pVCpu, 0 /*fExecOpts*/);
    6344     if (rcStrict == VINF_SUCCESS)
    6345     {
    6346 #ifdef IEM_WITH_SETJMP
    6347         pVCpu->iem.s.cActiveMappings = 0; /** @todo wtf? */
    6348         IEM_TRY_SETJMP(pVCpu, rcStrict)
    6349 #endif
    6350         {
    6351             /*
    6352              * The run loop.  We limit ourselves to 4096 instructions right now.
    6353              */
    6354             uint32_t cMaxInstructionsGccStupidity = cMaxInstructions;
    6355             PVMCC pVM = pVCpu->CTX_SUFF(pVM);
    6356             for (;;)
    6357             {
    6358                 /*
    6359                  * Log the state.
    6360                  */
    6361 #ifdef LOG_ENABLED
    6362                 iemLogCurInstr(pVCpu, true, "IEMExecLots");
    6363 #endif
    6364 
    6365                 /*
    6366                  * Do the decoding and emulation.
    6367                  */
    6368                 uint8_t b; IEM_OPCODE_GET_FIRST_U8(&b);
    6369                 rcStrict = FNIEMOP_CALL(g_apfnIemInterpretOnlyOneByteMap[b]);
    6370 #ifdef VBOX_STRICT
    6371                 CPUMAssertGuestRFlagsCookie(pVM, pVCpu);
    6372 #endif
    6373                 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
    6374                 {
    6375                     Assert(pVCpu->iem.s.cActiveMappings == 0);
    6376                     pVCpu->iem.s.cInstructions++;
    6377 
    6378 #ifdef VBOX_WITH_NESTED_HWVIRT_VMX
    6379                     /* Perform any VMX nested-guest instruction boundary actions. */
    6380                     uint64_t fCpu = pVCpu->fLocalForcedActions;
    6381                     if (!(fCpu & (  VMCPU_FF_VMX_APIC_WRITE | VMCPU_FF_VMX_MTF | VMCPU_FF_VMX_PREEMPT_TIMER
    6382                                   | VMCPU_FF_VMX_INT_WINDOW | VMCPU_FF_VMX_NMI_WINDOW)))
    6383                     { /* likely */ }
    6384                     else
    6385                     {
    6386                         rcStrict = iemHandleNestedInstructionBoundaryFFs(pVCpu, rcStrict);
    6387                         if (RT_LIKELY(rcStrict == VINF_SUCCESS))
    6388                             fCpu = pVCpu->fLocalForcedActions;
    6389                         else
    6390                         {
    6391                             rcStrict = iemExecStatusCodeFiddling(pVCpu, rcStrict);
    6392                             break;
    6393                         }
    6394                     }
    6395 #endif
    6396                     if (RT_LIKELY(pVCpu->iem.s.rcPassUp == VINF_SUCCESS))
    6397                     {
    6398 #ifndef VBOX_WITH_NESTED_HWVIRT_VMX
    6399                         uint64_t fCpu = pVCpu->fLocalForcedActions;
    6400 #endif
    6401                         fCpu &= VMCPU_FF_ALL_MASK & ~(  VMCPU_FF_PGM_SYNC_CR3
    6402                                                       | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL
    6403                                                       | VMCPU_FF_TLB_FLUSH
    6404                                                       | VMCPU_FF_UNHALT );
    6405 
    6406                         if (RT_LIKELY(   (   !fCpu
    6407                                           || (   !(fCpu & ~(VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC))
    6408                                               && !pVCpu->cpum.GstCtx.rflags.Bits.u1IF) )
    6409                                       && !VM_FF_IS_ANY_SET(pVM, VM_FF_ALL_MASK) ))
    6410                         {
    6411                             if (--cMaxInstructionsGccStupidity > 0)
    6412                             {
    6413                                 /* Poll timers every now an then according to the caller's specs. */
    6414                                 if (   (cMaxInstructionsGccStupidity & cPollRate) != 0
    6415                                     || !TMTimerPollBool(pVM, pVCpu))
    6416                                 {
    6417                                     Assert(pVCpu->iem.s.cActiveMappings == 0);
    6418                                     iemReInitDecoder(pVCpu);
    6419                                     continue;
    6420                                 }
    6421                             }
    6422                         }
    6423                     }
    6424                     Assert(pVCpu->iem.s.cActiveMappings == 0);
    6425                 }
    6426                 else if (pVCpu->iem.s.cActiveMappings > 0)
    6427                     iemMemRollback(pVCpu);
    6428                 rcStrict = iemExecStatusCodeFiddling(pVCpu, rcStrict);
    6429                 break;
    6430             }
    6431         }
    6432 #ifdef IEM_WITH_SETJMP
    6433         IEM_CATCH_LONGJMP_BEGIN(pVCpu, rcStrict);
    6434         {
    6435             if (pVCpu->iem.s.cActiveMappings > 0)
    6436                 iemMemRollback(pVCpu);
    6437 # if defined(VBOX_WITH_NESTED_HWVIRT_SVM) || defined(VBOX_WITH_NESTED_HWVIRT_VMX)
    6438             rcStrict = iemExecStatusCodeFiddling(pVCpu, rcStrict);
    6439 # endif
    6440             pVCpu->iem.s.cLongJumps++;
    6441         }
    6442         IEM_CATCH_LONGJMP_END(pVCpu);
    6443 #endif
    6444 
    6445         /*
    6446          * Assert hidden register sanity (also done in iemInitDecoder and iemReInitDecoder).
    6447          */
    6448         Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pVCpu->cpum.GstCtx.cs));
    6449         Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pVCpu->cpum.GstCtx.ss));
    6450     }
    6451     else
    6452     {
    6453         if (pVCpu->iem.s.cActiveMappings > 0)
    6454             iemMemRollback(pVCpu);
    6455 
    6456 #if defined(VBOX_WITH_NESTED_HWVIRT_SVM) || defined(VBOX_WITH_NESTED_HWVIRT_VMX)
    6457         /*
    6458          * When a nested-guest causes an exception intercept (e.g. #PF) when fetching
    6459          * code as part of instruction execution, we need this to fix-up VINF_SVM_VMEXIT.
    6460          */
    6461         rcStrict = iemExecStatusCodeFiddling(pVCpu, rcStrict);
    6462 #endif
    6463     }
    6464 
    6465     /*
    6466      * Maybe re-enter raw-mode and log.
    6467      */
    6468     if (rcStrict != VINF_SUCCESS)
    6469         LogFlow(("IEMExecLots: cs:rip=%04x:%08RX64 ss:rsp=%04x:%08RX64 EFL=%06x - rcStrict=%Rrc\n",
    6470                  pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.ss.Sel, pVCpu->cpum.GstCtx.rsp, pVCpu->cpum.GstCtx.eflags.u, VBOXSTRICTRC_VAL(rcStrict)));
    6471     if (pcInstructions)
    6472         *pcInstructions = pVCpu->iem.s.cInstructions - cInstructionsAtStart;
    6473     return rcStrict;
    6474 }
    6475 
    6476 
    6477 /**
    6478  * Interface used by EMExecuteExec, does exit statistics and limits.
    6479  *
    6480  * @returns Strict VBox status code.
    6481  * @param   pVCpu               The cross context virtual CPU structure.
    6482  * @param   fWillExit           To be defined.
    6483  * @param   cMinInstructions    Minimum number of instructions to execute before checking for FFs.
    6484  * @param   cMaxInstructions    Maximum number of instructions to execute.
    6485  * @param   cMaxInstructionsWithoutExits
    6486  *                              The max number of instructions without exits.
    6487  * @param   pStats              Where to return statistics.
    6488  */
    6489 VMM_INT_DECL(VBOXSTRICTRC)
    6490 IEMExecForExits(PVMCPUCC pVCpu, uint32_t fWillExit, uint32_t cMinInstructions, uint32_t cMaxInstructions,
    6491                 uint32_t cMaxInstructionsWithoutExits, PIEMEXECFOREXITSTATS pStats)
    6492 {
    6493     NOREF(fWillExit); /** @todo define flexible exit crits */
    6494 
    6495     /*
    6496      * Initialize return stats.
    6497      */
    6498     pStats->cInstructions    = 0;
    6499     pStats->cExits           = 0;
    6500     pStats->cMaxExitDistance = 0;
    6501     pStats->cReserved        = 0;
    6502 
    6503     /*
    6504      * Initial decoder init w/ prefetch, then setup setjmp.
    6505      */
    6506     VBOXSTRICTRC rcStrict = iemInitDecoderAndPrefetchOpcodes(pVCpu, 0 /*fExecOpts*/);
    6507     if (rcStrict == VINF_SUCCESS)
    6508     {
    6509 #ifdef IEM_WITH_SETJMP
    6510         pVCpu->iem.s.cActiveMappings     = 0; /** @todo wtf?!? */
    6511         IEM_TRY_SETJMP(pVCpu, rcStrict)
    6512 #endif
    6513         {
    6514 #ifdef IN_RING0
    6515             bool const fCheckPreemptionPending   = !RTThreadPreemptIsPossible() || !RTThreadPreemptIsEnabled(NIL_RTTHREAD);
    6516 #endif
    6517             uint32_t   cInstructionSinceLastExit = 0;
    6518 
    6519             /*
    6520              * The run loop.  We limit ourselves to 4096 instructions right now.
    6521              */
    6522             PVM pVM = pVCpu->CTX_SUFF(pVM);
    6523             for (;;)
    6524             {
    6525                 /*
    6526                  * Log the state.
    6527                  */
    6528 #ifdef LOG_ENABLED
    6529                 iemLogCurInstr(pVCpu, true, "IEMExecForExits");
    6530 #endif
    6531 
    6532                 /*
    6533                  * Do the decoding and emulation.
    6534                  */
    6535                 uint32_t const cPotentialExits = pVCpu->iem.s.cPotentialExits;
    6536 
    6537                 uint8_t b; IEM_OPCODE_GET_FIRST_U8(&b);
    6538                 rcStrict = FNIEMOP_CALL(g_apfnIemInterpretOnlyOneByteMap[b]);
    6539 
    6540                 if (   cPotentialExits != pVCpu->iem.s.cPotentialExits
    6541                     && cInstructionSinceLastExit > 0 /* don't count the first */ )
    6542                 {
    6543                     pStats->cExits += 1;
    6544                     if (cInstructionSinceLastExit > pStats->cMaxExitDistance)
    6545                         pStats->cMaxExitDistance = cInstructionSinceLastExit;
    6546                     cInstructionSinceLastExit = 0;
    6547                 }
    6548 
    6549                 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
    6550                 {
    6551                     Assert(pVCpu->iem.s.cActiveMappings == 0);
    6552                     pVCpu->iem.s.cInstructions++;
    6553                     pStats->cInstructions++;
    6554                     cInstructionSinceLastExit++;
    6555 
    6556 #ifdef VBOX_WITH_NESTED_HWVIRT_VMX
    6557                     /* Perform any VMX nested-guest instruction boundary actions. */
    6558                     uint64_t fCpu = pVCpu->fLocalForcedActions;
    6559                     if (!(fCpu & (  VMCPU_FF_VMX_APIC_WRITE | VMCPU_FF_VMX_MTF | VMCPU_FF_VMX_PREEMPT_TIMER
    6560                                   | VMCPU_FF_VMX_INT_WINDOW | VMCPU_FF_VMX_NMI_WINDOW)))
    6561                     { /* likely */ }
    6562                     else
    6563                     {
    6564                         rcStrict = iemHandleNestedInstructionBoundaryFFs(pVCpu, rcStrict);
    6565                         if (RT_LIKELY(rcStrict == VINF_SUCCESS))
    6566                             fCpu = pVCpu->fLocalForcedActions;
    6567                         else
    6568                         {
    6569                             rcStrict = iemExecStatusCodeFiddling(pVCpu, rcStrict);
    6570                             break;
    6571                         }
    6572                     }
    6573 #endif
    6574                     if (RT_LIKELY(pVCpu->iem.s.rcPassUp == VINF_SUCCESS))
    6575                     {
    6576 #ifndef VBOX_WITH_NESTED_HWVIRT_VMX
    6577                         uint64_t fCpu = pVCpu->fLocalForcedActions;
    6578 #endif
    6579                         fCpu &= VMCPU_FF_ALL_MASK & ~(  VMCPU_FF_PGM_SYNC_CR3
    6580                                                       | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL
    6581                                                       | VMCPU_FF_TLB_FLUSH
    6582                                                       | VMCPU_FF_UNHALT );
    6583                         if (RT_LIKELY(   (   (   !fCpu
    6584                                               || (   !(fCpu & ~(VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC))
    6585                                                   && !pVCpu->cpum.GstCtx.rflags.Bits.u1IF))
    6586                                           && !VM_FF_IS_ANY_SET(pVM, VM_FF_ALL_MASK) )
    6587                                       || pStats->cInstructions < cMinInstructions))
    6588                         {
    6589                             if (pStats->cInstructions < cMaxInstructions)
    6590                             {
    6591                                 if (cInstructionSinceLastExit <= cMaxInstructionsWithoutExits)
    6592                                 {
    6593 #ifdef IN_RING0
    6594                                     if (   !fCheckPreemptionPending
    6595                                         || !RTThreadPreemptIsPending(NIL_RTTHREAD))
    6596 #endif
    6597                                     {
    6598                                         Assert(pVCpu->iem.s.cActiveMappings == 0);
    6599                                         iemReInitDecoder(pVCpu);
    6600                                         continue;
    6601                                     }
    6602 #ifdef IN_RING0
    6603                                     rcStrict = VINF_EM_RAW_INTERRUPT;
    6604                                     break;
    6605 #endif
    6606                                 }
    6607                             }
    6608                         }
    6609                         Assert(!(fCpu & VMCPU_FF_IEM));
    6610                     }
    6611                     Assert(pVCpu->iem.s.cActiveMappings == 0);
    6612                 }
    6613                 else if (pVCpu->iem.s.cActiveMappings > 0)
    6614                         iemMemRollback(pVCpu);
    6615                 rcStrict = iemExecStatusCodeFiddling(pVCpu, rcStrict);
    6616                 break;
    6617             }
    6618         }
    6619 #ifdef IEM_WITH_SETJMP
    6620         IEM_CATCH_LONGJMP_BEGIN(pVCpu, rcStrict);
    6621         {
    6622             if (pVCpu->iem.s.cActiveMappings > 0)
    6623                 iemMemRollback(pVCpu);
    6624             pVCpu->iem.s.cLongJumps++;
    6625         }
    6626         IEM_CATCH_LONGJMP_END(pVCpu);
    6627 #endif
    6628 
    6629         /*
    6630          * Assert hidden register sanity (also done in iemInitDecoder and iemReInitDecoder).
    6631          */
    6632         Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pVCpu->cpum.GstCtx.cs));
    6633         Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pVCpu->cpum.GstCtx.ss));
    6634     }
    6635     else
    6636     {
    6637         if (pVCpu->iem.s.cActiveMappings > 0)
    6638             iemMemRollback(pVCpu);
    6639 
    6640 #if defined(VBOX_WITH_NESTED_HWVIRT_SVM) || defined(VBOX_WITH_NESTED_HWVIRT_VMX)
    6641         /*
    6642          * When a nested-guest causes an exception intercept (e.g. #PF) when fetching
    6643          * code as part of instruction execution, we need this to fix-up VINF_SVM_VMEXIT.
    6644          */
    6645         rcStrict = iemExecStatusCodeFiddling(pVCpu, rcStrict);
    6646 #endif
    6647     }
    6648 
    6649     /*
    6650      * Maybe re-enter raw-mode and log.
    6651      */
    6652     if (rcStrict != VINF_SUCCESS)
    6653         LogFlow(("IEMExecForExits: cs:rip=%04x:%08RX64 ss:rsp=%04x:%08RX64 EFL=%06x - rcStrict=%Rrc; ins=%u exits=%u maxdist=%u\n",
    6654                  pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.ss.Sel, pVCpu->cpum.GstCtx.rsp,
    6655                  pVCpu->cpum.GstCtx.eflags.u, VBOXSTRICTRC_VAL(rcStrict), pStats->cInstructions, pStats->cExits, pStats->cMaxExitDistance));
    6656     return rcStrict;
    6657 }
    6658 
    6659 
    6660 /**
    6661  * Injects a trap, fault, abort, software interrupt or external interrupt.
    6662  *
    6663  * The parameter list matches TRPMQueryTrapAll pretty closely.
    6664  *
    6665  * @returns Strict VBox status code.
    6666  * @param   pVCpu               The cross context virtual CPU structure of the calling EMT.
    6667  * @param   u8TrapNo            The trap number.
    6668  * @param   enmType             What type is it (trap/fault/abort), software
    6669  *                              interrupt or hardware interrupt.
    6670  * @param   uErrCode            The error code if applicable.
    6671  * @param   uCr2                The CR2 value if applicable.
    6672  * @param   cbInstr             The instruction length (only relevant for
    6673  *                              software interrupts).
    6674  * @note    x86 specific, but difficult to move due to iemInitDecoder dep.
    6675  */
    6676 VMM_INT_DECL(VBOXSTRICTRC) IEMInjectTrap(PVMCPUCC pVCpu, uint8_t u8TrapNo, TRPMEVENT enmType, uint16_t uErrCode, RTGCPTR uCr2,
    6677                                          uint8_t cbInstr)
    6678 {
    6679     iemInitDecoder(pVCpu, 0 /*fExecOpts*/); /** @todo wrong init function! */
    6680 #ifdef DBGFTRACE_ENABLED
    6681     RTTraceBufAddMsgF(pVCpu->CTX_SUFF(pVM)->CTX_SUFF(hTraceBuf), "IEMInjectTrap: %x %d %x %llx",
    6682                       u8TrapNo, enmType, uErrCode, uCr2);
    6683 #endif
    6684 
    6685     uint32_t fFlags;
    6686     switch (enmType)
    6687     {
    6688         case TRPM_HARDWARE_INT:
    6689             Log(("IEMInjectTrap: %#4x ext\n", u8TrapNo));
    6690             fFlags = IEM_XCPT_FLAGS_T_EXT_INT;
    6691             uErrCode = uCr2 = 0;
    6692             break;
    6693 
    6694         case TRPM_SOFTWARE_INT:
    6695             Log(("IEMInjectTrap: %#4x soft\n", u8TrapNo));
    6696             fFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
    6697             uErrCode = uCr2 = 0;
    6698             break;
    6699 
    6700         case TRPM_TRAP:
    6701         case TRPM_NMI: /** @todo Distinguish NMI from exception 2. */
    6702             Log(("IEMInjectTrap: %#4x trap err=%#x cr2=%#RGv\n", u8TrapNo, uErrCode, uCr2));
    6703             fFlags = IEM_XCPT_FLAGS_T_CPU_XCPT;
    6704             if (u8TrapNo == X86_XCPT_PF)
    6705                 fFlags |= IEM_XCPT_FLAGS_CR2;
    6706             switch (u8TrapNo)
    6707             {
    6708                 case X86_XCPT_DF:
    6709                 case X86_XCPT_TS:
    6710                 case X86_XCPT_NP:
    6711                 case X86_XCPT_SS:
    6712                 case X86_XCPT_PF:
    6713                 case X86_XCPT_AC:
    6714                 case X86_XCPT_GP:
    6715                     fFlags |= IEM_XCPT_FLAGS_ERR;
    6716                     break;
    6717             }
    6718             break;
    6719 
    6720         IEM_NOT_REACHED_DEFAULT_CASE_RET();
    6721     }
    6722 
    6723     VBOXSTRICTRC rcStrict = iemRaiseXcptOrInt(pVCpu, cbInstr, u8TrapNo, fFlags, uErrCode, uCr2);
    6724 
    6725     if (pVCpu->iem.s.cActiveMappings > 0)
    6726         iemMemRollback(pVCpu);
    6727 
    6728     return rcStrict;
    6729 }
    6730 
    6731 
    6732 /**
    6733  * Injects the active TRPM event.
    6734  *
    6735  * @returns Strict VBox status code.
    6736  * @param   pVCpu               The cross context virtual CPU structure.
    6737  */
    6738 VMM_INT_DECL(VBOXSTRICTRC) IEMInjectTrpmEvent(PVMCPUCC pVCpu)
    6739 {
    6740 #ifndef IEM_IMPLEMENTS_TASKSWITCH
    6741     IEM_RETURN_ASPECT_NOT_IMPLEMENTED_LOG(("Event injection\n"));
    6742 #else
    6743     uint8_t     u8TrapNo;
    6744     TRPMEVENT   enmType;
    6745     uint32_t    uErrCode;
    6746     RTGCUINTPTR uCr2;
    6747     uint8_t     cbInstr;
    6748     int rc = TRPMQueryTrapAll(pVCpu, &u8TrapNo, &enmType, &uErrCode, &uCr2, &cbInstr, NULL /* fIcebp */);
    6749     if (RT_FAILURE(rc))
    6750         return rc;
    6751 
    6752     /** @todo r=ramshankar: Pass ICEBP info. to IEMInjectTrap() below and handle
    6753      *        ICEBP \#DB injection as a special case. */
    6754     VBOXSTRICTRC rcStrict = IEMInjectTrap(pVCpu, u8TrapNo, enmType, uErrCode, uCr2, cbInstr);
    6755 #ifdef VBOX_WITH_NESTED_HWVIRT_SVM
    6756     if (rcStrict == VINF_SVM_VMEXIT)
    6757         rcStrict = VINF_SUCCESS;
    6758 #endif
    6759 #ifdef VBOX_WITH_NESTED_HWVIRT_VMX
    6760     if (rcStrict == VINF_VMX_VMEXIT)
    6761         rcStrict = VINF_SUCCESS;
    6762 #endif
    6763     /** @todo Are there any other codes that imply the event was successfully
    6764      *        delivered to the guest? See @bugref{6607}.  */
    6765     if (   rcStrict == VINF_SUCCESS
    6766         || rcStrict == VINF_IEM_RAISED_XCPT)
    6767         TRPMResetTrap(pVCpu);
    6768 
    6769     return rcStrict;
    6770 #endif
    6771 }
    6772 
    6773 
    6774 VMM_INT_DECL(int) IEMBreakpointSet(PVM pVM, RTGCPTR GCPtrBp)
    6775 {
    6776     RT_NOREF_PV(pVM); RT_NOREF_PV(GCPtrBp);
    6777     return VERR_NOT_IMPLEMENTED;
    6778 }
    6779 
    6780 
    6781 VMM_INT_DECL(int) IEMBreakpointClear(PVM pVM, RTGCPTR GCPtrBp)
    6782 {
    6783     RT_NOREF_PV(pVM); RT_NOREF_PV(GCPtrBp);
    6784     return VERR_NOT_IMPLEMENTED;
    6785 }
    6786 
    6787 #ifdef IN_RING3
    6788 
    6789 /**
    6790  * Handles the unlikely and probably fatal merge cases.
    6791  *
    6792  * @returns Merged status code.
    6793  * @param   rcStrict        Current EM status code.
    6794  * @param   rcStrictCommit  The IOM I/O or MMIO write commit status to merge
    6795  *                          with @a rcStrict.
    6796  * @param   iMemMap         The memory mapping index. For error reporting only.
    6797  * @param   pVCpu           The cross context virtual CPU structure of the calling
    6798  *                          thread, for error reporting only.
    6799  */
    6800 DECL_NO_INLINE(static, VBOXSTRICTRC) iemR3MergeStatusSlow(VBOXSTRICTRC rcStrict, VBOXSTRICTRC rcStrictCommit,
    6801                                                           unsigned iMemMap, PVMCPUCC pVCpu)
    6802 {
    6803     if (RT_FAILURE_NP(rcStrict))
    6804         return rcStrict;
    6805 
    6806     if (RT_FAILURE_NP(rcStrictCommit))
    6807         return rcStrictCommit;
    6808 
    6809     if (rcStrict == rcStrictCommit)
    6810         return rcStrictCommit;
    6811 
    6812     AssertLogRelMsgFailed(("rcStrictCommit=%Rrc rcStrict=%Rrc iMemMap=%u fAccess=%#x FirstPg=%RGp LB %u SecondPg=%RGp LB %u\n",
    6813                            VBOXSTRICTRC_VAL(rcStrictCommit), VBOXSTRICTRC_VAL(rcStrict), iMemMap,
    6814                            pVCpu->iem.s.aMemMappings[iMemMap].fAccess,
    6815                            pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysFirst, pVCpu->iem.s.aMemBbMappings[iMemMap].cbFirst,
    6816                            pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysSecond, pVCpu->iem.s.aMemBbMappings[iMemMap].cbSecond));
    6817     return VERR_IOM_FF_STATUS_IPE;
    6818 }
    6819 
    6820 
    6821 /**
    6822  * Helper for IOMR3ProcessForceFlag.
    6823  *
    6824  * @returns Merged status code.
    6825  * @param   rcStrict        Current EM status code.
    6826  * @param   rcStrictCommit  The IOM I/O or MMIO write commit status to merge
    6827  *                          with @a rcStrict.
    6828  * @param   iMemMap         The memory mapping index. For error reporting only.
    6829  * @param   pVCpu           The cross context virtual CPU structure of the calling
    6830  *                          thread, for error reporting only.
    6831  */
    6832 DECLINLINE(VBOXSTRICTRC) iemR3MergeStatus(VBOXSTRICTRC rcStrict, VBOXSTRICTRC rcStrictCommit, unsigned iMemMap, PVMCPUCC pVCpu)
    6833 {
    6834     /* Simple. */
    6835     if (RT_LIKELY(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RAW_TO_R3))
    6836         return rcStrictCommit;
    6837 
    6838     if (RT_LIKELY(rcStrictCommit == VINF_SUCCESS))
    6839         return rcStrict;
    6840 
    6841     /* EM scheduling status codes. */
    6842     if (RT_LIKELY(   rcStrict >= VINF_EM_FIRST
    6843                   && rcStrict <= VINF_EM_LAST))
    6844     {
    6845         if (RT_LIKELY(   rcStrictCommit >= VINF_EM_FIRST
    6846                       && rcStrictCommit <= VINF_EM_LAST))
    6847             return rcStrict < rcStrictCommit ? rcStrict : rcStrictCommit;
    6848     }
    6849 
    6850     /* Unlikely */
    6851     return iemR3MergeStatusSlow(rcStrict, rcStrictCommit, iMemMap, pVCpu);
    6852 }
    6853 
    6854 
    6855 /**
    6856  * Called by force-flag handling code when VMCPU_FF_IEM is set.
    6857  *
    6858  * @returns Merge between @a rcStrict and what the commit operation returned.
    6859  * @param   pVM         The cross context VM structure.
    6860  * @param   pVCpu       The cross context virtual CPU structure of the calling EMT.
    6861  * @param   rcStrict    The status code returned by ring-0 or raw-mode.
    6862  */
    6863 VMMR3_INT_DECL(VBOXSTRICTRC) IEMR3ProcessForceFlag(PVM pVM, PVMCPUCC pVCpu, VBOXSTRICTRC rcStrict)
    6864 {
    6865     /*
    6866      * Reset the pending commit.
    6867      */
    6868     AssertMsg(  (pVCpu->iem.s.aMemMappings[0].fAccess | pVCpu->iem.s.aMemMappings[1].fAccess | pVCpu->iem.s.aMemMappings[2].fAccess)
    6869               & (IEM_ACCESS_PENDING_R3_WRITE_1ST | IEM_ACCESS_PENDING_R3_WRITE_2ND),
    6870               ("%#x %#x %#x\n",
    6871                pVCpu->iem.s.aMemMappings[0].fAccess, pVCpu->iem.s.aMemMappings[1].fAccess, pVCpu->iem.s.aMemMappings[2].fAccess));
    6872     VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_IEM);
    6873 
    6874     /*
    6875      * Commit the pending bounce buffers (usually just one).
    6876      */
    6877     unsigned cBufs = 0;
    6878     unsigned iMemMap = RT_ELEMENTS(pVCpu->iem.s.aMemMappings);
    6879     while (iMemMap-- > 0)
    6880         if (pVCpu->iem.s.aMemMappings[iMemMap].fAccess & (IEM_ACCESS_PENDING_R3_WRITE_1ST | IEM_ACCESS_PENDING_R3_WRITE_2ND))
    6881         {
    6882             Assert(pVCpu->iem.s.aMemMappings[iMemMap].fAccess & IEM_ACCESS_TYPE_WRITE);
    6883             Assert(pVCpu->iem.s.aMemMappings[iMemMap].fAccess & IEM_ACCESS_BOUNCE_BUFFERED);
    6884             Assert(!pVCpu->iem.s.aMemBbMappings[iMemMap].fUnassigned);
    6885 
    6886             uint16_t const  cbFirst  = pVCpu->iem.s.aMemBbMappings[iMemMap].cbFirst;
    6887             uint16_t const  cbSecond = pVCpu->iem.s.aMemBbMappings[iMemMap].cbSecond;
    6888             uint8_t const  *pbBuf    = &pVCpu->iem.s.aBounceBuffers[iMemMap].ab[0];
    6889 
    6890             if (pVCpu->iem.s.aMemMappings[iMemMap].fAccess & IEM_ACCESS_PENDING_R3_WRITE_1ST)
    6891             {
    6892                 VBOXSTRICTRC rcStrictCommit1 = PGMPhysWrite(pVM,
    6893                                                             pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysFirst,
    6894                                                             pbBuf,
    6895                                                             cbFirst,
    6896                                                             PGMACCESSORIGIN_IEM);
    6897                 rcStrict = iemR3MergeStatus(rcStrict, rcStrictCommit1, iMemMap, pVCpu);
    6898                 Log(("IEMR3ProcessForceFlag: iMemMap=%u GCPhysFirst=%RGp LB %#x %Rrc => %Rrc\n",
    6899                      iMemMap, pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysFirst, cbFirst,
    6900                      VBOXSTRICTRC_VAL(rcStrictCommit1), VBOXSTRICTRC_VAL(rcStrict)));
    6901             }
    6902 
    6903             if (pVCpu->iem.s.aMemMappings[iMemMap].fAccess & IEM_ACCESS_PENDING_R3_WRITE_2ND)
    6904             {
    6905                 VBOXSTRICTRC rcStrictCommit2 = PGMPhysWrite(pVM,
    6906                                                             pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysSecond,
    6907                                                             pbBuf + cbFirst,
    6908                                                             cbSecond,
    6909                                                             PGMACCESSORIGIN_IEM);
    6910                 rcStrict = iemR3MergeStatus(rcStrict, rcStrictCommit2, iMemMap, pVCpu);
    6911                 Log(("IEMR3ProcessForceFlag: iMemMap=%u GCPhysSecond=%RGp LB %#x %Rrc => %Rrc\n",
    6912                      iMemMap, pVCpu->iem.s.aMemBbMappings[iMemMap].GCPhysSecond, cbSecond,
    6913                      VBOXSTRICTRC_VAL(rcStrictCommit2), VBOXSTRICTRC_VAL(rcStrict)));
    6914             }
    6915             cBufs++;
    6916             pVCpu->iem.s.aMemMappings[iMemMap].fAccess = IEM_ACCESS_INVALID;
    6917         }
    6918 
    6919     AssertMsg(cBufs > 0 && cBufs == pVCpu->iem.s.cActiveMappings,
    6920               ("cBufs=%u cActiveMappings=%u - %#x %#x %#x\n", cBufs, pVCpu->iem.s.cActiveMappings,
    6921                pVCpu->iem.s.aMemMappings[0].fAccess, pVCpu->iem.s.aMemMappings[1].fAccess, pVCpu->iem.s.aMemMappings[2].fAccess));
    6922     pVCpu->iem.s.cActiveMappings = 0;
    6923     return rcStrict;
    6924 }
    6925 
    6926 #endif /* IN_RING3 */
    6927 
Note: See TracChangeset for help on using the changeset viewer.

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