VirtualBox

Changeset 7286 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Mar 5, 2008 8:06:41 AM (17 years ago)
Author:
vboxsync
Message:

emulate [lock] xadd in GC

Location:
trunk/src/VBox/VMM
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/EM.cpp

    r6796 r7286  
    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->StatGCXAdd,                 STAMTYPE_COUNTER, "/EM/GC/Interpret/Success/XAdd",      STAMUNIT_OCCURENCES,    "The number of times XADD was successfully interpreted.");
     204    STAM_REG_USED(pVM, &pStats->StatHCXAdd,                 STAMTYPE_COUNTER, "/EM/HC/Interpret/Success/XAdd",      STAMUNIT_OCCURENCES,    "The number of times XADD was successfully interpreted.");
    203205
    204206    STAM_REG(pVM, &pStats->StatGCInterpretFailed,           STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed",            STAMUNIT_OCCURENCES,    "The number of times an instruction was not interpreted.");
     
    260262    STAM_REG_USED(pVM, &pStats->StatGCFailedCmpXchg,        STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/CmpXchg",    STAMUNIT_OCCURENCES,    "The number of times CMPXCHG was not interpreted.");
    261263    STAM_REG_USED(pVM, &pStats->StatHCFailedCmpXchg,        STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/CmpXchg",    STAMUNIT_OCCURENCES,    "The number of times CMPXCHG was not interpreted.");
     264    STAM_REG_USED(pVM, &pStats->StatGCFailedXAdd,           STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/XAdd",       STAMUNIT_OCCURENCES,    "The number of times XADD was not interpreted.");
     265    STAM_REG_USED(pVM, &pStats->StatHCFailedXAdd,           STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/XAdd",       STAMUNIT_OCCURENCES,    "The number of times XADD was not interpreted.");
    262266    STAM_REG_USED(pVM, &pStats->StatGCFailedMovNTPS,        STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/MovNTPS",    STAMUNIT_OCCURENCES,    "The number of times MOVNTPS was not interpreted.");
    263267    STAM_REG_USED(pVM, &pStats->StatHCFailedMovNTPS,        STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/MovNTPS",    STAMUNIT_OCCURENCES,    "The number of times MOVNTPS was not interpreted.");
  • trunk/src/VBox/VMM/EMInternal.h

    r5999 r7286  
    131131    STAMCOUNTER             StatGCCmpXchg;
    132132    STAMCOUNTER             StatHCCmpXchg;
     133    STAMCOUNTER             StatGCXAdd;
     134    STAMCOUNTER             StatHCXAdd;
    133135    STAMCOUNTER             StatGCClts;
    134136    STAMCOUNTER             StatHCClts;
     
    190192    STAMCOUNTER             StatGCFailedCmpXchg;
    191193    STAMCOUNTER             StatHCFailedCmpXchg;
     194    STAMCOUNTER             StatGCFailedXAdd;
     195    STAMCOUNTER             StatHCFailedXAdd;
    192196    STAMCOUNTER             StatHCFailedMovNTPS;
    193197    STAMCOUNTER             StatGCFailedMovNTPS;
  • trunk/src/VBox/VMM/VMMAll/EMAll.cpp

    r6297 r7286  
    12371237}
    12381238
     1239/*
     1240 * [LOCK] CMPXCHG emulation.
     1241 */
    12391242#ifdef IN_GC
    12401243static int emInterpretCmpXchg(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
     
    13081311
    13091312            *pcbSize = param2.size;
     1313            return VINF_SUCCESS;
     1314        }
     1315    }
     1316    return VERR_EM_INTERPRETER;
     1317}
     1318#endif
     1319
     1320/*
     1321 * [LOCK] XADD emulation.
     1322 */
     1323#ifdef IN_GC
     1324static int emInterpretXAdd(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
     1325{
     1326    OP_PARAMVAL param1;
     1327    uint32_t *pParamReg2;
     1328    size_t cbSizeParamReg2;
     1329
     1330    /* Source to make DISQueryParamVal read the register value - ugly hack */
     1331    int rc = DISQueryParamVal(pRegFrame, pCpu, &pCpu->param1, &param1, PARAM_SOURCE);
     1332    if(VBOX_FAILURE(rc))
     1333        return VERR_EM_INTERPRETER;
     1334
     1335    rc = DISQueryParamRegPtr(pRegFrame, pCpu, &pCpu->param2, &pParamReg2, &cbSizeParamReg2);
     1336    if(VBOX_FAILURE(rc))
     1337        return VERR_EM_INTERPRETER;
     1338
     1339    if (TRPMHasTrap(pVM))
     1340    {
     1341        if (TRPMGetErrorCode(pVM) & X86_TRAP_PF_RW)
     1342        {
     1343            RTGCPTR pParam1;
     1344            uint32_t eflags;
     1345#ifdef VBOX_STRICT
     1346            uint32_t valpar1 = 0; /// @todo used uninitialized...
     1347#endif
     1348
     1349            AssertReturn(pCpu->param1.size == pCpu->param2.size, VERR_EM_INTERPRETER);
     1350            switch(param1.type)
     1351            {
     1352            case PARMTYPE_ADDRESS:
     1353                pParam1 = (RTGCPTR)param1.val.val32;
     1354                pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, pParam1);
     1355
     1356                /* Safety check (in theory it could cross a page boundary and fault there though) */
     1357                AssertMsgReturn(pParam1 == pvFault, ("eip=%VGv pParam1=%VGv pvFault=%VGv\n", pRegFrame->eip, pParam1, pvFault), VERR_EM_INTERPRETER);
     1358                break;
     1359
     1360            default:
     1361                return VERR_EM_INTERPRETER;
     1362            }
     1363
     1364            LogFlow(("XAdd %VGv=%08x reg=%08x\n", pParam1, *pParamReg2));
     1365
     1366            MMGCRamRegisterTrapHandler(pVM);
     1367            if (pCpu->prefix & PREFIX_LOCK)
     1368                rc = EMGCEmulateLockXAdd(pParam1, pParamReg2, cbSizeParamReg2, &eflags);
     1369            else
     1370                rc = EMGCEmulateXAdd(pParam1, pParamReg2, cbSizeParamReg2, &eflags);
     1371            MMGCRamDeregisterTrapHandler(pVM);
     1372
     1373            if (VBOX_FAILURE(rc))
     1374            {
     1375                Log(("XAdd %VGv=%08x reg=%08x -> emulation failed due to page fault!\n", pParam1, valpar1, pRegFrame->eax));
     1376                return VERR_EM_INTERPRETER;
     1377            }
     1378
     1379            LogFlow(("XAdd %VGv=%08x reg=%08x ZF=%d\n", pParam1, valpar1, pRegFrame->eax, !!(eflags & X86_EFL_ZF)));
     1380
     1381            /* Update guest's eflags and finish. */
     1382            pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
     1383                                  | (eflags                &  (X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF));
     1384
     1385            *pcbSize = cbSizeParamReg2;
    13101386            return VINF_SUCCESS;
    13111387        }
     
    19101986        ||  (   (pCpu->prefix & PREFIX_LOCK)
    19111987             && pCpu->pCurInstr->opcode != OP_CMPXCHG
     1988             && pCpu->pCurInstr->opcode != OP_XADD
    19121989             && pCpu->pCurInstr->opcode != OP_OR
    19131990             && pCpu->pCurInstr->opcode != OP_BTR
     
    19932070        INTERPRET_CASE(OP_STI,Sti);
    19942071        INTERPRET_CASE(OP_CMPXCHG, CmpXchg);
     2072        INTERPRET_CASE(OP_XADD, XAdd);
    19952073#endif
    19962074        INTERPRET_CASE(OP_HLT,Hlt);
     
    19992077#ifndef IN_GC
    20002078        INTERPRET_STAT_CASE(OP_CMPXCHG,CmpXchg);
     2079        INTERPRET_STAT_CASE(OP_XADD, XAdd);
    20012080#endif
    20022081        INTERPRET_STAT_CASE(OP_MOVNTPS,MovNTPS);
  • trunk/src/VBox/VMM/VMMGC/EMGCA.asm

    • Property svn:eol-style set to native
    r5999 r7286  
    2626
    2727;;
    28 ; Emulate lock CMPXCHG instruction, CDECL calling conv.
     28; Emulate LOCK CMPXCHG instruction, CDECL calling conv.
    2929; EMGCDECL(uint32_t) EMGCEmulateLockCmpXchg(RTGCPTR pu32Param1, uint32_t *pu32Param2, uint32_t u32Param3, size_t cbSize, uint32_t *pEflags);
    3030;
     
    165165    ret
    166166ENDPROC     EMGCEmulateCmpXchg
     167
     168;;
     169; Emulate LOCK XADD instruction, CDECL calling conv.
     170; EMGCDECL(uint32_t) EMGCEmulateLockXAdd(RTGCPTR pu32Param1, uint32_t *pu32Param2, uint32_t u32Param3, size_t cbSize, uint32_t *pEflags);
     171;
     172; @returns eax=0 if data exchanged, 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 - Second parameter - pointer to second parameter (general register)
     175; @param    [esp + 0ch]    Param 3 - Size of parameters, only 1/2/4 is valid.
     176; @param    [esp + 10h]    Param 4 - Pointer to eflags (out)
     177; @uses     eax, ecx, edx
     178;
     179align 16
     180BEGINPROC   EMGCEmulateLockXAdd
     181    push    ebx
     182    mov     ecx, [esp + 04h + 4]        ; ecx = first parameter
     183    mov     ebx, [esp + 08h + 4]        ; ebx = 2nd parameter
     184    mov     eax, [esp + 0ch + 4]        ; eax = size of parameters
     185
     186    cmp     al, 4
     187    je short .do_dword                  ; 4 bytes variant
     188    cmp     al, 2
     189    je short .do_word                   ; 2 byte variant
     190    cmp     al, 1
     191    je short .do_byte                   ; 1 bytes variant
     192    int3
     193
     194.do_dword:
     195    ; load 2nd parameter's value
     196    mov     eax, dword [ebx]
     197    lock xadd dword [ecx], eax              ; do 4 bytes XADD
     198    mov     dword [ebx], eax
     199    jmp     short .done
     200
     201.do_word:
     202    ; load 2nd parameter's value
     203    mov     eax, dword [ebx]
     204    lock xadd word [ecx], ax                ; do 2 bytes XADD
     205    mov     word [ebx], ax
     206    jmp     short .done
     207
     208.do_byte:
     209    ; load 2nd parameter's value
     210    mov     eax, dword [ebx]
     211    lock xadd byte [ecx], al                ; do 1 bytes XADD
     212    mov     byte [ebx], al
     213
     214.done:
     215    ; collect flags and return.
     216    pushf
     217    pop     eax
     218
     219    mov     edx, [esp + 10h + 4]            ; eflags pointer
     220    mov     dword [edx], eax
     221
     222    pop     ebx
     223    mov     eax, VINF_SUCCESS
     224    retn
     225
     226; Read error - we will be here after our page fault handler.
     227GLOBALNAME EMGCEmulateLockXAdd_Error
     228    pop     ebx
     229    mov     eax, VERR_ACCESS_DENIED
     230    ret
     231
     232ENDPROC     EMGCEmulateLockXAdd
     233
     234;;
     235; Emulate XADD instruction, CDECL calling conv.
     236; EMGCDECL(uint32_t) EMGCEmulateXAdd(RTGCPTR pu32Param1, uint32_t *pu32Param2, uint32_t u32Param3, size_t cbSize, uint32_t *pEflags);
     237;
     238; @returns eax=0 if data written, other code - invalid access, #PF was generated.
     239; @param    [esp + 04h]    Param 1 - First parameter - pointer to first parameter
     240; @param    [esp + 08h]    Param 2 - Second parameter - pointer to second parameter (general register)
     241; @param    [esp + 0ch]    Param 3 - Size of parameters, only 1/2/4 is valid.
     242; @param    [esp + 10h]    Param 4 - Pointer to eflags (out)
     243; @uses     eax, ecx, edx
     244;
     245align 16
     246BEGINPROC   EMGCEmulateXAdd
     247    push    ebx
     248    mov     ecx, [esp + 04h + 4]        ; ecx = first parameter
     249    mov     ebx, [esp + 08h + 4]        ; ebx = 2nd parameter (eax)
     250    mov     eax, [esp + 0ch + 4]        ; eax = size of parameters
     251
     252    cmp     al, 4
     253    je short .do_dword                  ; 4 bytes variant
     254    cmp     al, 2
     255    je short .do_word                   ; 2 byte variant
     256    cmp     al, 1
     257    je short .do_byte                   ; 1 bytes variant
     258    int3
     259
     260.do_dword:
     261    ; load 2nd parameter's value
     262    mov     eax, dword [ebx]
     263    xadd    dword [ecx], eax            ; do 4 bytes XADD
     264    mov     dword [ebx], eax
     265    jmp     short .done
     266
     267.do_word:
     268    ; load 2nd parameter's value
     269    mov     eax, dword [ebx]
     270    xadd    word [ecx], ax              ; do 2 bytes XADD
     271    mov     word [ebx], ax
     272    jmp     short .done
     273
     274.do_byte:
     275    ; load 2nd parameter's value
     276    mov     eax, dword [ebx]
     277    xadd    byte [ecx], al              ; do 1 bytes XADD
     278    mov     byte [ebx], al
     279
     280.done:
     281    ; collect flags and return.
     282    pushf
     283    pop     eax
     284
     285    mov     edx, [esp + 10h + 4]        ; eflags pointer
     286    mov     dword [edx], eax
     287
     288    pop     ebx
     289    mov     eax, VINF_SUCCESS
     290    retn
     291
     292; Read error - we will be here after our page fault handler.
     293GLOBALNAME EMGCEmulateXAdd_Error
     294    pop     ebx
     295    mov     eax, VERR_ACCESS_DENIED
     296    ret
     297ENDPROC     EMGCEmulateXAdd
  • trunk/src/VBox/VMM/VMMGC/MMRamGC.cpp

    r5999 r7286  
    4545DECLASM(void) EMGCEmulateCmpXchg_EndProc(void);
    4646DECLASM(void) EMGCEmulateCmpXchg_Error(void);
     47DECLASM(void) EMGCEmulateLockXAdd_EndProc(void);
     48DECLASM(void) EMGCEmulateLockXAdd_Error(void);
     49DECLASM(void) EMGCEmulateXAdd_EndProc(void);
     50DECLASM(void) EMGCEmulateXAdd_Error(void);
    4751DECLASM(void) EMEmulateLockOr_EndProc(void);
    4852DECLASM(void) EMEmulateLockOr_Error(void);
     
    184188
    185189    /*
     190     * Page fault inside EMGCEmulateLockXAdd()? Resume at _Error.
     191     */
     192    if (    (uintptr_t)&EMGCEmulateLockXAdd < (uintptr_t)pRegFrame->eip
     193        &&  (uintptr_t)pRegFrame->eip < (uintptr_t)&EMGCEmulateLockXAdd_EndProc)
     194    {
     195        pRegFrame->eip = (uintptr_t)&EMGCEmulateLockXAdd_Error;
     196        return VINF_SUCCESS;
     197    }
     198
     199    /*
     200     * Page fault inside EMGCEmulateXAdd()? Resume at _Error.
     201     */
     202    if (    (uintptr_t)&EMGCEmulateXAdd < (uintptr_t)pRegFrame->eip
     203        &&  (uintptr_t)pRegFrame->eip < (uintptr_t)&EMGCEmulateXAdd_EndProc)
     204    {
     205        pRegFrame->eip = (uintptr_t)&EMGCEmulateXAdd_Error;
     206        return VINF_SUCCESS;
     207    }
     208
     209    /*
    186210     * Page fault inside EMEmulateLockOr()? Resume at *_Error.
    187211     */
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