VirtualBox

Changeset 8098 in vbox


Ignore:
Timestamp:
Apr 17, 2008 2:08:15 PM (17 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
29799
Message:

Emulate cmpxchg8b in GC.

Location:
trunk
Files:
6 edited

Legend:

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

    r7286 r8098  
    469469EMGCDECL(uint32_t) EMGCEmulateLockCmpXchg(RTGCPTR pu32Param1, uint32_t *pu32Param2, uint32_t u32Param3, size_t cbSize, uint32_t *pEflags);
    470470EMGCDECL(uint32_t) EMGCEmulateCmpXchg(RTGCPTR pu32Param1, uint32_t *pu32Param2, uint32_t u32Param3, size_t cbSize, uint32_t *pEflags);
     471EMGCDECL(uint32_t) EMGCEmulateLockCmpXchg8b(RTGCPTR pu32Param1, uint32_t *pEAX, uint32_t *pEDX, uint32_t uEBX, uint32_t uECX, uint32_t *pEflags);
     472EMGCDECL(uint32_t) EMGCEmulateCmpXchg8b(RTGCPTR pu32Param1, uint32_t *pEAX, uint32_t *pEDX, uint32_t uEBX, uint32_t uECX, uint32_t *pEflags);
    471473EMGCDECL(uint32_t) EMGCEmulateLockXAdd(RTGCPTR pu32Param1, uint32_t *pu32Param2, size_t cbSize, uint32_t *pEflags);
    472474EMGCDECL(uint32_t) EMGCEmulateXAdd(RTGCPTR pu32Param1, uint32_t *pu32Param2, size_t cbSize, uint32_t *pEflags);
  • trunk/src/VBox/VMM/EM.cpp

    r7996 r8098  
    201201    STAM_REG_USED(pVM, &pStats->StatGCCmpXchg,              STAMTYPE_COUNTER, "/EM/GC/Interpret/Success/CmpXchg",   STAMUNIT_OCCURENCES,    "The number of times CMPXCHG was successfully interpreted.");
    202202    STAM_REG_USED(pVM, &pStats->StatHCCmpXchg,              STAMTYPE_COUNTER, "/EM/HC/Interpret/Success/CmpXchg",   STAMUNIT_OCCURENCES,    "The number of times CMPXCHG was successfully interpreted.");
     203    STAM_REG_USED(pVM, &pStats->StatGCCmpXchg8b,            STAMTYPE_COUNTER, "/EM/GC/Interpret/Success/CmpXchg8b",   STAMUNIT_OCCURENCES,  "The number of times CMPXCHG8B was successfully interpreted.");
     204    STAM_REG_USED(pVM, &pStats->StatHCCmpXchg8b,            STAMTYPE_COUNTER, "/EM/HC/Interpret/Success/CmpXchg8b",   STAMUNIT_OCCURENCES,  "The number of times CMPXCHG8B was successfully interpreted.");
    203205    STAM_REG_USED(pVM, &pStats->StatGCXAdd,                 STAMTYPE_COUNTER, "/EM/GC/Interpret/Success/XAdd",      STAMUNIT_OCCURENCES,    "The number of times XADD was successfully interpreted.");
    204206    STAM_REG_USED(pVM, &pStats->StatHCXAdd,                 STAMTYPE_COUNTER, "/EM/HC/Interpret/Success/XAdd",      STAMUNIT_OCCURENCES,    "The number of times XADD was successfully interpreted.");
     
    262264    STAM_REG_USED(pVM, &pStats->StatGCFailedCmpXchg,        STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/CmpXchg",    STAMUNIT_OCCURENCES,    "The number of times CMPXCHG was not interpreted.");
    263265    STAM_REG_USED(pVM, &pStats->StatHCFailedCmpXchg,        STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/CmpXchg",    STAMUNIT_OCCURENCES,    "The number of times CMPXCHG was not interpreted.");
     266    STAM_REG_USED(pVM, &pStats->StatGCFailedCmpXchg8b,      STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/CmpXchg8b",  STAMUNIT_OCCURENCES,    "The number of times CMPXCHG8B was not interpreted.");
     267    STAM_REG_USED(pVM, &pStats->StatHCFailedCmpXchg8b,      STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/CmpXchg8b",  STAMUNIT_OCCURENCES,    "The number of times CMPXCHG8B was not interpreted.");
    264268    STAM_REG_USED(pVM, &pStats->StatGCFailedXAdd,           STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/XAdd",       STAMUNIT_OCCURENCES,    "The number of times XADD was not interpreted.");
    265269    STAM_REG_USED(pVM, &pStats->StatHCFailedXAdd,           STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/XAdd",       STAMUNIT_OCCURENCES,    "The number of times XADD was not interpreted.");
  • trunk/src/VBox/VMM/EMInternal.h

    r7286 r8098  
    131131    STAMCOUNTER             StatGCCmpXchg;
    132132    STAMCOUNTER             StatHCCmpXchg;
     133    STAMCOUNTER             StatGCCmpXchg8b;
     134    STAMCOUNTER             StatHCCmpXchg8b;
    133135    STAMCOUNTER             StatGCXAdd;
    134136    STAMCOUNTER             StatHCXAdd;
     
    192194    STAMCOUNTER             StatGCFailedCmpXchg;
    193195    STAMCOUNTER             StatHCFailedCmpXchg;
     196    STAMCOUNTER             StatGCFailedCmpXchg8b;
     197    STAMCOUNTER             StatHCFailedCmpXchg8b;
    194198    STAMCOUNTER             StatGCFailedXAdd;
    195199    STAMCOUNTER             StatHCFailedXAdd;
  • trunk/src/VBox/VMM/VMMAll/EMAll.cpp

    r7905 r8098  
    12451245    OP_PARAMVAL param1, param2;
    12461246
     1247#ifdef LOG_ENABLED
     1248    char *pszInstr;
     1249
     1250    if (pCpu->prefix & PREFIX_LOCK)
     1251        pszInstr = "Lock CmpXchg";
     1252    else
     1253        pszInstr = "CmpXchg";
     1254#endif
     1255
    12471256    /* Source to make DISQueryParamVal read the register value - ugly hack */
    12481257    int rc = DISQueryParamVal(pRegFrame, pCpu, &pCpu->param1, &param1, PARAM_SOURCE);
     
    12891298            }
    12901299
    1291             LogFlow(("CmpXchg %VGv=%08x eax=%08x %08x\n", pParam1, valpar1, pRegFrame->eax, valpar));
     1300            LogFlow(("%s %VGv=%08x eax=%08x %08x\n", pszInstr, pParam1, valpar1, pRegFrame->eax, valpar));
    12921301
    12931302            MMGCRamRegisterTrapHandler(pVM);
     
    13001309            if (VBOX_FAILURE(rc))
    13011310            {
    1302                 Log(("CmpXchg %VGv=%08x eax=%08x %08x -> emulation failed due to page fault!\n", pParam1, valpar1, pRegFrame->eax, valpar));
    1303                 return VERR_EM_INTERPRETER;
    1304             }
    1305 
    1306             LogFlow(("CmpXchg %VGv=%08x eax=%08x %08x ZF=%d\n", pParam1, valpar1, pRegFrame->eax, valpar, !!(eflags & X86_EFL_ZF)));
     1311                Log(("%s %VGv=%08x eax=%08x %08x -> emulation failed due to page fault!\n", pszInstr, pParam1, valpar1, pRegFrame->eax, valpar));
     1312                return VERR_EM_INTERPRETER;
     1313            }
     1314
     1315            LogFlow(("%s %VGv=%08x eax=%08x %08x ZF=%d\n", pszInstr, pParam1, valpar1, pRegFrame->eax, valpar, !!(eflags & X86_EFL_ZF)));
    13071316
    13081317            /* Update guest's eflags and finish. */
     
    13111320
    13121321            *pcbSize = param2.size;
     1322            return VINF_SUCCESS;
     1323        }
     1324    }
     1325    return VERR_EM_INTERPRETER;
     1326}
     1327
     1328/*
     1329 * [LOCK] CMPXCHG8B emulation.
     1330 */
     1331static int emInterpretCmpXchg8b(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
     1332{
     1333    OP_PARAMVAL param1;
     1334
     1335#ifdef LOG_ENABLED
     1336    char *pszInstr;
     1337
     1338    if (pCpu->prefix & PREFIX_LOCK)
     1339        pszInstr = "Lock CmpXchg8b";
     1340    else
     1341        pszInstr = "CmpXchg8b";
     1342#endif
     1343
     1344    /* Source to make DISQueryParamVal read the register value - ugly hack */
     1345    int rc = DISQueryParamVal(pRegFrame, pCpu, &pCpu->param1, &param1, PARAM_SOURCE);
     1346    if(VBOX_FAILURE(rc))
     1347        return VERR_EM_INTERPRETER;
     1348
     1349    if (TRPMHasTrap(pVM))
     1350    {
     1351        if (TRPMGetErrorCode(pVM) & X86_TRAP_PF_RW)
     1352        {
     1353            RTGCPTR pParam1;
     1354            uint32_t eflags;
     1355
     1356            AssertReturn(pCpu->param1.size == pCpu->param2.size, VERR_EM_INTERPRETER);
     1357            switch(param1.type)
     1358            {
     1359            case PARMTYPE_ADDRESS:
     1360                pParam1 = (RTGCPTR)param1.val.val32;
     1361                pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, pParam1);
     1362
     1363                /* Safety check (in theory it could cross a page boundary and fault there though) */
     1364                AssertMsgReturn(pParam1 == pvFault, ("eip=%VGv pParam1=%VGv pvFault=%VGv\n", pRegFrame->eip, pParam1, pvFault), VERR_EM_INTERPRETER);
     1365                break;
     1366
     1367            default:
     1368                return VERR_EM_INTERPRETER;
     1369            }
     1370
     1371            LogFlow(("%s %VGv=%08x eax=%08x\n", pszInstr, pParam1, pRegFrame->eax));
     1372
     1373            MMGCRamRegisterTrapHandler(pVM);
     1374            if (pCpu->prefix & PREFIX_LOCK)
     1375                rc = EMGCEmulateLockCmpXchg8b(pParam1, &pRegFrame->eax, &pRegFrame->edx, pRegFrame->ebx, pRegFrame->ecx, &eflags);
     1376            else
     1377                rc = EMGCEmulateCmpXchg8b(pParam1, &pRegFrame->eax, &pRegFrame->edx, pRegFrame->ebx, pRegFrame->ecx, &eflags);
     1378            MMGCRamDeregisterTrapHandler(pVM);
     1379
     1380            if (VBOX_FAILURE(rc))
     1381            {
     1382                Log(("%s %VGv=%08x eax=%08x -> emulation failed due to page fault!\n", pszInstr, pParam1, pRegFrame->eax));
     1383                return VERR_EM_INTERPRETER;
     1384            }
     1385
     1386            LogFlow(("%s %VGv=%08x eax=%08x ZF=%d\n", pszInstr, pParam1, pRegFrame->eax, !!(eflags & X86_EFL_ZF)));
     1387
     1388            /* Update guest's eflags and finish. */
     1389            pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
     1390                                  | (eflags                &  (X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF));
     1391
     1392            *pcbSize = 8;
    13131393            return VINF_SUCCESS;
    13141394        }
     
    20682148        INTERPRET_CASE(OP_STI,Sti);
    20692149        INTERPRET_CASE(OP_CMPXCHG, CmpXchg);
     2150        INTERPRET_CASE(OP_CMPXCHG8B, CmpXchg8b);
    20702151        INTERPRET_CASE(OP_XADD, XAdd);
    20712152#endif
     
    20752156#ifndef IN_GC
    20762157        INTERPRET_STAT_CASE(OP_CMPXCHG,CmpXchg);
     2158        INTERPRET_STAT_CASE(OP_CMPXCHG8B, CmpXchg8b);
    20772159        INTERPRET_STAT_CASE(OP_XADD, XAdd);
    20782160#endif
  • trunk/src/VBox/VMM/VMMGC/EMGCA.asm

    r7294 r8098  
    167167
    168168;;
     169; Emulate LOCK CMPXCHG8B instruction, CDECL calling conv.
     170; EMGCDECL(uint32_t) EMGCEmulateLockCmpXchg8b(RTGCPTR pu32Param1, uint32_t *pEAX, uint32_t *pEDX, uint32_t uEBX, uint32_t uECX, uint32_t *pEflags);
     171;
     172; @returns eax=0 if data written, other code - invalid access, #PF was generated.
     173; @param    [esp + 04h]    Param 1 - First parameter - pointer to first parameter
     174; @param    [esp + 08h]    Param 2 - Address of the eax register
     175; @param    [esp + 0ch]    Param 3 - Address of the edx register
     176; @param    [esp + 10h]    Param 4 - EBX
     177; @param    [esp + 14h]    Param 5 - ECX
     178; @param    [esp + 18h]    Param 6 - Pointer to eflags (out)
     179; @uses     eax, ecx, edx
     180;
     181align 16
     182BEGINPROC   EMGCEmulateLockCmpXchg8b
     183    push    ebp
     184    push    ebx
     185    mov     ebp, [esp + 04h + 8]        ; ebp = first parameter
     186    mov     eax, [esp + 08h + 8]        ; &EAX
     187    mov     eax, dword [eax]
     188    mov     edx, [esp + 0ch + 8]        ; &EDX
     189    mov     edx, dword [edx]
     190    mov     ebx, [esp + 10h + 8]        ; EBX
     191    mov     ecx, [esp + 14h + 8]        ; ECX
     192
     193    lock cmpxchg8b qword [ebp]          ; do CMPXCHG8B
     194    mov     dword [esp + 08h + 8], eax
     195    mov     dword [esp + 0ch + 8], edx
     196
     197    ; collect flags and return.
     198    pushf
     199    pop     eax
     200
     201    mov     edx, [esp + 18h + 8]            ; eflags pointer
     202    mov     dword [edx], eax
     203
     204    pop     ebx
     205    pop     ebp
     206    mov     eax, VINF_SUCCESS
     207    retn
     208
     209; Read error - we will be here after our page fault handler.
     210GLOBALNAME EMGCEmulateLockCmpXchg8b_Error
     211    pop     ebx
     212    pop     ebp
     213    mov     eax, VERR_ACCESS_DENIED
     214    ret
     215
     216ENDPROC     EMGCEmulateLockCmpXchg8b
     217
     218;;
     219; Emulate CMPXCHG8B instruction, CDECL calling conv.
     220; EMGCDECL(uint32_t) EMGCEmulateCmpXchg8b(RTGCPTR pu32Param1, uint32_t *pEAX, uint32_t *pEDX, uint32_t uEBX, uint32_t uECX, uint32_t *pEflags);
     221;
     222; @returns eax=0 if data written, other code - invalid access, #PF was generated.
     223; @param    [esp + 04h]    Param 1 - First parameter - pointer to first parameter
     224; @param    [esp + 08h]    Param 2 - Address of the eax register
     225; @param    [esp + 0ch]    Param 3 - Address of the edx register
     226; @param    [esp + 10h]    Param 4 - EBX
     227; @param    [esp + 14h]    Param 5 - ECX
     228; @param    [esp + 18h]    Param 6 - Pointer to eflags (out)
     229; @uses     eax, ecx, edx
     230;
     231align 16
     232BEGINPROC   EMGCEmulateCmpXchg8b
     233    push    ebp
     234    push    ebx
     235    mov     ebp, [esp + 04h + 8]        ; ebp = first parameter
     236    mov     eax, [esp + 08h + 8]        ; &EAX
     237    mov     eax, dword [eax]
     238    mov     edx, [esp + 0ch + 8]        ; &EDX
     239    mov     edx, dword [edx]
     240    mov     ebx, [esp + 10h + 8]        ; EBX
     241    mov     ecx, [esp + 14h + 8]        ; ECX
     242
     243    cmpxchg8b qword [ebp]               ; do CMPXCHG8B
     244    mov     dword [esp + 08h + 8], eax
     245    mov     dword [esp + 0ch + 8], edx
     246
     247    ; collect flags and return.
     248    pushf
     249    pop     eax
     250
     251    mov     edx, [esp + 18h + 8]            ; eflags pointer
     252    mov     dword [edx], eax
     253
     254    pop     ebx
     255    pop     ebp
     256    mov     eax, VINF_SUCCESS
     257    retn
     258
     259; Read error - we will be here after our page fault handler.
     260GLOBALNAME EMGCEmulateCmpXchg8b_Error
     261    pop     ebx
     262    pop     ebp
     263    mov     eax, VERR_ACCESS_DENIED
     264    ret
     265ENDPROC     EMGCEmulateCmpXchg8b
     266
     267;;
    169268; Emulate LOCK XADD instruction, CDECL calling conv.
    170269; EMGCDECL(uint32_t) EMGCEmulateLockXAdd(RTGCPTR pu32Param1, uint32_t *pu32Param2, uint32_t u32Param3, size_t cbSize, uint32_t *pEflags);
  • trunk/src/VBox/VMM/VMMGC/MMRamGC.cpp

    r7286 r8098  
    4545DECLASM(void) EMGCEmulateCmpXchg_EndProc(void);
    4646DECLASM(void) EMGCEmulateCmpXchg_Error(void);
     47DECLASM(void) EMGCEmulateLockCmpXchg8b_EndProc(void);
     48DECLASM(void) EMGCEmulateLockCmpXchg8b_Error(void);
     49DECLASM(void) EMGCEmulateCmpXchg8b_EndProc(void);
     50DECLASM(void) EMGCEmulateCmpXchg8b_Error(void);
    4751DECLASM(void) EMGCEmulateLockXAdd_EndProc(void);
    4852DECLASM(void) EMGCEmulateLockXAdd_Error(void);
     
    188192
    189193    /*
     194     * Page fault inside EMGCEmulateLockCmpXchg8b()? Resume at _Error.
     195     */
     196    if (    (uintptr_t)&EMGCEmulateLockCmpXchg8b < (uintptr_t)pRegFrame->eip
     197        &&  (uintptr_t)pRegFrame->eip < (uintptr_t)&EMGCEmulateLockCmpXchg8b_EndProc)
     198    {
     199        pRegFrame->eip = (uintptr_t)&EMGCEmulateLockCmpXchg8b_Error;
     200        return VINF_SUCCESS;
     201    }
     202
     203    /*
     204     * Page fault inside EMGCEmulateCmpXchg8b()? Resume at _Error.
     205     */
     206    if (    (uintptr_t)&EMGCEmulateCmpXchg8b < (uintptr_t)pRegFrame->eip
     207        &&  (uintptr_t)pRegFrame->eip < (uintptr_t)&EMGCEmulateCmpXchg8b_EndProc)
     208    {
     209        pRegFrame->eip = (uintptr_t)&EMGCEmulateCmpXchg8b_Error;
     210        return VINF_SUCCESS;
     211    }
     212
     213    /*
    190214     * Page fault inside EMGCEmulateLockXAdd()? Resume at _Error.
    191215     */
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