VirtualBox

Changeset 56072 in vbox


Ignore:
Timestamp:
May 26, 2015 11:26:35 AM (10 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
100594
Message:

IOM: Moved some RC code into IOMRC.cpp.

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/iom.h

    r53615 r56072  
    271271VMMDECL(VBOXSTRICTRC)   IOMIOPortRead(PVM pVM, PVMCPU pVCpu, RTIOPORT Port, uint32_t *pu32Value, size_t cbValue);
    272272VMMDECL(VBOXSTRICTRC)   IOMIOPortWrite(PVM pVM, PVMCPU pVCpu, RTIOPORT Port, uint32_t u32Value, size_t cbValue);
    273 VMMDECL(VBOXSTRICTRC)   IOMInterpretOUT(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu);
    274 VMMDECL(VBOXSTRICTRC)   IOMInterpretIN(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu);
    275273VMMDECL(VBOXSTRICTRC)   IOMIOPortReadString(PVM pVM, PVMCPU pVCpu, RTIOPORT Port, PRTGCPTR pGCPtrDst, PRTGCUINTREG pcTransfers, unsigned cb);
    276274VMMDECL(VBOXSTRICTRC)   IOMIOPortWriteString(PVM pVM, PVMCPU pVCpu, RTIOPORT Port, PRTGCPTR pGCPtrSrc, PRTGCUINTREG pcTransfers, unsigned cb);
    277 VMMDECL(VBOXSTRICTRC)   IOMInterpretINS(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu);
    278275VMMDECL(VBOXSTRICTRC)   IOMInterpretINSEx(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t uPort, uint32_t uPrefix, DISCPUMODE enmAddrMode, uint32_t cbTransfer);
    279 VMMDECL(VBOXSTRICTRC)   IOMInterpretOUTS(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu);
    280276VMMDECL(VBOXSTRICTRC)   IOMInterpretOUTSEx(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t uPort, uint32_t uPrefix, DISCPUMODE enmAddrMode, uint32_t cbTransfer);
    281277VMMDECL(VBOXSTRICTRC)   IOMMMIORead(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, uint32_t *pu32Value, size_t cbValue);
  • trunk/src/VBox/VMM/VMMAll/IOMAll.cpp

    r55816 r56072  
    5757
    5858
    59 /**
    60  * Returns the contents of register or immediate data of instruction's parameter.
    61  *
    62  * @returns true on success.
    63  *
    64  * @todo Get rid of this code. Use DISQueryParamVal instead
    65  *
    66  * @param   pCpu                Pointer to current disassembler context.
    67  * @param   pParam              Pointer to parameter of instruction to process.
    68  * @param   pRegFrame           Pointer to CPUMCTXCORE guest structure.
    69  * @param   pu64Data            Where to store retrieved data.
    70  * @param   pcbSize             Where to store the size of data (1, 2, 4, 8).
    71  */
    72 bool iomGetRegImmData(PDISCPUSTATE pCpu, PCDISOPPARAM pParam, PCPUMCTXCORE pRegFrame, uint64_t *pu64Data, unsigned *pcbSize)
    73 {
    74     NOREF(pCpu);
    75     if (pParam->fUse & (DISUSE_BASE | DISUSE_INDEX | DISUSE_SCALE | DISUSE_DISPLACEMENT8 | DISUSE_DISPLACEMENT16 | DISUSE_DISPLACEMENT32))
    76     {
    77         *pcbSize  = 0;
    78         *pu64Data = 0;
    79         return false;
    80     }
    81 
    82     /* divide and conquer */
    83     if (pParam->fUse & (DISUSE_REG_GEN64 | DISUSE_REG_GEN32 | DISUSE_REG_GEN16 | DISUSE_REG_GEN8))
    84     {
    85         if (pParam->fUse & DISUSE_REG_GEN32)
    86         {
    87             *pcbSize  = 4;
    88             DISFetchReg32(pRegFrame, pParam->Base.idxGenReg, (uint32_t *)pu64Data);
    89             return true;
    90         }
    91 
    92         if (pParam->fUse & DISUSE_REG_GEN16)
    93         {
    94             *pcbSize  = 2;
    95             DISFetchReg16(pRegFrame, pParam->Base.idxGenReg, (uint16_t *)pu64Data);
    96             return true;
    97         }
    98 
    99         if (pParam->fUse & DISUSE_REG_GEN8)
    100         {
    101             *pcbSize  = 1;
    102             DISFetchReg8(pRegFrame, pParam->Base.idxGenReg, (uint8_t *)pu64Data);
    103             return true;
    104         }
    105 
    106         Assert(pParam->fUse & DISUSE_REG_GEN64);
    107         *pcbSize  = 8;
    108         DISFetchReg64(pRegFrame, pParam->Base.idxGenReg, pu64Data);
    109         return true;
    110     }
    111     else
    112     {
    113         if (pParam->fUse & (DISUSE_IMMEDIATE64 | DISUSE_IMMEDIATE64_SX8))
    114         {
    115             *pcbSize  = 8;
    116             *pu64Data = pParam->uValue;
    117             return true;
    118         }
    119 
    120         if (pParam->fUse & (DISUSE_IMMEDIATE32 | DISUSE_IMMEDIATE32_SX8))
    121         {
    122             *pcbSize  = 4;
    123             *pu64Data = (uint32_t)pParam->uValue;
    124             return true;
    125         }
    126 
    127         if (pParam->fUse & (DISUSE_IMMEDIATE16 | DISUSE_IMMEDIATE16_SX8))
    128         {
    129             *pcbSize  = 2;
    130             *pu64Data = (uint16_t)pParam->uValue;
    131             return true;
    132         }
    133 
    134         if (pParam->fUse & DISUSE_IMMEDIATE8)
    135         {
    136             *pcbSize  = 1;
    137             *pu64Data = (uint8_t)pParam->uValue;
    138             return true;
    139         }
    140 
    141         if (pParam->fUse & DISUSE_REG_SEG)
    142         {
    143             *pcbSize  = 2;
    144             DISFetchRegSeg(pRegFrame, (DISSELREG)pParam->Base.idxSegReg, (RTSEL *)pu64Data);
    145             return true;
    146         } /* Else - error. */
    147 
    148         AssertFailed();
    149         *pcbSize  = 0;
    150         *pu64Data = 0;
    151         return false;
    152     }
    153 }
    154 
    155 
    156 /**
    157  * Saves data to 8/16/32 general purpose or segment register defined by
    158  * instruction's parameter.
    159  *
    160  * @returns true on success.
    161  * @param   pCpu                Pointer to current disassembler context.
    162  * @param   pParam              Pointer to parameter of instruction to process.
    163  * @param   pRegFrame           Pointer to CPUMCTXCORE guest structure.
    164  * @param   u64Data             8/16/32/64 bit data to store.
    165  */
    166 bool iomSaveDataToReg(PDISCPUSTATE pCpu, PCDISOPPARAM pParam, PCPUMCTXCORE pRegFrame, uint64_t u64Data)
    167 {
    168     NOREF(pCpu);
    169     if (pParam->fUse & (DISUSE_BASE | DISUSE_INDEX | DISUSE_SCALE | DISUSE_DISPLACEMENT8 | DISUSE_DISPLACEMENT16 | DISUSE_DISPLACEMENT32 | DISUSE_DISPLACEMENT64 | DISUSE_IMMEDIATE8 | DISUSE_IMMEDIATE16 | DISUSE_IMMEDIATE32 | DISUSE_IMMEDIATE32_SX8 | DISUSE_IMMEDIATE16_SX8))
    170     {
    171         return false;
    172     }
    173 
    174     if (pParam->fUse & DISUSE_REG_GEN32)
    175     {
    176         DISWriteReg32(pRegFrame, pParam->Base.idxGenReg, (uint32_t)u64Data);
    177         return true;
    178     }
    179 
    180     if (pParam->fUse & DISUSE_REG_GEN64)
    181     {
    182         DISWriteReg64(pRegFrame, pParam->Base.idxGenReg, u64Data);
    183         return true;
    184     }
    185 
    186     if (pParam->fUse & DISUSE_REG_GEN16)
    187     {
    188         DISWriteReg16(pRegFrame, pParam->Base.idxGenReg, (uint16_t)u64Data);
    189         return true;
    190     }
    191 
    192     if (pParam->fUse & DISUSE_REG_GEN8)
    193     {
    194         DISWriteReg8(pRegFrame, pParam->Base.idxGenReg, (uint8_t)u64Data);
    195         return true;
    196     }
    197 
    198     if (pParam->fUse & DISUSE_REG_SEG)
    199     {
    200         DISWriteRegSeg(pRegFrame, (DISSELREG)pParam->Base.idxSegReg, (RTSEL)u64Data);
    201         return true;
    202     }
    203 
    204     /* Else - error. */
    205     return false;
    206 }
    207 
    208 
    20959//#undef LOG_GROUP
    21060//#define LOG_GROUP LOG_GROUP_IOM_IOPORT
     
    893743
    894744/**
    895  * IN <AL|AX|EAX>, <DX|imm16>
    896  *
    897  * @returns Strict VBox status code. Informational status codes other than the one documented
    898  *          here are to be treated as internal failure. Use IOM_SUCCESS() to check for success.
    899  * @retval  VINF_SUCCESS                Success.
    900  * @retval  VINF_EM_FIRST-VINF_EM_LAST  Success with some exceptions (see IOM_SUCCESS()), the
    901  *                                      status code must be passed on to EM.
    902  * @retval  VINF_IOM_R3_IOPORT_READ     Defer the read to ring-3. (R0/GC only)
    903  * @retval  VINF_EM_RAW_GUEST_TRAP      The exception was left pending. (TRPMRaiseXcptErr)
    904  * @retval  VINF_TRPM_XCPT_DISPATCHED   The exception was raised and dispatched for raw-mode execution. (TRPMRaiseXcptErr)
    905  * @retval  VINF_EM_RESCHEDULE_REM      The exception was dispatched and cannot be executed in raw-mode. (TRPMRaiseXcptErr)
    906  *
    907  * @param   pVM         The virtual machine (GC pointer of course).
    908  * @param   pVCpu       Pointer to the virtual CPU structure of the caller.
    909  * @param   pRegFrame   Pointer to CPUMCTXCORE guest registers structure.
    910  * @param   pCpu        Disassembler CPU state.
    911  */
    912 VMMDECL(VBOXSTRICTRC) IOMInterpretIN(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu)
    913 {
    914 #ifdef IN_RC
    915     STAM_COUNTER_INC(&pVM->iom.s.StatInstIn);
    916 #endif
    917 
    918     /*
    919      * Get port number from second parameter.
    920      * And get the register size from the first parameter.
    921      */
    922     uint64_t    uPort = 0;
    923     unsigned    cbSize = 0;
    924     bool fRc = iomGetRegImmData(pCpu, &pCpu->Param2, pRegFrame, &uPort, &cbSize);
    925     AssertMsg(fRc, ("Failed to get reg/imm port number!\n")); NOREF(fRc);
    926 
    927     cbSize = DISGetParamSize(pCpu, &pCpu->Param1);
    928     Assert(cbSize > 0);
    929     VBOXSTRICTRC rcStrict = IOMInterpretCheckPortIOAccess(pVM, pRegFrame, uPort, cbSize);
    930     if (rcStrict == VINF_SUCCESS)
    931     {
    932         /*
    933          * Attempt to read the port.
    934          */
    935         uint32_t u32Data = UINT32_C(0xffffffff);
    936         rcStrict = IOMIOPortRead(pVM, pVCpu, uPort, &u32Data, cbSize);
    937         if (IOM_SUCCESS(rcStrict))
    938         {
    939             /*
    940              * Store the result in the AL|AX|EAX register.
    941              */
    942             fRc = iomSaveDataToReg(pCpu, &pCpu->Param1, pRegFrame, u32Data);
    943             AssertMsg(fRc, ("Failed to store register value!\n")); NOREF(fRc);
    944         }
    945         else
    946             AssertMsg(rcStrict == VINF_IOM_R3_IOPORT_READ || RT_FAILURE(rcStrict), ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
    947     }
    948     else
    949         AssertMsg(rcStrict == VINF_EM_RAW_GUEST_TRAP || rcStrict == VINF_TRPM_XCPT_DISPATCHED || RT_FAILURE(rcStrict), ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
    950 
    951     return rcStrict;
    952 }
    953 
    954 
    955 /**
    956  * OUT <DX|imm16>, <AL|AX|EAX>
    957  *
    958  * @returns Strict VBox status code. Informational status codes other than the one documented
    959  *          here are to be treated as internal failure. Use IOM_SUCCESS() to check for success.
    960  * @retval  VINF_SUCCESS                Success.
    961  * @retval  VINF_EM_FIRST-VINF_EM_LAST  Success with some exceptions (see IOM_SUCCESS()), the
    962  *                                      status code must be passed on to EM.
    963  * @retval  VINF_IOM_R3_IOPORT_WRITE    Defer the write to ring-3. (R0/GC only)
    964  * @retval  VINF_EM_RAW_GUEST_TRAP      The exception was left pending. (TRPMRaiseXcptErr)
    965  * @retval  VINF_TRPM_XCPT_DISPATCHED   The exception was raised and dispatched for raw-mode execution. (TRPMRaiseXcptErr)
    966  * @retval  VINF_EM_RESCHEDULE_REM      The exception was dispatched and cannot be executed in raw-mode. (TRPMRaiseXcptErr)
    967  *
    968  * @param   pVM         The virtual machine (GC pointer of course).
    969  * @param   pVCpu       Pointer to the virtual CPU structure of the caller.
    970  * @param   pRegFrame   Pointer to CPUMCTXCORE guest registers structure.
    971  * @param   pCpu        Disassembler CPU state.
    972  */
    973 VMMDECL(VBOXSTRICTRC) IOMInterpretOUT(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu)
    974 {
    975 #ifdef IN_RC
    976     STAM_COUNTER_INC(&pVM->iom.s.StatInstOut);
    977 #endif
    978 
    979     /*
    980      * Get port number from first parameter.
    981      * And get the register size and value from the second parameter.
    982      */
    983     uint64_t    uPort = 0;
    984     unsigned    cbSize = 0;
    985     bool fRc = iomGetRegImmData(pCpu, &pCpu->Param1, pRegFrame, &uPort, &cbSize);
    986     AssertMsg(fRc, ("Failed to get reg/imm port number!\n")); NOREF(fRc);
    987 
    988     VBOXSTRICTRC rcStrict = IOMInterpretCheckPortIOAccess(pVM, pRegFrame, uPort, cbSize);
    989     if (rcStrict == VINF_SUCCESS)
    990     {
    991         uint64_t u64Data = 0;
    992         fRc = iomGetRegImmData(pCpu, &pCpu->Param2, pRegFrame, &u64Data, &cbSize);
    993         AssertMsg(fRc, ("Failed to get reg value!\n")); NOREF(fRc);
    994 
    995         /*
    996          * Attempt to write to the port.
    997          */
    998         rcStrict = IOMIOPortWrite(pVM, pVCpu, uPort, u64Data, cbSize);
    999         AssertMsg(rcStrict == VINF_SUCCESS || rcStrict == VINF_IOM_R3_IOPORT_WRITE || (rcStrict >= VINF_EM_FIRST && rcStrict <= VINF_EM_LAST) || RT_FAILURE(rcStrict), ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
    1000     }
    1001     else
    1002         AssertMsg(rcStrict == VINF_EM_RAW_GUEST_TRAP || rcStrict == VINF_TRPM_XCPT_DISPATCHED || RT_FAILURE(rcStrict), ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
    1003     return rcStrict;
    1004 }
    1005 
    1006 
    1007 /**
    1008745 * Fress an MMIO range after the reference counter has become zero.
    1009746 *
  • trunk/src/VBox/VMM/VMMAll/IOMAllMMIO.cpp

    r56064 r56072  
    7474 */
    7575#define SIZE_2_SHIFT(cb)    (g_aSize2Shift[cb])
     76
     77
     78/**
     79 * Returns the contents of register or immediate data of instruction's parameter.
     80 *
     81 * @returns true on success.
     82 *
     83 * @todo Get rid of this code. Use DISQueryParamVal instead
     84 *
     85 * @param   pCpu                Pointer to current disassembler context.
     86 * @param   pParam              Pointer to parameter of instruction to process.
     87 * @param   pRegFrame           Pointer to CPUMCTXCORE guest structure.
     88 * @param   pu64Data            Where to store retrieved data.
     89 * @param   pcbSize             Where to store the size of data (1, 2, 4, 8).
     90 */
     91bool iomGetRegImmData(PDISCPUSTATE pCpu, PCDISOPPARAM pParam, PCPUMCTXCORE pRegFrame, uint64_t *pu64Data, unsigned *pcbSize)
     92{
     93    NOREF(pCpu);
     94    if (pParam->fUse & (DISUSE_BASE | DISUSE_INDEX | DISUSE_SCALE | DISUSE_DISPLACEMENT8 | DISUSE_DISPLACEMENT16 | DISUSE_DISPLACEMENT32))
     95    {
     96        *pcbSize  = 0;
     97        *pu64Data = 0;
     98        return false;
     99    }
     100
     101    /* divide and conquer */
     102    if (pParam->fUse & (DISUSE_REG_GEN64 | DISUSE_REG_GEN32 | DISUSE_REG_GEN16 | DISUSE_REG_GEN8))
     103    {
     104        if (pParam->fUse & DISUSE_REG_GEN32)
     105        {
     106            *pcbSize  = 4;
     107            DISFetchReg32(pRegFrame, pParam->Base.idxGenReg, (uint32_t *)pu64Data);
     108            return true;
     109        }
     110
     111        if (pParam->fUse & DISUSE_REG_GEN16)
     112        {
     113            *pcbSize  = 2;
     114            DISFetchReg16(pRegFrame, pParam->Base.idxGenReg, (uint16_t *)pu64Data);
     115            return true;
     116        }
     117
     118        if (pParam->fUse & DISUSE_REG_GEN8)
     119        {
     120            *pcbSize  = 1;
     121            DISFetchReg8(pRegFrame, pParam->Base.idxGenReg, (uint8_t *)pu64Data);
     122            return true;
     123        }
     124
     125        Assert(pParam->fUse & DISUSE_REG_GEN64);
     126        *pcbSize  = 8;
     127        DISFetchReg64(pRegFrame, pParam->Base.idxGenReg, pu64Data);
     128        return true;
     129    }
     130    else
     131    {
     132        if (pParam->fUse & (DISUSE_IMMEDIATE64 | DISUSE_IMMEDIATE64_SX8))
     133        {
     134            *pcbSize  = 8;
     135            *pu64Data = pParam->uValue;
     136            return true;
     137        }
     138
     139        if (pParam->fUse & (DISUSE_IMMEDIATE32 | DISUSE_IMMEDIATE32_SX8))
     140        {
     141            *pcbSize  = 4;
     142            *pu64Data = (uint32_t)pParam->uValue;
     143            return true;
     144        }
     145
     146        if (pParam->fUse & (DISUSE_IMMEDIATE16 | DISUSE_IMMEDIATE16_SX8))
     147        {
     148            *pcbSize  = 2;
     149            *pu64Data = (uint16_t)pParam->uValue;
     150            return true;
     151        }
     152
     153        if (pParam->fUse & DISUSE_IMMEDIATE8)
     154        {
     155            *pcbSize  = 1;
     156            *pu64Data = (uint8_t)pParam->uValue;
     157            return true;
     158        }
     159
     160        if (pParam->fUse & DISUSE_REG_SEG)
     161        {
     162            *pcbSize  = 2;
     163            DISFetchRegSeg(pRegFrame, (DISSELREG)pParam->Base.idxSegReg, (RTSEL *)pu64Data);
     164            return true;
     165        } /* Else - error. */
     166
     167        AssertFailed();
     168        *pcbSize  = 0;
     169        *pu64Data = 0;
     170        return false;
     171    }
     172}
     173
     174
     175/**
     176 * Saves data to 8/16/32 general purpose or segment register defined by
     177 * instruction's parameter.
     178 *
     179 * @returns true on success.
     180 * @param   pCpu                Pointer to current disassembler context.
     181 * @param   pParam              Pointer to parameter of instruction to process.
     182 * @param   pRegFrame           Pointer to CPUMCTXCORE guest structure.
     183 * @param   u64Data             8/16/32/64 bit data to store.
     184 */
     185bool iomSaveDataToReg(PDISCPUSTATE pCpu, PCDISOPPARAM pParam, PCPUMCTXCORE pRegFrame, uint64_t u64Data)
     186{
     187    NOREF(pCpu);
     188    if (pParam->fUse & (DISUSE_BASE | DISUSE_INDEX | DISUSE_SCALE | DISUSE_DISPLACEMENT8 | DISUSE_DISPLACEMENT16 | DISUSE_DISPLACEMENT32 | DISUSE_DISPLACEMENT64 | DISUSE_IMMEDIATE8 | DISUSE_IMMEDIATE16 | DISUSE_IMMEDIATE32 | DISUSE_IMMEDIATE32_SX8 | DISUSE_IMMEDIATE16_SX8))
     189    {
     190        return false;
     191    }
     192
     193    if (pParam->fUse & DISUSE_REG_GEN32)
     194    {
     195        DISWriteReg32(pRegFrame, pParam->Base.idxGenReg, (uint32_t)u64Data);
     196        return true;
     197    }
     198
     199    if (pParam->fUse & DISUSE_REG_GEN64)
     200    {
     201        DISWriteReg64(pRegFrame, pParam->Base.idxGenReg, u64Data);
     202        return true;
     203    }
     204
     205    if (pParam->fUse & DISUSE_REG_GEN16)
     206    {
     207        DISWriteReg16(pRegFrame, pParam->Base.idxGenReg, (uint16_t)u64Data);
     208        return true;
     209    }
     210
     211    if (pParam->fUse & DISUSE_REG_GEN8)
     212    {
     213        DISWriteReg8(pRegFrame, pParam->Base.idxGenReg, (uint8_t)u64Data);
     214        return true;
     215    }
     216
     217    if (pParam->fUse & DISUSE_REG_SEG)
     218    {
     219        DISWriteRegSeg(pRegFrame, (DISSELREG)pParam->Base.idxSegReg, (RTSEL)u64Data);
     220        return true;
     221    }
     222
     223    /* Else - error. */
     224    return false;
     225}
    76226
    77227
     
    22312381
    22322382
    2233 #ifdef IN_RC /* Latter for IOMRCIOPortHandler */
    2234 /**
    2235  * [REP*] INSB/INSW/INSD
    2236  * ES:EDI,DX[,ECX]
    2237  *
    2238  * @returns Strict VBox status code. Informational status codes other than the one documented
    2239  *          here are to be treated as internal failure. Use IOM_SUCCESS() to check for success.
    2240  * @retval  VINF_SUCCESS                Success.
    2241  * @retval  VINF_EM_FIRST-VINF_EM_LAST  Success with some exceptions (see IOM_SUCCESS()), the
    2242  *                                      status code must be passed on to EM.
    2243  * @retval  VINF_IOM_R3_IOPORT_READ     Defer the read to ring-3. (R0/GC only)
    2244  * @retval  VINF_EM_RAW_EMULATE_INSTR   Defer the read to the REM.
    2245  * @retval  VINF_EM_RAW_GUEST_TRAP      The exception was left pending. (TRPMRaiseXcptErr)
    2246  * @retval  VINF_TRPM_XCPT_DISPATCHED   The exception was raised and dispatched for raw-mode execution. (TRPMRaiseXcptErr)
    2247  * @retval  VINF_EM_RESCHEDULE_REM      The exception was dispatched and cannot be executed in raw-mode. (TRPMRaiseXcptErr)
    2248  *
    2249  * @param   pVM         The virtual machine.
    2250  * @param   pVCpu       Pointer to the virtual CPU structure of the caller.
    2251  * @param   pRegFrame   Pointer to CPUMCTXCORE guest registers structure.
    2252  * @param   pCpu        Disassembler CPU state.
    2253  */
    2254 VMMDECL(VBOXSTRICTRC) IOMInterpretINS(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu)
    2255 {
    2256     /*
    2257      * Get port number directly from the register (no need to bother the
    2258      * disassembler). And get the I/O register size from the opcode / prefix.
    2259      */
    2260     RTIOPORT    Port = pRegFrame->edx & 0xffff;
    2261     unsigned    cb = 0;
    2262     if (pCpu->pCurInstr->uOpcode == OP_INSB)
    2263         cb = 1;
    2264     else
    2265         cb = (pCpu->uOpMode == DISCPUMODE_16BIT) ? 2 : 4;       /* dword in both 32 & 64 bits mode */
    2266 
    2267     VBOXSTRICTRC rcStrict = IOMInterpretCheckPortIOAccess(pVM, pRegFrame, Port, cb);
    2268     if (RT_UNLIKELY(rcStrict != VINF_SUCCESS))
    2269     {
    2270         AssertMsg(rcStrict == VINF_EM_RAW_GUEST_TRAP || rcStrict == VINF_TRPM_XCPT_DISPATCHED || RT_FAILURE(rcStrict), ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
    2271         return rcStrict;
    2272     }
    2273 
    2274     return IOMInterpretINSEx(pVM, pVCpu, pRegFrame, Port, pCpu->fPrefix, (DISCPUMODE)pCpu->uAddrMode, cb);
    2275 }
    2276 #endif /* RC */
    2277 
    2278 
    22792383/**
    22802384 * [REP*] OUTSB/OUTSW/OUTSD
     
    23992503}
    24002504
    2401 
    2402 #ifdef IN_RC /* Latter for IOMRCIOPortHandler */
    2403 /**
    2404  * [REP*] OUTSB/OUTSW/OUTSD
    2405  * DS:ESI,DX[,ECX]
    2406  *
    2407  * @returns Strict VBox status code. Informational status codes other than the one documented
    2408  *          here are to be treated as internal failure. Use IOM_SUCCESS() to check for success.
    2409  * @retval  VINF_SUCCESS                Success.
    2410  * @retval  VINF_EM_FIRST-VINF_EM_LAST  Success with some exceptions (see IOM_SUCCESS()), the
    2411  *                                      status code must be passed on to EM.
    2412  * @retval  VINF_IOM_R3_IOPORT_WRITE    Defer the write to ring-3. (R0/GC only)
    2413  * @retval  VINF_EM_RAW_EMULATE_INSTR   Defer the write to the REM.
    2414  * @retval  VINF_EM_RAW_GUEST_TRAP      The exception was left pending. (TRPMRaiseXcptErr)
    2415  * @retval  VINF_TRPM_XCPT_DISPATCHED   The exception was raised and dispatched for raw-mode execution. (TRPMRaiseXcptErr)
    2416  * @retval  VINF_EM_RESCHEDULE_REM      The exception was dispatched and cannot be executed in raw-mode. (TRPMRaiseXcptErr)
    2417  *
    2418  * @param   pVM         The virtual machine.
    2419  * @param   pVCpu       Pointer to the virtual CPU structure of the caller.
    2420  * @param   pRegFrame   Pointer to CPUMCTXCORE guest registers structure.
    2421  * @param   pCpu        Disassembler CPU state.
    2422  */
    2423 VMMDECL(VBOXSTRICTRC) IOMInterpretOUTS(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu)
    2424 {
    2425     /*
    2426      * Get port number from the first parameter.
    2427      * And get the I/O register size from the opcode / prefix.
    2428      */
    2429     uint64_t    Port = 0;
    2430     unsigned    cb = 0;
    2431     bool fRc = iomGetRegImmData(pCpu, &pCpu->Param1, pRegFrame, &Port, &cb);
    2432     AssertMsg(fRc, ("Failed to get reg/imm port number!\n")); NOREF(fRc);
    2433     if (pCpu->pCurInstr->uOpcode == OP_OUTSB)
    2434         cb = 1;
    2435     else
    2436         cb = (pCpu->uOpMode == DISCPUMODE_16BIT) ? 2 : 4;       /* dword in both 32 & 64 bits mode */
    2437 
    2438     VBOXSTRICTRC rcStrict = IOMInterpretCheckPortIOAccess(pVM, pRegFrame, Port, cb);
    2439     if (RT_UNLIKELY(rcStrict != VINF_SUCCESS))
    2440     {
    2441         AssertMsg(rcStrict == VINF_EM_RAW_GUEST_TRAP || rcStrict == VINF_TRPM_XCPT_DISPATCHED || RT_FAILURE(rcStrict), ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
    2442         return rcStrict;
    2443     }
    2444 
    2445     return IOMInterpretOUTSEx(pVM, pVCpu, pRegFrame, Port, pCpu->fPrefix, (DISCPUMODE)pCpu->uAddrMode, cb);
    2446 }
    2447 #endif /* RC */
    24482505
    24492506#ifndef IN_RC
  • trunk/src/VBox/VMM/VMMRC/IOMRC.cpp

    r45305 r56072  
    4444
    4545/**
     46 * IN <AL|AX|EAX>, <DX|imm16>
     47 *
     48 * @returns Strict VBox status code. Informational status codes other than the one documented
     49 *          here are to be treated as internal failure. Use IOM_SUCCESS() to check for success.
     50 * @retval  VINF_SUCCESS                Success.
     51 * @retval  VINF_EM_FIRST-VINF_EM_LAST  Success with some exceptions (see IOM_SUCCESS()), the
     52 *                                      status code must be passed on to EM.
     53 * @retval  VINF_IOM_R3_IOPORT_READ     Defer the read to ring-3. (R0/GC only)
     54 * @retval  VINF_EM_RAW_GUEST_TRAP      The exception was left pending. (TRPMRaiseXcptErr)
     55 * @retval  VINF_TRPM_XCPT_DISPATCHED   The exception was raised and dispatched for raw-mode execution. (TRPMRaiseXcptErr)
     56 * @retval  VINF_EM_RESCHEDULE_REM      The exception was dispatched and cannot be executed in raw-mode. (TRPMRaiseXcptErr)
     57 *
     58 * @param   pVM         The virtual machine (GC pointer of course).
     59 * @param   pVCpu       Pointer to the virtual CPU structure of the caller.
     60 * @param   pRegFrame   Pointer to CPUMCTXCORE guest registers structure.
     61 * @param   pCpu        Disassembler CPU state.
     62 */
     63static VBOXSTRICTRC iomRCInterpretIN(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu)
     64{
     65#ifdef IN_RC
     66    STAM_COUNTER_INC(&pVM->iom.s.StatInstIn);
     67#endif
     68
     69    /*
     70     * Get port number from second parameter.
     71     * And get the register size from the first parameter.
     72     */
     73    uint64_t    uPort = 0;
     74    unsigned    cbSize = 0;
     75    bool fRc = iomGetRegImmData(pCpu, &pCpu->Param2, pRegFrame, &uPort, &cbSize);
     76    AssertMsg(fRc, ("Failed to get reg/imm port number!\n")); NOREF(fRc);
     77
     78    cbSize = DISGetParamSize(pCpu, &pCpu->Param1);
     79    Assert(cbSize > 0);
     80    VBOXSTRICTRC rcStrict = IOMInterpretCheckPortIOAccess(pVM, pRegFrame, uPort, cbSize);
     81    if (rcStrict == VINF_SUCCESS)
     82    {
     83        /*
     84         * Attempt to read the port.
     85         */
     86        uint32_t u32Data = UINT32_C(0xffffffff);
     87        rcStrict = IOMIOPortRead(pVM, pVCpu, uPort, &u32Data, cbSize);
     88        if (IOM_SUCCESS(rcStrict))
     89        {
     90            /*
     91             * Store the result in the AL|AX|EAX register.
     92             */
     93            fRc = iomSaveDataToReg(pCpu, &pCpu->Param1, pRegFrame, u32Data);
     94            AssertMsg(fRc, ("Failed to store register value!\n")); NOREF(fRc);
     95        }
     96        else
     97            AssertMsg(rcStrict == VINF_IOM_R3_IOPORT_READ || RT_FAILURE(rcStrict), ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
     98    }
     99    else
     100        AssertMsg(rcStrict == VINF_EM_RAW_GUEST_TRAP || rcStrict == VINF_TRPM_XCPT_DISPATCHED || RT_FAILURE(rcStrict), ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
     101
     102    return rcStrict;
     103}
     104
     105
     106/**
     107 * OUT <DX|imm16>, <AL|AX|EAX>
     108 *
     109 * @returns Strict VBox status code. Informational status codes other than the one documented
     110 *          here are to be treated as internal failure. Use IOM_SUCCESS() to check for success.
     111 * @retval  VINF_SUCCESS                Success.
     112 * @retval  VINF_EM_FIRST-VINF_EM_LAST  Success with some exceptions (see IOM_SUCCESS()), the
     113 *                                      status code must be passed on to EM.
     114 * @retval  VINF_IOM_R3_IOPORT_WRITE    Defer the write to ring-3. (R0/GC only)
     115 * @retval  VINF_EM_RAW_GUEST_TRAP      The exception was left pending. (TRPMRaiseXcptErr)
     116 * @retval  VINF_TRPM_XCPT_DISPATCHED   The exception was raised and dispatched for raw-mode execution. (TRPMRaiseXcptErr)
     117 * @retval  VINF_EM_RESCHEDULE_REM      The exception was dispatched and cannot be executed in raw-mode. (TRPMRaiseXcptErr)
     118 *
     119 * @param   pVM         The virtual machine (GC pointer of course).
     120 * @param   pVCpu       Pointer to the virtual CPU structure of the caller.
     121 * @param   pRegFrame   Pointer to CPUMCTXCORE guest registers structure.
     122 * @param   pCpu        Disassembler CPU state.
     123 */
     124static VBOXSTRICTRC iomRCInterpretOUT(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu)
     125{
     126#ifdef IN_RC
     127    STAM_COUNTER_INC(&pVM->iom.s.StatInstOut);
     128#endif
     129
     130    /*
     131     * Get port number from first parameter.
     132     * And get the register size and value from the second parameter.
     133     */
     134    uint64_t    uPort = 0;
     135    unsigned    cbSize = 0;
     136    bool fRc = iomGetRegImmData(pCpu, &pCpu->Param1, pRegFrame, &uPort, &cbSize);
     137    AssertMsg(fRc, ("Failed to get reg/imm port number!\n")); NOREF(fRc);
     138
     139    VBOXSTRICTRC rcStrict = IOMInterpretCheckPortIOAccess(pVM, pRegFrame, uPort, cbSize);
     140    if (rcStrict == VINF_SUCCESS)
     141    {
     142        uint64_t u64Data = 0;
     143        fRc = iomGetRegImmData(pCpu, &pCpu->Param2, pRegFrame, &u64Data, &cbSize);
     144        AssertMsg(fRc, ("Failed to get reg value!\n")); NOREF(fRc);
     145
     146        /*
     147         * Attempt to write to the port.
     148         */
     149        rcStrict = IOMIOPortWrite(pVM, pVCpu, uPort, u64Data, cbSize);
     150        AssertMsg(rcStrict == VINF_SUCCESS || rcStrict == VINF_IOM_R3_IOPORT_WRITE || (rcStrict >= VINF_EM_FIRST && rcStrict <= VINF_EM_LAST) || RT_FAILURE(rcStrict), ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
     151    }
     152    else
     153        AssertMsg(rcStrict == VINF_EM_RAW_GUEST_TRAP || rcStrict == VINF_TRPM_XCPT_DISPATCHED || RT_FAILURE(rcStrict), ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
     154    return rcStrict;
     155}
     156
     157
     158/**
     159 * [REP*] INSB/INSW/INSD
     160 * ES:EDI,DX[,ECX]
     161 *
     162 * @returns Strict VBox status code. Informational status codes other than the one documented
     163 *          here are to be treated as internal failure. Use IOM_SUCCESS() to check for success.
     164 * @retval  VINF_SUCCESS                Success.
     165 * @retval  VINF_EM_FIRST-VINF_EM_LAST  Success with some exceptions (see IOM_SUCCESS()), the
     166 *                                      status code must be passed on to EM.
     167 * @retval  VINF_IOM_R3_IOPORT_READ     Defer the read to ring-3. (R0/GC only)
     168 * @retval  VINF_EM_RAW_EMULATE_INSTR   Defer the read to the REM.
     169 * @retval  VINF_EM_RAW_GUEST_TRAP      The exception was left pending. (TRPMRaiseXcptErr)
     170 * @retval  VINF_TRPM_XCPT_DISPATCHED   The exception was raised and dispatched for raw-mode execution. (TRPMRaiseXcptErr)
     171 * @retval  VINF_EM_RESCHEDULE_REM      The exception was dispatched and cannot be executed in raw-mode. (TRPMRaiseXcptErr)
     172 *
     173 * @param   pVM         The virtual machine.
     174 * @param   pVCpu       Pointer to the virtual CPU structure of the caller.
     175 * @param   pRegFrame   Pointer to CPUMCTXCORE guest registers structure.
     176 * @param   pCpu        Disassembler CPU state.
     177 */
     178static VBOXSTRICTRC iomRCInterpretINS(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu)
     179{
     180    /*
     181     * Get port number directly from the register (no need to bother the
     182     * disassembler). And get the I/O register size from the opcode / prefix.
     183     */
     184    RTIOPORT    Port = pRegFrame->edx & 0xffff;
     185    unsigned    cb;
     186    if (pCpu->pCurInstr->uOpcode == OP_INSB)
     187        cb = 1;
     188    else
     189        cb = (pCpu->uOpMode == DISCPUMODE_16BIT) ? 2 : 4;       /* dword in both 32 & 64 bits mode */
     190
     191    VBOXSTRICTRC rcStrict = IOMInterpretCheckPortIOAccess(pVM, pRegFrame, Port, cb);
     192    if (RT_UNLIKELY(rcStrict != VINF_SUCCESS))
     193    {
     194        AssertMsg(rcStrict == VINF_EM_RAW_GUEST_TRAP || rcStrict == VINF_TRPM_XCPT_DISPATCHED || RT_FAILURE(rcStrict), ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
     195        return rcStrict;
     196    }
     197
     198    return IOMInterpretINSEx(pVM, pVCpu, pRegFrame, Port, pCpu->fPrefix, (DISCPUMODE)pCpu->uAddrMode, cb);
     199}
     200
     201
     202/**
     203 * [REP*] OUTSB/OUTSW/OUTSD
     204 * DS:ESI,DX[,ECX]
     205 *
     206 * @returns Strict VBox status code. Informational status codes other than the one documented
     207 *          here are to be treated as internal failure. Use IOM_SUCCESS() to check for success.
     208 * @retval  VINF_SUCCESS                Success.
     209 * @retval  VINF_EM_FIRST-VINF_EM_LAST  Success with some exceptions (see IOM_SUCCESS()), the
     210 *                                      status code must be passed on to EM.
     211 * @retval  VINF_IOM_R3_IOPORT_WRITE    Defer the write to ring-3. (R0/GC only)
     212 * @retval  VINF_EM_RAW_EMULATE_INSTR   Defer the write to the REM.
     213 * @retval  VINF_EM_RAW_GUEST_TRAP      The exception was left pending. (TRPMRaiseXcptErr)
     214 * @retval  VINF_TRPM_XCPT_DISPATCHED   The exception was raised and dispatched for raw-mode execution. (TRPMRaiseXcptErr)
     215 * @retval  VINF_EM_RESCHEDULE_REM      The exception was dispatched and cannot be executed in raw-mode. (TRPMRaiseXcptErr)
     216 *
     217 * @param   pVM         The virtual machine.
     218 * @param   pVCpu       Pointer to the virtual CPU structure of the caller.
     219 * @param   pRegFrame   Pointer to CPUMCTXCORE guest registers structure.
     220 * @param   pCpu        Disassembler CPU state.
     221 */
     222static VBOXSTRICTRC iomRCInterpretOUTS(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu)
     223{
     224    /*
     225     * Get port number from the first parameter.
     226     * And get the I/O register size from the opcode / prefix.
     227     */
     228    uint64_t    Port = 0;
     229    unsigned    cb;
     230    bool fRc = iomGetRegImmData(pCpu, &pCpu->Param1, pRegFrame, &Port, &cb);
     231    AssertMsg(fRc, ("Failed to get reg/imm port number!\n")); NOREF(fRc);
     232    if (pCpu->pCurInstr->uOpcode == OP_OUTSB)
     233        cb = 1;
     234    else
     235        cb = (pCpu->uOpMode == DISCPUMODE_16BIT) ? 2 : 4;       /* dword in both 32 & 64 bits mode */
     236
     237    VBOXSTRICTRC rcStrict = IOMInterpretCheckPortIOAccess(pVM, pRegFrame, Port, cb);
     238    if (RT_UNLIKELY(rcStrict != VINF_SUCCESS))
     239    {
     240        AssertMsg(rcStrict == VINF_EM_RAW_GUEST_TRAP || rcStrict == VINF_TRPM_XCPT_DISPATCHED || RT_FAILURE(rcStrict), ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
     241        return rcStrict;
     242    }
     243
     244    return IOMInterpretOUTSEx(pVM, pVCpu, pRegFrame, Port, pCpu->fPrefix, (DISCPUMODE)pCpu->uAddrMode, cb);
     245}
     246
     247
     248
     249/**
    46250 * Attempts to service an IN/OUT instruction.
    47251 *
     
    71275    {
    72276        case OP_IN:
    73             return IOMInterpretIN(pVM, pVCpu, pRegFrame, pCpu);
     277            return iomRCInterpretIN(pVM, pVCpu, pRegFrame, pCpu);
    74278
    75279        case OP_OUT:
    76             return IOMInterpretOUT(pVM, pVCpu, pRegFrame, pCpu);
     280            return iomRCInterpretOUT(pVM, pVCpu, pRegFrame, pCpu);
    77281
    78282        case OP_INSB:
    79283        case OP_INSWD:
    80             return IOMInterpretINS(pVM, pVCpu, pRegFrame, pCpu);
     284            return iomRCInterpretINS(pVM, pVCpu, pRegFrame, pCpu);
    81285
    82286        case OP_OUTSB:
    83287        case OP_OUTSWD:
    84             return IOMInterpretOUTS(pVM, pVCpu, pRegFrame, pCpu);
     288            return iomRCInterpretOUTS(pVM, pVCpu, pRegFrame, pCpu);
    85289
    86290        /*
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