VirtualBox

Changeset 302 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
Jan 25, 2007 2:48:55 PM (18 years ago)
Author:
vboxsync
Message:

Handle iret to ring 0 code with IF cleared. Warning: possibly dangerous change.

Location:
trunk/src/VBox/VMM/PATM
Files:
7 edited

Legend:

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

    r208 r302  
    427427        pVM->patm.s.pfnHelperCallGC += delta;
    428428        pVM->patm.s.pfnHelperRetGC  += delta;
     429        pVM->patm.s.pfnHelperIretGC += delta;
    429430        pVM->patm.s.pfnHelperJumpGC += delta;
    430431
  • trunk/src/VBox/VMM/PATM/PATMA.asm

    r277 r302  
    10941094
    10951095    test    dword [esp+12], X86_EFL_IF
    1096     jz      iret_fault
     1096    jz      iret_clearIF
    10971097
    10981098    ; if interrupts are pending, then we must go back to the host context to handle them!
     
    11511151    mov     dword [ss:PATM_INTERRUPTFLAG], 1
    11521152    PATM_INT3
     1153
     1154iret_clearIF:
     1155    push    dword [esp+4]           ; eip to return to
     1156    pushfd
     1157    push    eax
     1158    push    PATM_FIXUP
     1159    DB      0E8h                    ; call
     1160    DD      PATM_IRET_FUNCTION
     1161    add     esp, 4                  ; pushed address of jump table
     1162
     1163    cmp     eax, 0
     1164    je      near iret_fault3
     1165
     1166    mov     dword [esp+12+4], eax   ; stored eip in iret frame
     1167    pop     eax
     1168    popfd
     1169    add     esp, 4                  ; pushed eip
     1170
     1171    ; always ring 0 return -> change to ring 1 (CS in iret frame)
     1172    or      dword [esp+8], 1
     1173
     1174        ; This section must *always* be executed (!!)
     1175        ; Extract the IOPL from the return flags, save them to our virtual flags and
     1176        ; put them back to zero
     1177        push    eax
     1178        mov     eax, dword [esp+16]
     1179        and     eax, X86_EFL_IOPL
     1180        and     dword [ss:PATM_VMFLAGS], ~X86_EFL_IOPL
     1181        or      dword [ss:PATM_VMFLAGS], eax
     1182    pop         eax
     1183        and             dword [esp+12], ~X86_EFL_IOPL
     1184
     1185    ; Clear IF
     1186    and     dword [ss:PATM_VMFLAGS], ~X86_EFL_IF
     1187    popfd
     1188
     1189                                                ; the patched destination code will set PATM_INTERRUPTFLAG after the return!
     1190    iretd
     1191
     1192iret_fault3:
     1193    pop     eax
     1194    popfd
     1195    add     esp, 4                  ; pushed eip
     1196    jmp     iret_fault
     1197
     1198align   4
     1199PATMIretTable:
     1200    DW      PATM_MAX_JUMPTABLE_ENTRIES          ; nrSlots
     1201    DW      0                                   ; ulInsertPos
     1202    DD      0                                   ; cAddresses
     1203    RESB    PATCHJUMPTABLE_SIZE                 ; lookup slots
     1204   
    11531205PATMIretEnd:
    11541206ENDPROC     PATMIretReplacement
     
    11621214    DD      PATMIretEnd- PATMIretStart
    11631215%ifdef PATM_LOG_IF_CHANGES
    1164     DD      17
     1216    DD      22
    11651217%else
    1166     DD      16
     1218    DD      21
    11671219%endif
    11681220    DD      PATM_INTERRUPTFLAG
     
    12011253    DD      0
    12021254    DD      PATM_INTERRUPTFLAG
     1255    DD      0
     1256    DD      PATM_FIXUP
     1257    DD      PATMIretTable - PATMIretStart
     1258    DD      PATM_IRET_FUNCTION
     1259    DD      0
     1260    DD      PATM_VMFLAGS
     1261    DD      0
     1262    DD      PATM_VMFLAGS
     1263    DD      0
     1264    DD      PATM_VMFLAGS
     1265    DD      0
     1266    DD      0ffffffffh
     1267
     1268
     1269;
     1270; global function for implementing 'iret' to code with IF cleared
     1271;
     1272; Caller is responsible for right stack layout
     1273;  + 16 original return address
     1274;  + 12 eflags
     1275;  +  8 eax
     1276;  +  4 Jump table address
     1277;( +  0 return address )
     1278;
     1279; @note assumes PATM_INTERRUPTFLAG is zero
     1280; @note assumes it can trash eax and eflags
     1281;
     1282; @returns eax=0 on failure
     1283;          otherwise return address in eax
     1284;
     1285; @note NEVER change this without bumping the SSM version
     1286align 16
     1287BEGINPROC   PATMIretFunction
     1288PATMIretFunction_Start:
     1289    push    ecx
     1290    push    edx
     1291    push    edi
     1292
     1293    ; Event order:
     1294    ; 1) Check if the return patch address can be found in the lookup table
     1295    ; 2) Query return patch address from the hypervisor
     1296
     1297    ; 1) Check if the return patch address can be found in the lookup table
     1298    mov     edx, dword [esp+12+16]  ; pushed target address
     1299
     1300    xor     eax, eax                ; default result -> nothing found
     1301    mov     edi, dword [esp+12+4]  ; jump table
     1302    mov     ecx, [ss:edi + PATCHJUMPTABLE.cAddresses]
     1303    cmp     ecx, 0
     1304    je      near PATMIretFunction_AskHypervisor
     1305
     1306PATMIretFunction_SearchStart:
     1307    cmp     [ss:edi + PATCHJUMPTABLE.Slot_pInstrGC + eax*8], edx        ; edx = GC address to search for
     1308    je      near PATMIretFunction_SearchHit
     1309    inc     eax
     1310    cmp     eax, ecx
     1311    jl      near PATMIretFunction_SearchStart
     1312
     1313PATMIretFunction_AskHypervisor:
     1314    ; 2) Query return patch address from the hypervisor
     1315    ; @todo private ugly interface, since we have nothing generic at the moment
     1316    lock    or dword [ss:PATM_PENDINGACTION], PATM_ACTION_LOOKUP_ADDRESS
     1317    mov     eax, PATM_ACTION_LOOKUP_ADDRESS
     1318    mov     ecx, PATM_ACTION_MAGIC
     1319    mov     edi, dword [esp+12+4]               ; jump table address
     1320    mov     edx, dword [esp+12+16]              ; original return address
     1321    db      0fh, 0bh        ; illegal instr (hardcoded assumption in PATMHandleIllegalInstrTrap)
     1322    jmp     near PATMIretFunction_SearchEnd
     1323
     1324PATMIretFunction_SearchHit:
     1325    mov     eax, [ss:edi + PATCHJUMPTABLE.Slot_pRelPatchGC + eax*8]        ; found a match!
     1326    ;@note can be zero, so the next check is required!!
     1327
     1328PATMIretFunction_SearchEnd:
     1329    cmp     eax, 0
     1330    jz      PATMIretFunction_Failure
     1331
     1332    add     eax, PATM_PATCHBASE
     1333
     1334    pop     edi
     1335    pop     edx
     1336    pop     ecx
     1337    ret
     1338
     1339PATMIretFunction_Failure:
     1340    ;signal error
     1341    xor     eax, eax
     1342    pop     edi
     1343    pop     edx
     1344    pop     ecx
     1345    ret
     1346
     1347PATMIretFunction_End:
     1348ENDPROC     PATMIretFunction
     1349
     1350GLOBALNAME PATMIretFunctionRecord
     1351    RTCCPTR_DEF PATMIretFunction_Start
     1352    DD      0
     1353    DD      0
     1354    DD      0
     1355    DD      PATMIretFunction_End - PATMIretFunction_Start
     1356    DD      2
     1357    DD      PATM_PENDINGACTION
     1358    DD      0
     1359    DD      PATM_PATCHBASE
    12031360    DD      0
    12041361    DD      0ffffffffh
  • trunk/src/VBox/VMM/PATM/PATMA.h

    r267 r302  
    6565#define PATM_RETURN_FUNCTION                    0xF1ABCE08    /** Relative address of global PATM return function. */
    6666#define PATM_LOOKUP_AND_JUMP_FUNCTION           0xF1ABCE09    /** Relative address of global PATM lookup and jump function. */
     67#define PATM_IRET_FUNCTION                      0xF1ABCE0A    /** Relative address of global PATM iret function. */
    6768
    6869// everything except IOPL, NT, IF, VM, VIF, VIP and RF
     
    167168extern PATCHASMRECORD PATMRetFunctionRecord;
    168169extern PATCHASMRECORD PATMLookupAndJumpRecord;
     170extern PATCHASMRECORD PATMIretFunctionRecord;
    169171
    170172extern PATCHASMRECORD PATMStatsRecord;
  • trunk/src/VBox/VMM/PATM/PATMA.mac

    r267 r302  
    6464%define PATM_RETURN_FUNCTION                    0xF1ABCE08   ; /** Relative address of global PATM return function. */
    6565%define PATM_LOOKUP_AND_JUMP_FUNCTION           0xF1ABCE09   ; /** Relative address of global PATM lookup and jump function. */
     66%define PATM_IRET_FUNCTION                      0xF1ABCE0A   ; /** Relative address of global PATM iret function. */
    6667
    6768
  • trunk/src/VBox/VMM/PATM/PATMInternal.h

    r266 r302  
    3737
    3838
    39 #define PATM_SSM_VERSION                    49
     39#define PATM_SSM_VERSION                    50
    4040
    4141/* Enable for call patching. */
     
    402402    /** Global PATM jump function (used by indirect jmp patches). */
    403403    RTGCPTR                 pfnHelperJumpGC;
     404    /** Global PATM return function (used by iret patches). */
     405    RTGCPTR                 pfnHelperIretGC;
    404406
    405407    /** Fake patch record for global functions. */
  • trunk/src/VBox/VMM/PATM/PATMPatch.cpp

    r23 r302  
    124124
    125125#define PATCHGEN_EPILOG(pPatch, size) \
    126     Assert(size <= 400);              \
     126    Assert(size <= 512);              \
    127127    pPatch->uCurPatchOffset += size;
    128128
     
    309309                    /* Relative value is target minus address of instruction after the actual call instruction. */
    310310                    dest = pVM->patm.s.pfnHelperRetGC - pInstrAfterCall;
     311                    break;
     312                }
     313
     314                case PATM_IRET_FUNCTION:
     315                {
     316                    RTGCPTR pInstrAfterCall = pVM->patm.s.pPatchMemGC + (RTGCUINTPTR)(&pPB[j] + sizeof(RTGCPTR) - pVM->patm.s.pPatchMemHC);
     317                    Assert(pVM->patm.s.pfnHelperIretGC);
     318                    Assert(sizeof(uint32_t) == sizeof(RTGCPTR));
     319
     320                    /* Relative value is target minus address of instruction after the actual call instruction. */
     321                    dest = pVM->patm.s.pfnHelperIretGC - pInstrAfterCall;
    311322                    break;
    312323                }
     
    895906    PATCHGEN_EPILOG(pPatch, size);
    896907
     908    /* Round to next 8 byte boundary. */
     909    pPatch->uCurPatchOffset = RT_ALIGN_32(pPatch->uCurPatchOffset, 8);
     910
     911    pVM->patm.s.pfnHelperIretGC = PATCHCODE_PTR_GC(pPatch) + pPatch->uCurPatchOffset;
     912    PATCHGEN_PROLOG_NODEF(pVM, pPatch);
     913    size = patmPatchGenCode(pVM, pPatch, pPB, &PATMIretFunctionRecord, 0, false);
     914    PATCHGEN_EPILOG(pPatch, size);
     915
    897916    Log(("pfnHelperCallGC %VGv\n", pVM->patm.s.pfnHelperCallGC));
    898917    Log(("pfnHelperRetGC  %VGv\n", pVM->patm.s.pfnHelperRetGC));
    899918    Log(("pfnHelperJumpGC %VGv\n", pVM->patm.s.pfnHelperJumpGC));
     919    Log(("pfnHelperIretGC  %VGv\n", pVM->patm.s.pfnHelperIretGC));
    900920
    901921    return VINF_SUCCESS;
  • trunk/src/VBox/VMM/PATM/PATMSSM.cpp

    r101 r302  
    302302    }
    303303
     304    /* Relative calls are made to the helper functions. Therefor their location must not change! */
     305    if (    pVM->patm.s.pfnHelperCallGC != patmInfo.pfnHelperCallGC
     306        ||  pVM->patm.s.pfnHelperRetGC  != patmInfo.pfnHelperRetGC
     307        ||  pVM->patm.s.pfnHelperJumpGC != patmInfo.pfnHelperJumpGC
     308        ||  pVM->patm.s.pfnHelperIretGC != patmInfo.pfnHelperIretGC)
     309    {
     310        AssertMsgFailed(("Helper function ptrs don't match!!!\n"));
     311        return VERR_SSM_INVALID_STATE;
     312    }
     313
    304314    if (    pVM->patm.s.pPatchMemGC != patmInfo.pPatchMemGC
    305315        ||  pVM->patm.s.cbPatchMem != patmInfo.cbPatchMem)
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