VirtualBox

Changeset 104516 in vbox


Ignore:
Timestamp:
May 4, 2024 1:53:42 AM (9 months ago)
Author:
vboxsync
Message:

VMM/GCM,IEM,HM: Integrate GCM with IEM, extending it to cover the mesa drv situation and valid ring-0 IN instructions to same port. Untested. TODO: NEM. bugref:9735 bugref:10683

Location:
trunk
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/err.h

    r104407 r104516  
    32723272/** @} */
    32733273
     3274/** @name Guest Compatibility Manage Status Codes.
     3275 * @{
     3276 */
     3277/** The intercepted situation was completely handled, continue execution. */
     3278#define VINF_GCM_HANDLED                            (7600)
     3279/** The intercepted instruction handled, advance RIP and continue execution. */
     3280#define VINF_GCM_HANDLED_ADVANCE_RIP                (7601)
     3281/** The intercepted operation was not handled, take default action. */
     3282#define VERR_GCM_NOT_HANDLED                        (-7602)
     3283/** @} */
     3284
    32743285/* SED-END */
    32753286
  • trunk/include/VBox/vmm/cpum-common.h

    r98970 r104516  
    124124    } while (0)
    125125
     126/** @def CPUM_IMPORT_EXTRN_WITH_CTX_RET
     127 * Macro for making sure the state specified by @a fExtrnImport is present,
     128 * calling CPUMImportGuestStateOnDemand() to get it if necessary.
     129 *
     130 * Will return if CPUMImportGuestStateOnDemand() fails.
     131 *
     132 * @param   a_pVCpu         The cross context virtual CPU structure of the calling EMT.
     133 * @param   a_pCtx          Pointer to the CPU context (CPUMCTX).
     134 * @param   a_fExtrnImport  Mask of CPUMCTX_EXTRN_XXX bits to get.
     135 * @thread  EMT(a_pVCpu)
     136 */
     137#define CPUM_IMPORT_EXTRN_WITH_CTX_RET(a_pVCpu, a_pCtx, a_fExtrnImport) \
     138    do { \
     139        if (!((a_pCtx)->fExtrn & (a_fExtrnImport))) \
     140        { /* already present, consider this likely */ } \
     141        else \
     142        { \
     143            int rcCpumImport = CPUMImportGuestStateOnDemand(a_pVCpu, a_fExtrnImport); \
     144            AssertRCReturn(rcCpumImport, rcCpumImport); \
     145        } \
     146    } while (0)
     147
    126148VMM_INT_DECL(int) CPUMImportGuestStateOnDemand(PVMCPUCC pVCpu, uint64_t fExtrnImport);
    127149/** @} */
  • trunk/include/VBox/vmm/gcm.h

    r104511 r104516  
    6161VMM_INT_DECL(bool)          GCMIsInterceptingXcptDE(PVMCPUCC pVCpu);
    6262VMM_INT_DECL(int)           GCMXcptDE(PVMCPUCC pVCpu, PCPUMCTX pCtx);
     63
     64VMM_INT_DECL(bool)          GCMIsInterceptingXcptGP(PVMCPUCC pVCpu);
     65VMM_INT_DECL(int)           GCMXcptGP(PVMCPUCC pVCpu, PCPUMCTX pCtx);
     66
     67VMM_INT_DECL(VBOXSTRICTRC)  GCMInterceptedIOPortRead(PVMCPUCC pVCpu, PCPUMCTX pCtx, uint16_t u16Port, uint8_t cbReg);
     68VMM_INT_DECL(bool)          GCMIsInterceptingIOPortReadSlow(PVMCPUCC pVCpu, uint16_t u16Port, uint8_t cbReg);
     69
     70/**
     71 * Checks if the given IN instruction is intercepted.
     72 */
     73DECLINLINE(bool) GCMIsInterceptingIOPortRead(PVMCPUCC pVCpu, uint16_t u16Port, uint8_t cbReg)
     74{
     75    return u16Port == 0x5658 /* vmware hypervisor port */
     76        && cbReg == 4
     77        && GCMIsInterceptingIOPortReadSlow(pVCpu, u16Port, cbReg);
     78}
     79
     80#if 0 /* If we need to deal with high speed vmware hypervisor calls */
     81VMM_INT_DECL(bool)          GCMIsInterceptingIOPortReadStringSlow(PVMCPUCC pVCpu, uint16_t u16Port, uint8_t cbReg);
     82VMM_INT_DECL(bool)          GCMIsInterceptingIOPortWriteStringSlow(PVMCPUCC pVCpu, uint16_t u16Port, uint8_t cbReg);
     83
     84/**
     85 * Checks if the given INS instruction is intercepted.
     86 */
     87DECLINLINE(bool) GCMIsInterceptingIOPortReadString(PVMCPUCC pVCpu, uint16_t u16Port, uint8_t cbReg)
     88{
     89    return u16Port == 0x5659 /* new vmware hypervisor port */
     90        && cbReg == 1
     91        && GCMIsInterceptingIOPortReadStringSlow(pVCpu, u16Port, cbReg);
     92}
     93
     94/**
     95 * Checks if the given OUTS instruction is intercepted.
     96 */
     97DECLINLINE(bool) GCMIsInterceptingIOPortWriteString(PVMCPUCC pVCpu, uint16_t u16Port, uint8_t cbReg)
     98{
     99    return u16Port == 0x5659 /* new vmware hypervisor port */
     100        && cbReg == 1
     101        && GCMIsInterceptingIOPortWriteStringSlow(pVCpu, u16Port, cbReg);
     102}
     103#endif
     104
    63105/** @} */
    64106
  • trunk/src/VBox/Main/src-client/ConsoleImplConfigX86.cpp

    r104507 r104516  
    10781078        if (fW9xGuest)
    10791079            InsertConfigInteger(pGcmNode, "DivByZeroWin9x", 1);
     1080        /* MesaVmsvgaDrv (formerly LovelyMesaDrvWorkaround) is set futher down. */
    10801081
    10811082        /*
     
    14071408#ifdef VBOX_WITH_VMSVGA
    14081409            case GraphicsControllerType_VMSVGA:
    1409                 InsertConfigInteger(pHM, "LovelyMesaDrvWorkaround", 1); /* hits someone else logging backdoor. */
    1410                 InsertConfigInteger(pNEM, "LovelyMesaDrvWorkaround", 1); /* hits someone else logging backdoor. */
     1410                InsertConfigInteger(pHM, "LovelyMesaDrvWorkaround", 1);  /* hits someone else's logging backdoor. */
     1411                InsertConfigInteger(pNEM, "LovelyMesaDrvWorkaround", 1); /* hits someone else's logging backdoor. */
     1412                InsertConfigInteger(pGcmNode, "MesaVmsvgaDrv", 1);       /* hits someone else's logging backdoor. */
    14111413                RT_FALL_THROUGH();
    14121414            case GraphicsControllerType_VBoxSVGA:
  • trunk/src/VBox/VMM/VMMAll/GCMAll.cpp

    r104511 r104516  
    3535
    3636#include <VBox/dis.h>       /* For DISSTATE */
    37 #include <iprt/errcore.h>
     37#include <VBox/err.h>
    3838#include <iprt/string.h>
     39
     40
     41/*********************************************************************************************************************************
     42*   Defined Constants And Macros                                                                                                 *
     43*********************************************************************************************************************************/
     44#define VMWARE_HYPERVISOR_PORT                  UINT16_C(0x5658)
     45#define VMWARE_HYPERVISOR_PORT_HB               UINT16_C(0x5659)
     46#define VMWARE_HYPERVISOR_MAGIC                 UINT32_C(0x564d5868)    /**< eax value */
     47
     48#define VMWARE_HYPERVISOR_CMD_MSG               0x001e
     49#define VMWARE_HYPERVISOR_CMD_HB_MSG            0x0000
     50#define VMWARE_HYPERVISOR_CMD_OPEN_CHANNEL      RT_MAKE_U32(VMWARE_HYPERVISOR_CMD_MSG, 0) /**< ecx */
     51#define VMWARE_OC_RPCI_PROTOCOL_NUM                 UINT32_C(0x49435052) /**< VMWARE_HYPERVISOR_CMD_OPEN_CHANNEL: ebx[30:0] */
     52#define VMWARE_OC_GUESTMSG_FLAG_COOKIE              UINT32_C(0x80000000) /**< VMWARE_HYPERVISOR_CMD_OPEN_CHANNEL: ebx bit 31 */
     53#define VMWARE_HYPERVISOR_CMD_SEND_SIZE         RT_MAKE_U32(VMWARE_HYPERVISOR_CMD_MSG, 1) /**< ecx */
     54#define VMWARE_HYPERVISOR_CMD_SEND_PAYLOAD      RT_MAKE_U32(VMWARE_HYPERVISOR_CMD_MSG, 2) /**< ecx */
     55#define VMWARE_HYPERVISOR_CMD_RECV_SIZE         RT_MAKE_U32(VMWARE_HYPERVISOR_CMD_MSG, 3) /**< ecx */
     56#define VMWARE_HYPERVISOR_CMD_RECV_PAYLOAD      RT_MAKE_U32(VMWARE_HYPERVISOR_CMD_MSG, 4) /**< ecx */
     57#define VMWARE_HYPERVISOR_CMD_RECV_STATUS       RT_MAKE_U32(VMWARE_HYPERVISOR_CMD_MSG, 5) /**< ecx */
     58#define VMWARE_HYPERVISOR_CMD_CLOSE_CHANNEL     RT_MAKE_U32(VMWARE_HYPERVISOR_CMD_MSG, 6) /**< ecx */
     59
     60#define VMWARE_HYPERVISOR_CMD_MKS_GUEST_STATS   0x0055
     61#define VMWARE_HYPERVISOR_CMD_MKSGS_RESET       RT_MAKE_U32(VMWARE_HYPERVISOR_CMD_MKS_GUEST_STATS, 0) /**< ecx */
     62#define VMWARE_HYPERVISOR_CMD_MKSGS_ADD_PPN     RT_MAKE_U32(VMWARE_HYPERVISOR_CMD_MKS_GUEST_STATS, 1) /**< ecx */
     63#define VMWARE_HYPERVISOR_CMD_MKSGS_REMOVE_PPN  RT_MAKE_U32(VMWARE_HYPERVISOR_CMD_MKS_GUEST_STATS, 2) /**< ecx */
     64
     65/** @name Message status return flags (ecx).
     66 * @{ */
     67#define VMWARE_MSG_STATUS_F_SUCCESS             UINT32_C(0x00010000)
     68#define VMWARE_MSG_STATUS_F_DO_RECV             UINT32_C(0x00020000)
     69#define VMWARE_MSG_STATUS_F_CPT                 UINT32_C(0x00100000)
     70#define VMWARE_MSG_STATUS_F_HB                  UINT32_C(0x00800000)
     71/** @} */
    3972
    4073
     
    198231}
    199232
     233
     234#if 0
     235/**
     236 * Whether \#GP exceptions in the guest should be intercepted by GCM and
     237 * possibly fixed up.
     238 *
     239 * @returns true if needed, false otherwise.
     240 * @param   pVCpu       The cross context virtual CPU structure.
     241 */
     242VMM_INT_DECL(bool) GCMIsInterceptingXcptGP(PVMCPUCC pVCpu)
     243{
     244    /* See if the enabled fixers require #GP interception. */
     245    PVM const  pVM  = pVCpu->CTX_SUFF(pVM);
     246    bool const fRet = (pVM->gcm.s.fFixerSet & GCMFIXER_MESA_VMSVGA_DRV) != 0;
     247    LogFlow(("GCMIsInterceptingXcptDE: returns %d\n", fRet));
     248    return fRet;
     249}
     250
     251
     252/**
     253 * Exception handler for \#GP when registered by GCM.
     254 *
     255 * @returns VBox status code.
     256 * @retval  VINF_SUCCESS retry the instruction and continue.
     257 * @retval  VERR_NOT_FOUND deliver exception to guest.
     258 *
     259 * @param   pVCpu       The cross context virtual CPU structure.
     260 * @param   pCtx        Pointer to the guest-CPU context.
     261 *
     262 * @thread  EMT(pVCpu).
     263 */
     264VMM_INT_DECL(int) GCMXcptGP(PVMCPUCC pVCpu, PCPUMCTX pCtx)
     265{
     266
     267}
     268#endif
     269
     270
     271/**
     272 * Checks if I/O port reads for the given port need GCM attention.
     273 *
     274 * @returns true if needed, false otherwise.
     275 * @param   pVCpu       The cross context virtual CPU structure.
     276 * @param   u16Port     The port being accessed. UINT16_MAX and cbReg ==
     277 *                      UINT8_MAX for any port.
     278 * @param   cbReg       The access size. UINT8_MAX and u16Port == UINT16_MAX for
     279 *                      any size.
     280 */
     281VMM_INT_DECL(bool) GCMIsInterceptingIOPortReadSlow(PVMCPUCC pVCpu, uint16_t u16Port, uint8_t cbReg)
     282{
     283    PVM const  pVM  = pVCpu->CTX_SUFF(pVM);
     284    bool const fRet = (pVM->gcm.s.fFixerSet & GCMFIXER_MESA_VMSVGA_DRV) != 0
     285                   && (   (u16Port == VMWARE_HYPERVISOR_PORT && cbReg == 4)
     286                       || (u16Port == UINT16_MAX && cbReg == UINT8_MAX) );
     287    LogFlow(("GCMIsInterceptingIOPortReadSlow(,%#x,%#x): returns %d\n", u16Port, cbReg, fRet));
     288    return fRet;
     289}
     290
     291
     292/**
     293 * Processes an intercepted IO port read instruction.
     294 *
     295 * @returns Strict VBox status code. Only two informational status codes
     296 *          are returned VINF_GCM_HANDLED and VINF_GCM_HANDLED_ADVANCE_RIP.
     297 * @retval  VINF_GCM_HANDLED
     298 * @retval  VINF_GCM_HANDLED_ADVANCE_RIP
     299 * @retval  VERR_GCM_NOT_HANDLED
     300 * @param   pVCpu       The cross context virtual CPU structure.
     301 * @param   pCtx        The CPU context.
     302 * @param   u16Port     The port being accessed.
     303 * @param   cbReg       The size of the access.
     304 */
     305VMM_INT_DECL(VBOXSTRICTRC) GCMInterceptedIOPortRead(PVMCPUCC pVCpu, PCPUMCTX pCtx, uint16_t u16Port, uint8_t cbReg)
     306{
     307    Assert((pVCpu->CTX_SUFF(pVM)->gcm.s.fFixerSet & GCMFIXER_MESA_VMSVGA_DRV) != 0);
     308    if (u16Port == VMWARE_HYPERVISOR_PORT && cbReg == 4)
     309    {
     310        CPUM_IMPORT_EXTRN_WITH_CTX_RET(pVCpu, pCtx,
     311                                         CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RCX | CPUMCTX_EXTRN_RDX
     312                                       | CPUMCTX_EXTRN_RBX | CPUMCTX_EXTRN_RSI | CPUMCTX_EXTRN_RDI);
     313        if (pCtx->rax == VMWARE_HYPERVISOR_MAGIC)
     314        {
     315            switch (pCtx->rcx)
     316            {
     317                case VMWARE_HYPERVISOR_CMD_OPEN_CHANNEL:
     318                    Log(("GCMInterceptedIOPortRead: vmware open channel: protocol=%#RX64\n", pCtx->rbx));
     319                    break;
     320                case VMWARE_HYPERVISOR_CMD_SEND_SIZE:
     321                    Log(("GCMInterceptedIOPortRead: vmware send size\n"));
     322                    break;
     323                case VMWARE_HYPERVISOR_CMD_SEND_PAYLOAD:
     324                    Log(("GCMInterceptedIOPortRead: vmware send payload\n"));
     325                    break;
     326                case VMWARE_HYPERVISOR_CMD_RECV_SIZE:
     327                    Log(("GCMInterceptedIOPortRead: vmware recv size\n"));
     328                    break;
     329                case VMWARE_HYPERVISOR_CMD_RECV_PAYLOAD:
     330                    Log(("GCMInterceptedIOPortRead: vmware recv payload\n"));
     331                    break;
     332                case VMWARE_HYPERVISOR_CMD_RECV_STATUS:
     333                    Log(("GCMInterceptedIOPortRead: vmware recv status\n"));
     334                    break;
     335                case VMWARE_HYPERVISOR_CMD_CLOSE_CHANNEL:
     336                    Log(("GCMInterceptedIOPortRead: vmware close channel\n"));
     337                    break;
     338
     339                case VMWARE_HYPERVISOR_CMD_MKSGS_RESET:
     340                    Log(("GCMInterceptedIOPortRead: vmware mks guest stats reset\n"));
     341                    break;
     342                case VMWARE_HYPERVISOR_CMD_MKSGS_ADD_PPN:
     343                    Log(("GCMInterceptedIOPortRead: vmware mks guest stats add ppn\n"));
     344                    break;
     345                case VMWARE_HYPERVISOR_CMD_MKSGS_REMOVE_PPN:
     346                    Log(("GCMInterceptedIOPortRead: vmware mks guest stats remove ppn\n"));
     347                    break;
     348
     349                default:
     350                    LogRelMax(64, ("GCMInterceptedIOPortRead: Unknown vmware hypervisor call: rcx=%#RX64 (cmd), rbx=%#RX64 (len/whatever), rsi=%#RX64 (input), rdi=%#RX64 (input), rdx=%#RX64 (flags + chid) at %04x:%08RX64\n",
     351                                   pCtx->rcx, pCtx->rbx, pCtx->rsi, pCtx->rdi, pCtx->rdx, pCtx->cs.Sel, pCtx->rip));
     352                    return VERR_GCM_NOT_HANDLED;
     353            }
     354
     355            /* Just fail the command. */
     356            pCtx->ecx &= ~VMWARE_MSG_STATUS_F_SUCCESS;
     357            return VINF_GCM_HANDLED_ADVANCE_RIP;
     358        }
     359    }
     360    return VERR_GCM_NOT_HANDLED;
     361}
     362
     363
     364#if 0 /* If we need to deal with high speed vmware hypervisor calls */
     365
     366/**
     367 * Checks if I/O port string reads for the given port need GCM attention.
     368 *
     369 * @returns true if needed, false otherwise.
     370 * @param   pVCpu       The cross context virtual CPU structure.
     371 * @param   u16Port     The port being accessed. UINT16_MAX and cbReg ==
     372 *                      UINT8_MAX for any port.
     373 * @param   cbReg       The access size. UINT8_MAX and u16Port == UINT16_MAX for
     374 *                      any size.
     375 */
     376VMM_INT_DECL(bool) GCMIsInterceptingIOPortReadStringSlow(PVMCPUCC pVCpu, uint16_t u16Port, uint8_t cbReg)
     377{
     378    PVM const  pVM  = pVCpu->CTX_SUFF(pVM);
     379    bool const fRet = (pVM->gcm.s.fFixerSet & GCMFIXER_MESA_VMSVGA_DRV) != 0
     380                   && (   (u16Port == VMWARE_HYPERVISOR_PORT_HB && cbReg == 1)
     381                       || (u16Port == UINT16_MAX && cbReg == UINT8_MAX) );
     382    LogFlow(("GCMIsInterceptingIOPortReadStringSlow(,%#x,%#x): returns %d\n", u16Port, cbReg, fRet));
     383    return fRet;
     384}
     385
     386
     387/**
     388 * Checks if I/O port string writes for the given port need GCM attention.
     389 *
     390 * @returns true if needed, false otherwise.
     391 * @param   pVCpu       The cross context virtual CPU structure.
     392 * @param   u16Port     The port being accessed. UINT16_MAX and cbReg ==
     393 *                      UINT8_MAX for any port.
     394 * @param   cbReg       The access size. UINT8_MAX and u16Port == UINT16_MAX for
     395 *                      any size.
     396 */
     397VMM_INT_DECL(bool) GCMIsInterceptingIOPortWriteStringSlow(PVMCPUCC pVCpu, uint16_t u16Port, uint8_t cbReg)
     398{
     399    PVM const  pVM  = pVCpu->CTX_SUFF(pVM);
     400    bool const fRet = (pVM->gcm.s.fFixerSet & GCMFIXER_MESA_VMSVGA_DRV) != 0
     401                   && (   (u16Port == VMWARE_HYPERVISOR_PORT_HB && cbReg == 1)
     402                       || (u16Port == UINT16_MAX && cbReg == UINT8_MAX) );
     403    LogFlow(("GCMIsInterceptingIOPortWriteStringSlow(,%#x,%#x): returns %d\n", u16Port, cbReg, fRet));
     404    return fRet;
     405}
     406
     407#endif
     408
  • trunk/src/VBox/VMM/VMMAll/IEMAll.cpp

    r104129 r104516  
    131131#include <VBox/vmm/hm.h>
    132132#include <VBox/vmm/nem.h>
     133#include <VBox/vmm/gcm.h>
    133134#include <VBox/vmm/gim.h>
    134135#ifdef VBOX_WITH_NESTED_HWVIRT_SVM
     
    41974198VBOXSTRICTRC iemRaiseDivideError(PVMCPUCC pVCpu) RT_NOEXCEPT
    41984199{
     4200    if (GCMIsInterceptingXcptDE(pVCpu))
     4201    {
     4202        int rc = GCMXcptDE(pVCpu, &pVCpu->cpum.GstCtx);
     4203        if (rc == VINF_SUCCESS)
     4204        {
     4205            Log(("iemRaiseDivideError: Restarting instruction because of GCMXcptDE\n"));
     4206            return VINF_IEM_RAISED_XCPT; /* must return non-zero status here to cause a instruction restart */
     4207        }
     4208    }
    41994209    return iemRaiseXcptOrInt(pVCpu, 0, X86_XCPT_DE, IEM_XCPT_FLAGS_T_CPU_XCPT, 0, 0);
    42004210}
  • trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp

    r104419 r104516  
    4343#include <VBox/vmm/nem.h>
    4444#include <VBox/vmm/gim.h>
     45#include <VBox/vmm/gcm.h>
    4546#ifdef VBOX_WITH_NESTED_HWVIRT_SVM
    4647# include <VBox/vmm/em.h>
     
    72947295IEM_CIMPL_DEF_3(iemCImpl_in, uint16_t, u16Port, uint8_t, cbReg, uint8_t, bImmAndEffAddrMode)
    72957296{
     7297    /*
     7298     * GCM intercept.
     7299     *
     7300     * This must be placed before the IOPL check as the mesa driver intercept
     7301     * would otherwise trigger a #GP(0).
     7302     */
     7303    if (!IEM_IS_IN_GUEST(pVCpu) && GCMIsInterceptingIOPortRead(pVCpu, u16Port, cbReg))
     7304    {
     7305        VBOXSTRICTRC rcStrict = GCMInterceptedIOPortRead(pVCpu, &pVCpu->cpum.GstCtx, u16Port, cbReg);
     7306        if (rcStrict == VINF_GCM_HANDLED_ADVANCE_RIP || rcStrict == VINF_GCM_HANDLED)
     7307        {
     7308            Log(("iemCImpl_in: u16Port=%#x cbReg=%d was handled by GCMIOPortRead (%d)\n", u16Port, cbReg, VBOXSTRICTRC_VAL(rcStrict)));
     7309            if (rcStrict == VINF_GCM_HANDLED_ADVANCE_RIP)
     7310                rcStrict = iemRegAddToRipAndFinishingClearingRF(pVCpu, cbInstr);
     7311            else
     7312                rcStrict = VINF_SUCCESS;
     7313            return rcStrict;
     7314        }
     7315        Assert(rcStrict == VERR_GCM_NOT_HANDLED);
     7316    }
     7317
    72967318    /*
    72977319     * CPL check
  • trunk/src/VBox/VMM/VMMAll/VMXAllTemplate.cpp.h

    r104512 r104516  
    90039003            else
    90049004            {
    9005                 uint32_t u32Result = 0;
    9006                 rcStrict = IOMIOPortRead(pVM, pVCpu, uIOPort, &u32Result, cbValue);
    9007                 if (IOM_SUCCESS(rcStrict))
     9005                rcStrict = VERR_GCM_NOT_HANDLED;
     9006                if (GCMIsInterceptingIOPortRead(pVCpu, uIOPort, cbValue))
    90089007                {
    9009                     /* Save result of I/O IN instr. in AL/AX/EAX. */
    9010                     pCtx->eax = (pCtx->eax & ~uAndVal) | (u32Result & uAndVal);
     9008                    rcStrict = GCMInterceptedIOPortRead(pVCpu, pCtx, uIOPort, cbValue);
     9009                    if (rcStrict == VINF_GCM_HANDLED_ADVANCE_RIP || rcStrict == VINF_GCM_HANDLED)
     9010                    {
     9011                        /* ASSUMES we don't need to update fCtxChanged when regular GPRs change here. */
     9012                        fUpdateRipAlready = rcStrict == VINF_GCM_HANDLED;
     9013                        if (rcStrict == VINF_GCM_HANDLED)
     9014                            ASMAtomicUoOrU64(&VCPU_2_VMXSTATE(pVCpu).fCtxChanged, HM_CHANGED_GUEST_RIP);
     9015                        rcStrict = VINF_SUCCESS;
     9016                    }
     9017                    else
     9018                        Assert(rcStrict == VERR_GCM_NOT_HANDLED);
    90119019                }
     9020
     9021                if (rcStrict == VERR_GCM_NOT_HANDLED)
     9022                {
     9023                    uint32_t u32Result = 0;
     9024                    rcStrict = IOMIOPortRead(pVM, pVCpu, uIOPort, &u32Result, cbValue);
     9025                    if (IOM_SUCCESS(rcStrict))
     9026                    {
     9027                        /* Save result of I/O IN instr. in AL/AX/EAX. */
     9028                        /** @todo r=bird: 32-bit op size should clear high bits of rax! */
     9029                        pCtx->eax = (pCtx->eax & ~uAndVal) | (u32Result & uAndVal);
     9030                    }
    90129031#ifndef IN_NEM_DARWIN
    9013                 if (    rcStrict == VINF_IOM_R3_IOPORT_READ
    9014                     && !pCtx->eflags.Bits.u1TF)
    9015                     rcStrict = EMRZSetPendingIoPortRead(pVCpu, uIOPort, cbInstr, cbValue);
    9016 #endif
     9032                    if (    rcStrict == VINF_IOM_R3_IOPORT_READ
     9033                        && !pCtx->eflags.Bits.u1TF)
     9034                        rcStrict = EMRZSetPendingIoPortRead(pVCpu, uIOPort, cbInstr, cbValue);
     9035#endif
     9036                }
    90179037                STAM_COUNTER_INC(&VCPU_2_VMXSTATS(pVCpu).StatExitIORead);
    90189038            }
  • trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp

    r104512 r104516  
    76347634    static uint32_t const s_aIOOpAnd[8] = { 0, 0xff, 0xffff, 0, 0xffffffff, 0, 0, 0 };  /* AND masks for saving
    76357635                                                                                           the result (in AL/AX/EAX). */
    7636     PVMCC      pVM   = pVCpu->CTX_SUFF(pVM);
     7636    PVMCC    pVM   = pVCpu->CTX_SUFF(pVM);
    76377637    PCPUMCTX pCtx  = &pVCpu->cpum.GstCtx;
    76387638    PSVMVMCB pVmcb = hmR0SvmGetCurrentVmcb(pVCpu);
     
    77527752            else
    77537753            {
    7754                 uint32_t u32Val = 0;
    7755                 rcStrict = IOMIOPortRead(pVM, pVCpu, IoExitInfo.n.u16Port, &u32Val, cbValue);
    7756                 if (IOM_SUCCESS(rcStrict))
     7754                rcStrict = VERR_GCM_NOT_HANDLED;
     7755                if (GCMIsInterceptingIOPortRead(pVCpu, IoExitInfo.n.u16Port, cbValue))
    77577756                {
    7758                     /* Save result of I/O IN instr. in AL/AX/EAX. */
    7759                     /** @todo r=bird: 32-bit op size should clear high bits of rax! */
    7760                     pCtx->eax = (pCtx->eax & ~uAndVal) | (u32Val & uAndVal);
     7757                    rcStrict = GCMInterceptedIOPortRead(pVCpu, pCtx, IoExitInfo.n.u16Port, cbValue);
     7758                    if (rcStrict == VINF_GCM_HANDLED_ADVANCE_RIP || rcStrict == VINF_GCM_HANDLED)
     7759                    {
     7760                        fUpdateRipAlready = rcStrict != VINF_GCM_HANDLED_ADVANCE_RIP;
     7761                        rcStrict = VINF_SUCCESS;
     7762                    }
     7763                    else
     7764                        Assert(rcStrict == VERR_GCM_NOT_HANDLED);
    77617765                }
    7762                 else if (    rcStrict == VINF_IOM_R3_IOPORT_READ
    7763                          && !pCtx->eflags.Bits.u1TF)
    7764                     rcStrict = EMRZSetPendingIoPortRead(pVCpu, IoExitInfo.n.u16Port, cbInstr, cbValue);
     7766
     7767                if (RT_LIKELY(rcStrict == VERR_GCM_NOT_HANDLED))
     7768                {
     7769                    uint32_t u32Val = 0;
     7770                    rcStrict = IOMIOPortRead(pVM, pVCpu, IoExitInfo.n.u16Port, &u32Val, cbValue);
     7771                    if (IOM_SUCCESS(rcStrict))
     7772                    {
     7773                        /* Save result of I/O IN instr. in AL/AX/EAX. */
     7774                        /** @todo r=bird: 32-bit op size should clear high bits of rax! */
     7775                        pCtx->eax = (pCtx->eax & ~uAndVal) | (u32Val & uAndVal);
     7776                    }
     7777                    else if (    rcStrict == VINF_IOM_R3_IOPORT_READ
     7778                             && !pCtx->eflags.Bits.u1TF)
     7779                        rcStrict = EMRZSetPendingIoPortRead(pVCpu, IoExitInfo.n.u16Port, cbInstr, cbValue);
     7780                }
    77657781
    77667782                STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIORead);
  • trunk/src/VBox/VMM/VMMR3/GCM.cpp

    r104511 r104516  
    115115        { RT_STR_TUPLE("DivByZeroOS2"),       GCMFIXER_DBZ_OS2 },
    116116        { RT_STR_TUPLE("DivByZeroWin9x"),     GCMFIXER_DBZ_WIN9X },
     117        { RT_STR_TUPLE("MesaVmsvgaDrv"),      GCMFIXER_MESA_VMSVGA_DRV },
    117118    };
    118119
  • trunk/src/VBox/VMM/include/GCMInternal.h

    r104509 r104516  
    5656/** Windows 9x division by zero. */
    5757#define GCMFIXER_DBZ_WIN9X          RT_BIT_32(2)
     58/** Workaround for the Mesa vmsvga driver using a IN/OUT backdoor. */
     59#define GCMFIXER_MESA_VMSVGA_DRV    RT_BIT_32(3)
    5860/** @} */
    5961
Note: See TracChangeset for help on using the changeset viewer.

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