VirtualBox

Changeset 4979

Show
Ignore:
Timestamp:
09/22/07 02:04:09 (1 year ago)
Author:
vboxsync
Message:

New ring-0 assertion avoidance, now for all platforms.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/include/iprt/assert.h

    r4976 r4979  
    109109#  define AssertCompileMemberAlignment(type, member, align) \ 
    110110    AssertCompile(!(RT_OFFSETOF(type, member) & ((align) - 1))) 
    111 # endif  
     111# endif 
    112112#else 
    113113# define AssertCompileMemberAlignment(type, member, align) \ 
    114114    AssertCompile(!(RT_OFFSETOF(type, member) & ((align) - 1))) 
    115 #endif  
     115#endif 
    116116 
    117117 
     
    491491#ifdef __GNUC__ 
    492492# ifndef __L4ENV__ 
    493 #  define AssertReleaseBreakpoint()   do { __asm__ __volatile__ ("int3\n\tnop"); } while (0) 
     493#  define AssertReleaseBreakpoint()     do { RTAssertDoBreakpoint(); __asm__ __volatile__ ("int3\n\tnop"); } while (0) 
    494494# else 
    495 #  define AssertReleaseBreakpoint()   do { __asm__ __volatile__ ("int3; jmp 1f; 1:"); } while (0) 
     495#  define AssertReleaseBreakpoint()     do { RTAssertDoBreakpoint(); __asm__ __volatile__ ("int3; jmp 1f; 1:"); } while (0) 
    496496# endif 
    497497#elif defined(_MSC_VER) 
    498 # define AssertReleaseBreakpoint()      __debugbreak(
     498# define AssertReleaseBreakpoint()      do { RTAssertDoBreakpoint(); __debugbreak(); } while (0
    499499#else 
    500500# error "Unknown compiler" 
     
    11741174 
    11751175/** 
    1176  * Overridable function that decides whether assertions executes the breakpoint or not.  
    1177  *  
     1176 * Overridable function that decides whether assertions executes the breakpoint or not. 
     1177 * 
    11781178 * The generic implementation will return true. 
    1179  *  
     1179 * 
    11801180 * @returns true if the breakpoint should be hit, false if it should be ignored. 
    11811181 * @remark  The RTDECL() makes this a bit difficult to override on windows. Sorry. 
    11821182 */ 
    11831183RTDECL(bool)    RTAssertDoBreakpoint(void); 
    1184  
    11851184 
    11861185/** The last assert message, 1st part. */ 
  • trunk/src/VBox/VMM/VMM.cpp

    r4971 r4979  
    641641        if (VBOX_FAILURE(rc) || (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST)) 
    642642            break; 
    643         break; // remove this when we do setjmp for all ring-0 stuff. 
     643        /* Resume R0 */ 
    644644    } 
    645645 
     
    647647    { 
    648648        LogRel(("R0 init failed, rc=%Vra\n", rc)); 
    649         if (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST
     649        if (VBOX_SUCCESS(rc)
    650650            rc = VERR_INTERNAL_ERROR; 
    651651    } 
     
    758758        if (VBOX_FAILURE(rc) || (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST)) 
    759759            break; 
    760         break; // remove this when we do setjmp for all ring-0 stuff. 
     760        /* Resume R0 */ 
    761761    } 
    762762    if (VBOX_FAILURE(rc) || (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST)) 
    763763    { 
    764764        LogRel(("VMMR3Term: R0 term failed, rc=%Vra. (warning)\n", rc)); 
    765         if (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST
     765        if (VBOX_SUCCESS(rc)
    766766            rc = VERR_INTERNAL_ERROR; 
    767767    } 
     
    22572257        /* 
    22582258         * Signal a ring 0 hypervisor assertion. 
     2259         * Cancel the longjmp operation that's in progress. 
    22592260         */ 
    22602261        case VMMCALLHOST_VM_R0_HYPER_ASSERTION: 
     2262            pVM->vmm.s.CallHostR0JmpBuf.fInRing3Call = false; 
     2263#ifdef RT_ARCH_X86 
     2264            pVM->vmm.s.CallHostR0JmpBuf.eip = 0; 
     2265#else 
     2266            pVM->vmm.s.CallHostR0JmpBuf.rip = 0; 
     2267#endif 
    22612268            return VINF_EM_DBG_HYPER_ASSERTION; 
    22622269 
  • trunk/src/VBox/VMM/VMMInternal.h

    r4787 r4979  
    404404 
    405405/** 
     406 * Callback function for vmmR0CallHostSetJmpEx. 
     407 * 
     408 * @returns VBox status code. 
     409 * @param   pvUser      The user argument. 
     410 */ 
     411typedef DECLCALLBACK(int) FNVMMR0SETJMPEX(void *pvUser); 
     412/** Pointer to FNVMMR0SETJMP(). */ 
     413typedef FNVMMR0SETJMPEX *PFNVMMR0SETJMPEX; 
     414 
     415/** 
     416 * Same as vmmR0CallHostSetJmp except for the function signature. 
     417 * 
     418 * @returns VINF_SUCCESS on success or whatever is passed to vmmR0CallHostLongJmp. 
     419 * @param   pJmpBuf     The jmp_buf to set. 
     420 * @param   pfn         The function to be called when not resuming.. 
     421 * @param   pvUser      The argument of that function. 
     422 */ 
     423DECLASM(int)    vmmR0CallHostSetJmpEx(PVMMR0JMPBUF pJmpBuf, PFNVMMR0SETJMPEX pfn, void *pvUser); 
     424 
     425 
     426/** 
    406427 * Worker for VMMR0CallHost. 
    407428 * This will save the stack and registers. 
  • trunk/src/VBox/VMM/VMMR0/VMMR0.cpp

    r4971 r4979  
    5454__END_DECLS 
    5555 
    56  
    57 /** @def DEBUG_NO_RING0_ASSERTIONS 
    58  * Define this if you don't wish to BSOD on debug assertions in 
    59  * the VMMR0.r0 code. If would of course be nice to have this 
    60  * feature enabled by default of course, but it's not currently 
    61  * safe when more than one VM is running or when using internal 
    62  * networking. */ 
    63 #if defined(DEBUG_sandervl) /*|| defined(DEBUG_bird)*/ 
    64 # define DEBUG_NO_RING0_ASSERTIONS 
    65 #endif 
    66 #ifdef DEBUG_NO_RING0_ASSERTIONS 
    67 static PVM g_pVMAssert = 0; 
    68 #endif 
    6956 
    7057/******************************************************************************* 
     
    616603            if (VBOX_SUCCESS(rc)) 
    617604            { 
    618 #ifdef DEBUG_NO_RING0_ASSERTIONS 
    619                 g_pVMAssert = pVM; 
    620 #endif 
    621605                rc = vmmR0CallHostSetJmp(&pVM->vmm.s.CallHostR0JmpBuf, HWACCMR0RunGuestCode, pVM); /* this may resume code. */ 
    622 #ifdef DEBUG_NO_RING0_ASSERTIONS 
    623                 g_pVMAssert = NULL; 
    624 #endif 
    625606                int rc2 = HWACCMR0Disable(pVM); 
    626607                AssertRC(rc2); 
     
    655636 
    656637/** 
    657  * The Ring 0 entry point, called by the support library (SUP). 
     638 * VMMR0EntryEx worker function, either called directly or when ever possible 
     639 * called thru a longjmp so we can exit safely on failure. 
    658640 * 
    659641 * @returns VBox status code. 
     
    664646 * @remarks Assume called with interrupts _enabled_. 
    665647 */ 
    666 VMMR0DECL(int) VMMR0EntryEx(PVM pVM, VMMR0OPERATION enmOperation, PSUPVMMR0REQHDR pReq, uint64_t u64Arg) 
     648static int vmmR0EntryExWorker(PVM pVM, VMMR0OPERATION enmOperation, PSUPVMMR0REQHDR pReq, uint64_t u64Arg) 
    667649{ 
    668650    switch (enmOperation) 
     
    672654         */ 
    673655        case VMMR0_DO_VMMR0_INIT: 
    674         { 
    675             int rc = VMMR0Init(pVM, (unsigned)u64Arg); 
    676             return rc; 
    677         } 
     656            return VMMR0Init(pVM, (unsigned)u64Arg); 
    678657 
    679658        /* 
     
    681660         */ 
    682661        case VMMR0_DO_VMMR0_TERM: 
    683         { 
    684             int rc = VMMR0Term(pVM); 
    685             return rc; 
    686         } 
     662            return VMMR0Term(pVM); 
    687663 
    688664        /* 
     
    833809 
    834810 
     811/** 
     812 * Argument for vmmR0EntryExWrapper containing the argument s ofr VMMR0EntryEx. 
     813 */ 
     814typedef struct VMMR0ENTRYEXARGS 
     815{ 
     816    PVM                 pVM; 
     817    VMMR0OPERATION      enmOperation; 
     818    PSUPVMMR0REQHDR     pReq; 
     819    uint64_t            u64Arg; 
     820} VMMR0ENTRYEXARGS; 
     821/** Pointer to a vmmR0EntryExWrapper argument package. */ 
     822typedef VMMR0ENTRYEXARGS *PVMMR0ENTRYEXARGS; 
     823 
     824/** 
     825 * This is just a longjmp wrapper function for VMMR0EntryEx calls. 
     826 * 
     827 * @returns VBox status code. 
     828 * @param   pvArgs      The argument package 
     829 */ 
     830static int vmmR0EntryExWrapper(void *pvArgs) 
     831{ 
     832    return vmmR0EntryExWorker(((PVMMR0ENTRYEXARGS)pvArgs)->pVM, 
     833                              ((PVMMR0ENTRYEXARGS)pvArgs)->enmOperation, 
     834                              ((PVMMR0ENTRYEXARGS)pvArgs)->pReq, 
     835                              ((PVMMR0ENTRYEXARGS)pvArgs)->u64Arg); 
     836} 
     837 
     838 
     839/** 
     840 * The Ring 0 entry point, called by the support library (SUP). 
     841 * 
     842 * @returns VBox status code. 
     843 * @param   pVM             The VM to operate on. 
     844 * @param   enmOperation    Which operation to execute. 
     845 * @param   pReq            This points to a SUPVMMR0REQHDR packet. Optional. 
     846 * @param   u64Arg          Some simple constant argument. 
     847 * @remarks Assume called with interrupts _enabled_. 
     848 */ 
     849VMMR0DECL(int) VMMR0EntryEx(PVM pVM, VMMR0OPERATION enmOperation, PSUPVMMR0REQHDR pReq, uint64_t u64Arg) 
     850{ 
     851    /* 
     852     * Requests that should only happen on the EMT thread will be 
     853     * wrapped in a setjmp so we can assert without causing trouble. 
     854     */ 
     855    if (    VALID_PTR(pVM) 
     856        &&  pVM->pVMR0) 
     857    { 
     858        switch (enmOperation) 
     859        { 
     860            case VMMR0_DO_VMMR0_INIT: 
     861            case VMMR0_DO_VMMR0_TERM: 
     862            { 
     863                VMMR0ENTRYEXARGS Args; 
     864                Args.pVM = pVM; 
     865                Args.enmOperation = enmOperation; 
     866                Args.pReq = pReq; 
     867                Args.u64Arg = u64Arg; 
     868                return vmmR0CallHostSetJmpEx(&pVM->vmm.s.CallHostR0JmpBuf, vmmR0EntryExWrapper, &Args); 
     869            } 
     870 
     871            default: 
     872                break; 
     873        } 
     874    } 
     875    return vmmR0EntryExWorker(pVM, enmOperation, pReq, u64Arg); 
     876} 
     877 
    835878 
    836879 
     
    883926 
    884927 
    885 #ifdef DEBUG_NO_RING0_ASSERTIONS 
    886 /** 
    887  * Check if we really want to hit a breakpoint. 
    888  * Can jump back to ring-3 when the longjmp is armed. 
    889  */ 
    890 DECLEXPORT(bool) RTCALL  RTAssertDoBreakpoint() 
    891 
    892     if (g_pVMAssert) 
    893     { 
    894         int rc = VMMR0CallHost(g_pVMAssert, VMMCALLHOST_VM_R0_HYPER_ASSERTION, 0); 
    895         if (rc == VINF_SUCCESS) 
    896             rc = g_pVMAssert->vmm.s.rcCallHost; 
    897     } 
    898  
    899     return false; 
    900 
    901 #endif /* !DEBUG_NO_RING0_ASSERTIONS */ 
     928 
     929/** 
     930 * Jump back to ring-3 if we're the EMT and the longjmp is armed. 
     931 * 
     932 * @returns true if the breakpoint should be hit, false if it should be ignored. 
     933 * @remark  The RTDECL() makes this a bit difficult to override on windows. Sorry. 
     934 */ 
     935DECLEXPORT(bool) RTCALL RTAssertDoBreakpoint() 
     936
     937    PVM pVM = GVMR0ByEMT(NIL_RTNATIVETHREAD); 
     938    if (pVM) 
     939    { 
     940#ifdef RT_ARCH_X86 
     941        if (pVM->vmm.s.CallHostR0JmpBuf.eip) 
     942#else 
     943        if (pVM->vmm.s.CallHostR0JmpBuf.rip) 
     944#endif 
     945        { 
     946            int rc = VMMR0CallHost(pVM, VMMCALLHOST_VM_R0_HYPER_ASSERTION, 0); 
     947            return RT_FAILURE_NP(rc); 
     948        } 
     949    } 
     950    return true; 
     951
    902952 
    903953 
     
    906956# define LOG_GROUP LOG_GROUP_EM 
    907957 
    908 DECLEXPORT(void) RTCALL RTR0AssertBreakpoint(void *pvVM) 
    909 
    910     if (pvVM) 
    911     { 
    912         PVM pVM = (PVM)pvVM; 
    913         VMMR0CallHost(pVM, VMMCALLHOST_VM_R0_HYPER_ASSERTION, 0); 
    914         /* does not return */ 
    915     } 
    916 
    917  
    918  
     958/** 
     959 * Override this so we can push 
     960 * 
     961 * @param   pszExpr     Expression. Can be NULL. 
     962 * @param   uLine       Location line number. 
     963 * @param   pszFile     Location file name. 
     964 * @param   pszFunction Location function name. 
     965 * @remark  This API exists in HC Ring-3 and GC. 
     966 */ 
    919967DECLEXPORT(void) RTCALL AssertMsg1(const char *pszExpr, unsigned uLine, const char *pszFile, const char *pszFunction) 
    920968{ 
     
    939987    for (size_t i = 0; i < cbChars; i++) 
    940988    { 
    941         LogRel(("%c", pachChars[i])); 
     989        LogRel(("%c", pachChars[i])); /** @todo this isn't any release logging in ring-0 from what I can tell... */ 
    942990        SUPR0Printf("%c", pachChars[i]); 
    943991    } 
     
    9591007    } 
    9601008} 
     1009 
     1010 
  • trunk/src/VBox/VMM/VMMR0/VMMR0A.asm

    r4477 r4979  
    4141; @param    pJmpBuf msc:rcx gcc:rdi x86:[esp+4]     Our jmp_buf. 
    4242; @param    pfn     msc:rdx gcc:rsi x86:[esp+8]     The function to be called when not resuming. 
    43 ; @param    pVM     msc:r8  gcc:rdx x86:[esp+c]     The argument of that function. 
     43; @param    pvUser  msc:r8  gcc:rdx x86:[esp+c]     The argument of that function. 
    4444; 
    4545BEGINPROC vmmR0CallHostSetJmp 
     46GLOBALNAME vmmR0CallHostSetJmpEx 
    4647%ifdef RT_ARCH_X86 
    4748    ; 
     
    135136 %else 
    136137    sub     rsp, 10h 
    137     mov     r8, rdx                     ; pVM (save it like MSC) 
     138    mov     r8, rdx                     ; pvUser (save it like MSC) 
    138139    mov     r11, rsi                    ; pfn 
    139140    mov     rdx, rdi                    ; pJmpBuf 
     
    163164    mov     [rbp - 8], rdx              ; Save it and fix stack alignment (16). 
    164165 %ifdef ASM_CALL64_MSC 
    165     mov     rcx, r8                     ; pVM -> arg0 
     166    mov     rcx, r8                     ; pvUser -> arg0 
    166167 %else 
    167     mov     rdi, r8                     ; pVM -> arg0 
     168    mov     rdi, r8                     ; pvUser -> arg0 
    168169 %endif 
    169170    call    r11 

© 2008 Sun Microsystems, Inc.
ContactPrivacy policy