VirtualBox

Changeset 14515 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Nov 24, 2008 12:33:00 PM (16 years ago)
Author:
vboxsync
Message:

SUPDrv,SUPLib,VMM: Kicked out the dead VBOX_WITH_IDT_PATCHING code.

Location:
trunk/src/VBox
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/Support/Makefile.kmk

    r14015 r14515  
    7676endif
    7777SUPR3_DEFS          = IN_SUP_R3 IN_RT_R3
    78 ifdef VBOX_WITH_IDT_PATCHING
    79  SUPR3_DEFS        += VBOX_WITH_IDT_PATCHING
    80 endif
    8178ifdef VBOX_WITH_SUPSVC
    8279 SUPR3_DEFS        += VBOX_WITH_SUPSVC
     
    166163endif
    167164VBoxDrv_DEFS          = IN_RT_R0 IN_SUP_R0 SUPDRV_WITH_RELEASE_LOGGER
    168 ifdef VBOX_WITH_IDT_PATCHING
    169  VBoxDrv_DEFS        += VBOX_WITH_IDT_PATCHING
    170 endif
    171165VBoxDrv_DEFS.amd64    = RT_WITH_W64_UNWIND_HACK
    172166VBoxDrv_SDKS          = W2K3DDK WINPSDKINCS
     
    220214vboxdrv_NOINST        = true
    221215vboxdrv_DEFS          = KBUILD_MODNAME=KBUILD_STR\(vboxdrv\) KBUILD_BASENAME=KBUILD_STR\(vboxdrv\) MODULE IN_RT_R0 IN_SUP_R0 CONFIG_VBOXDRV_AS_MISC
    222 ifdef VBOX_WITH_IDT_PATCHING
    223 vboxdrv_DEFS         += VBOX_WITH_IDT_PATCHING
    224 endif
    225216ifdef VBOX_LINUX_VERSION_2_4
    226217vboxdrv_DEFS         += EXPORT_SYMTAB
     
    304295VBoxDrv_TEMPLATE      = VBOXR0DRV
    305296VBoxDrv_DEFS          = IN_RT_R0 IN_SUP_R0 SUPDRV_WITH_RELEASE_LOGGER VBOX_SVN_REV=$(VBOX_SVN_REV)
    306 ifdef VBOX_WITH_IDT_PATCHING
    307 VBoxDrv_DEFS         += VBOX_WITH_IDT_PATCHING
    308 endif
    309297VBoxDrv_DEFS         += DEBUG_DARWIN_GIP
    310298VBoxDrv_INCS         := $(PATH_SUB_CURRENT)
     
    378366vboxdrv_TEMPLATE      = VBOXR0DRV
    379367vboxdrv_DEFS          = IN_RT_R0 IN_SUP_R0 SUPDRV_WITH_RELEASE_LOGGER VBOX_SVN_REV=$(VBOX_SVN_REV)
    380 ifdef VBOX_WITH_IDT_PATCHING
    381 vboxdrv_DEFS         += VBOX_WITH_IDT_PATCHING
    382 endif
    383368vboxdrv_INCS         := $(PATH_SUB_CURRENT)
    384369vboxdrv_LIBS          = $(PATH_LIB)/RuntimeR0Drv$(VBOX_SUFF_LIB)
     
    397382vboxdrv_TEMPLATE      = VBOXR0DRV
    398383vboxdrv_DEFS          = IN_RT_R0 IN_SUP_R0 SUPDRV_WITH_RELEASE_LOGGER
    399 ifdef VBOX_WITH_IDT_PATCHING
    400 vboxdrv_DEFS         += VBOX_WITH_IDT_PATCHING
    401 endif
    402384ifdef VBOX_WITH_NETFLT
    403  vboxdrv_DEFS         += VBOX_WITH_NETFLT
     385 vboxdrv_DEFS        += VBOX_WITH_NETFLT
    404386endif
    405387vboxdrv_DEFS         += VBOX_SVN_REV=$(VBOX_SVN_REV)
  • trunk/src/VBox/HostDrivers/Support/SUPDrv.c

    r14512 r14515  
    6565 *      Log     - useful stuff, like failures.
    6666 *      LogFlow - program flow, except the really noisy bits.
    67  *      Log2    - Cleanup and IDTE
     67 *      Log2    - Cleanup.
    6868 *      Log3    - Loader flow noise.
    6969 *      Log4    - Call VMMR0 flow noise.
     
    125125static int      supdrvMemAdd(PSUPDRVMEMREF pMem, PSUPDRVSESSION pSession);
    126126static int      supdrvMemRelease(PSUPDRVSESSION pSession, RTHCUINTPTR uPtr, SUPDRVMEMREFTYPE eType);
    127 #ifdef VBOX_WITH_IDT_PATCHING
    128 static int      supdrvIOCtl_IdtInstall(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPIDTINSTALL pReq);
    129 static PSUPDRVPATCH supdrvIdtPatchOne(PSUPDRVDEVEXT pDevExt, PSUPDRVPATCH pPatch);
    130 static int      supdrvIOCtl_IdtRemoveAll(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession);
    131 static void     supdrvIdtRemoveOne(PSUPDRVDEVEXT pDevExt, PSUPDRVPATCH pPatch);
    132 static void     supdrvIdtWrite(volatile void *pvIdtEntry, const SUPDRVIDTE *pNewIDTEntry);
    133 #endif /* VBOX_WITH_IDT_PATCHING */
    134127static int      supdrvIOCtl_LdrOpen(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPLDROPEN pReq);
    135128static int      supdrvIOCtl_LdrLoad(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPLDRLOAD pReq);
     
    137130static int      supdrvIOCtl_LdrGetSymbol(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPLDRGETSYMBOL pReq);
    138131static int      supdrvIDC_LdrGetSymbol(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPDRVIDCREQGETSYM pReq);
    139 static int      supdrvLdrSetR0EP(PSUPDRVDEVEXT pDevExt, void *pvVMMR0, void *pvVMMR0EntryInt, void *pvVMMR0EntryFast, void *pvVMMR0EntryEx);
    140 static void     supdrvLdrUnsetR0EP(PSUPDRVDEVEXT pDevExt);
     132static int      supdrvLdrSetVMMR0EPs(PSUPDRVDEVEXT pDevExt, void *pvVMMR0, void *pvVMMR0EntryInt, void *pvVMMR0EntryFast, void *pvVMMR0EntryEx);
     133static void     supdrvLdrUnsetVMMR0EPs(PSUPDRVDEVEXT pDevExt);
    141134static int      supdrvLdrAddUsage(PSUPDRVSESSION pSession, PSUPDRVLDRIMAGE pImage);
    142135static void     supdrvLdrFree(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage);
     
    503496void VBOXCALL supdrvDeleteDevExt(PSUPDRVDEVEXT pDevExt)
    504497{
    505 #ifdef VBOX_WITH_IDT_PATCHING
    506     PSUPDRVPATCH        pPatch;
    507 #endif
    508498    PSUPDRVOBJ          pObj;
    509499    PSUPDRVUSAGE        pUsage;
     
    524514     * Free lists.
    525515     */
    526 #ifdef VBOX_WITH_IDT_PATCHING
    527     /* patches */
    528     /** @todo make sure we don't uninstall patches which has been patched by someone else. */
    529     pPatch = pDevExt->pIdtPatchesFree;
    530     pDevExt->pIdtPatchesFree = NULL;
    531     while (pPatch)
    532     {
    533         void *pvFree = pPatch;
    534         pPatch = pPatch->pNext;
    535         RTMemExecFree(pvFree);
    536     }
    537 #endif /* VBOX_WITH_IDT_PATCHING */
    538 
    539516    /* objects. */
    540517    pObj = pDevExt->pObjs;
     
    596573            pSession->u32Cookie         = BIRD_INV;
    597574            /*pSession->pLdrUsage         = NULL;
    598             pSession->pPatchUsage       = NULL;
    599575            pSession->pVM               = NULL;
    600576            pSession->pUsage            = NULL;
     
    672648     */
    673649    RTLogSetDefaultInstanceThread(NULL, (uintptr_t)pSession);
    674 
    675 #ifdef VBOX_WITH_IDT_PATCHING
    676     /*
    677      * Uninstall any IDT patches installed for this session.
    678      */
    679     supdrvIOCtl_IdtRemoveAll(pDevExt, pSession);
    680 #endif
    681650
    682651    /*
     
    11251094
    11261095            /* execute */
    1127 #ifdef VBOX_WITH_IDT_PATCHING
    1128             pReq->Hdr.rc = supdrvIOCtl_IdtInstall(pDevExt, pSession, pReq);
    1129 #else
    11301096            pReq->u.Out.u8Idt = 3;
    11311097            pReq->Hdr.rc = VERR_NOT_SUPPORTED;
    1132 #endif
    11331098            return 0;
    11341099        }
     
    11411106
    11421107            /* execute */
    1143 #ifdef VBOX_WITH_IDT_PATCHING
    1144             pReq->Hdr.rc = supdrvIOCtl_IdtRemoveAll(pDevExt, pSession);
    1145 #else
    11461108            pReq->Hdr.rc = VERR_NOT_SUPPORTED;
    1147 #endif
    11481109            return 0;
    11491110        }
     
    30322993
    30332994
    3034 #ifdef VBOX_WITH_IDT_PATCHING
    3035 /**
    3036  * Install IDT for the current CPU.
    3037  *
    3038  * @returns One of the following IPRT status codes:
    3039  * @retval  VINF_SUCCESS on success.
    3040  * @retval  VERR_IDT_FAILED.
    3041  * @retval  VERR_NO_MEMORY.
    3042  * @param   pDevExt     The device extension.
    3043  * @param   pSession    The session data.
    3044  * @param   pReq        The request.
    3045  */
    3046 static int supdrvIOCtl_IdtInstall(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPIDTINSTALL pReq)
    3047 {
    3048     PSUPDRVPATCHUSAGE   pUsagePre;
    3049     PSUPDRVPATCH        pPatchPre;
    3050     RTIDTR              Idtr;
    3051     PSUPDRVPATCH        pPatch;
    3052     RTSPINLOCKTMP       SpinlockTmp = RTSPINLOCKTMP_INITIALIZER;
    3053     LogFlow(("supdrvIOCtl_IdtInstall\n"));
    3054 
    3055     /*
    3056      * Preallocate entry for this CPU cause we don't wanna do
    3057      * that inside the spinlock!
    3058      */
    3059     pUsagePre = (PSUPDRVPATCHUSAGE)RTMemAlloc(sizeof(*pUsagePre));
    3060     if (!pUsagePre)
    3061         return VERR_NO_MEMORY;
    3062 
    3063     /*
    3064      * Take the spinlock and see what we need to do.
    3065      */
    3066     RTSpinlockAcquireNoInts(pDevExt->Spinlock, &SpinlockTmp);
    3067 
    3068     /* check if we already got a free patch. */
    3069     if (!pDevExt->pIdtPatchesFree)
    3070     {
    3071         /*
    3072          * Allocate a patch - outside the spinlock of course.
    3073          */
    3074         RTSpinlockReleaseNoInts(pDevExt->Spinlock, &SpinlockTmp);
    3075 
    3076         pPatchPre = (PSUPDRVPATCH)RTMemExecAlloc(sizeof(*pPatchPre));
    3077         if (!pPatchPre)
    3078             return VERR_NO_MEMORY;
    3079 
    3080         RTSpinlockAcquireNoInts(pDevExt->Spinlock, &SpinlockTmp);
    3081     }
    3082     else
    3083     {
    3084         pPatchPre = pDevExt->pIdtPatchesFree;
    3085         pDevExt->pIdtPatchesFree = pPatchPre->pNext;
    3086     }
    3087 
    3088     /* look for matching patch entry */
    3089     ASMGetIDTR(&Idtr);
    3090     pPatch = pDevExt->pIdtPatches;
    3091     while (pPatch && pPatch->pvIdt != (void *)Idtr.pIdt)
    3092         pPatch = pPatch->pNext;
    3093 
    3094     if (!pPatch)
    3095     {
    3096         /*
    3097          * Create patch.
    3098          */
    3099         pPatch = supdrvIdtPatchOne(pDevExt, pPatchPre);
    3100         if (pPatch)
    3101             pPatchPre = NULL;           /* mark as used. */
    3102     }
    3103     else
    3104     {
    3105         /*
    3106          * Simply increment patch usage.
    3107          */
    3108         pPatch->cUsage++;
    3109     }
    3110 
    3111     if (pPatch)
    3112     {
    3113         /*
    3114          * Increment and add if need be the session usage record for this patch.
    3115          */
    3116         PSUPDRVPATCHUSAGE   pUsage = pSession->pPatchUsage;
    3117         while (pUsage && pUsage->pPatch != pPatch)
    3118             pUsage = pUsage->pNext;
    3119 
    3120         if (!pUsage)
    3121         {
    3122             /*
    3123              * Add usage record.
    3124              */
    3125             pUsagePre->cUsage     = 1;
    3126             pUsagePre->pPatch     = pPatch;
    3127             pUsagePre->pNext      = pSession->pPatchUsage;
    3128             pSession->pPatchUsage = pUsagePre;
    3129             pUsagePre = NULL;           /* mark as used. */
    3130         }
    3131         else
    3132         {
    3133             /*
    3134              * Increment usage count.
    3135              */
    3136             pUsage->cUsage++;
    3137         }
    3138     }
    3139 
    3140     /* free patch - we accumulate them for paranoid saftly reasons. */
    3141     if (pPatchPre)
    3142     {
    3143         pPatchPre->pNext = pDevExt->pIdtPatchesFree;
    3144         pDevExt->pIdtPatchesFree = pPatchPre;
    3145     }
    3146 
    3147     RTSpinlockReleaseNoInts(pDevExt->Spinlock, &SpinlockTmp);
    3148 
    3149     /*
    3150      * Free unused preallocated buffers.
    3151      */
    3152     if (pUsagePre)
    3153         RTMemFree(pUsagePre);
    3154 
    3155     pReq->u.Out.u8Idt = pDevExt->u8Idt;
    3156 
    3157     return pPatch ? VINF_SUCCESS : VERR_IDT_FAILED;
    3158 }
    3159 
    3160 
    3161 /**
    3162  * This creates a IDT patch entry.
    3163  * If the first patch being installed it'll also determin the IDT entry
    3164  * to use.
    3165  *
    3166  * @returns pPatch on success.
    3167  * @returns NULL on failure.
    3168  * @param   pDevExt     Pointer to globals.
    3169  * @param   pPatch      Patch entry to use.
    3170  *                      This will be linked into SUPDRVDEVEXT::pIdtPatches on
    3171  *                      successful return.
    3172  * @remark  Call must be owning the SUPDRVDEVEXT::Spinlock!
    3173  */
    3174 static PSUPDRVPATCH supdrvIdtPatchOne(PSUPDRVDEVEXT pDevExt, PSUPDRVPATCH pPatch)
    3175 {
    3176     RTIDTR      Idtr;
    3177     PSUPDRVIDTE paIdt;
    3178     LogFlow(("supdrvIOCtl_IdtPatchOne: pPatch=%p\n", pPatch));
    3179 
    3180     /*
    3181      * Get IDT.
    3182      */
    3183     ASMGetIDTR(&Idtr);
    3184     paIdt = (PSUPDRVIDTE)Idtr.pIdt;
    3185     /*
    3186      * Recent Linux kernels can be configured to 1G user /3G kernel.
    3187      */
    3188     if ((uintptr_t)paIdt < 0x40000000)
    3189     {
    3190         AssertMsgFailed(("bad paIdt=%p\n", paIdt));
    3191         return NULL;
    3192     }
    3193 
    3194     if (!pDevExt->u8Idt)
    3195     {
    3196         /*
    3197          * Test out the alternatives.
    3198          *
    3199          * At the moment we do not support chaining thus we ASSUME that one of
    3200          * these 48 entries is unused (which is not a problem on Win32 and
    3201          * Linux to my knowledge).
    3202          */
    3203         /** @todo we MUST change this detection to try grab an entry which is NOT in use. This can be
    3204          * combined with gathering info about which guest system call gates we can hook up directly. */
    3205         unsigned    i;
    3206         uint8_t     u8Idt = 0;
    3207         static uint8_t au8Ints[] =
    3208         {
    3209 #ifdef RT_OS_WINDOWS   /* We don't use 0xef and above because they are system stuff on linux (ef is IPI,
    3210                   * local apic timer, or some other frequently fireing thing). */
    3211             0xef, 0xee, 0xed, 0xec,
    3212 #endif
    3213             0xeb, 0xea, 0xe9, 0xe8,
    3214             0xdf, 0xde, 0xdd, 0xdc,
    3215             0x7b, 0x7a, 0x79, 0x78,
    3216             0xbf, 0xbe, 0xbd, 0xbc,
    3217         };
    3218 #if defined(RT_ARCH_AMD64) && defined(DEBUG)
    3219         static int  s_iWobble = 0;
    3220         unsigned    iMax = !(s_iWobble++ % 2) ? 0x80 : 0x100;
    3221         Log2(("IDT: Idtr=%p:%#x\n", (void *)Idtr.pIdt, (unsigned)Idtr.cbIdt));
    3222         for (i = iMax - 0x80; i*16+15 < Idtr.cbIdt && i < iMax; i++)
    3223         {
    3224             Log2(("%#x: %04x:%08x%04x%04x P=%d DPL=%d IST=%d Type1=%#x u32Reserved=%#x u5Reserved=%#x\n",
    3225                   i, paIdt[i].u16SegSel, paIdt[i].u32OffsetTop, paIdt[i].u16OffsetHigh, paIdt[i].u16OffsetLow,
    3226                   paIdt[i].u1Present, paIdt[i].u2DPL, paIdt[i].u3IST, paIdt[i].u5Type2,
    3227                   paIdt[i].u32Reserved, paIdt[i].u5Reserved));
    3228         }
    3229 #endif
    3230         /* look for entries which are not present or otherwise unused. */
    3231         for (i = 0; i < sizeof(au8Ints) / sizeof(au8Ints[0]); i++)
    3232         {
    3233             u8Idt = au8Ints[i];
    3234             if (    u8Idt * sizeof(SUPDRVIDTE) < Idtr.cbIdt
    3235                 &&  (   !paIdt[u8Idt].u1Present
    3236                      || paIdt[u8Idt].u5Type2 == 0))
    3237                 break;
    3238             u8Idt = 0;
    3239         }
    3240         if (!u8Idt)
    3241         {
    3242             /* try again, look for a compatible entry .*/
    3243             for (i = 0; i < sizeof(au8Ints) / sizeof(au8Ints[0]); i++)
    3244             {
    3245                 u8Idt = au8Ints[i];
    3246                 if (    u8Idt * sizeof(SUPDRVIDTE) < Idtr.cbIdt
    3247                     &&  paIdt[u8Idt].u1Present
    3248                     &&  paIdt[u8Idt].u5Type2 == SUPDRV_IDTE_TYPE2_INTERRUPT_GATE
    3249                     &&  !(paIdt[u8Idt].u16SegSel & 3))
    3250                     break;
    3251                 u8Idt = 0;
    3252             }
    3253             if (!u8Idt)
    3254             {
    3255                 Log(("Failed to find appropirate IDT entry!!\n"));
    3256                 return NULL;
    3257             }
    3258         }
    3259         pDevExt->u8Idt = u8Idt;
    3260         LogFlow(("supdrvIOCtl_IdtPatchOne: u8Idt=%x\n", u8Idt));
    3261     }
    3262 
    3263     /*
    3264      * Prepare the patch
    3265      */
    3266     memset(pPatch, 0, sizeof(*pPatch));
    3267     pPatch->pvIdt                       = paIdt;
    3268     pPatch->cUsage                      = 1;
    3269     pPatch->pIdtEntry                   = &paIdt[pDevExt->u8Idt];
    3270     pPatch->SavedIdt                    = paIdt[pDevExt->u8Idt];
    3271     pPatch->ChangedIdt.u16OffsetLow     = (uint32_t)((uintptr_t)&pPatch->auCode[0] & 0xffff);
    3272     pPatch->ChangedIdt.u16OffsetHigh    = (uint32_t)((uintptr_t)&pPatch->auCode[0] >> 16);
    3273 #ifdef RT_ARCH_AMD64
    3274     pPatch->ChangedIdt.u32OffsetTop     = (uint32_t)((uintptr_t)&pPatch->auCode[0] >> 32);
    3275 #endif
    3276     pPatch->ChangedIdt.u16SegSel        = ASMGetCS();
    3277 #ifdef RT_ARCH_AMD64
    3278     pPatch->ChangedIdt.u3IST            = 0;
    3279     pPatch->ChangedIdt.u5Reserved       = 0;
    3280 #else /* x86 */
    3281     pPatch->ChangedIdt.u5Reserved       = 0;
    3282     pPatch->ChangedIdt.u3Type1          = 0;
    3283 #endif /* x86 */
    3284     pPatch->ChangedIdt.u5Type2          = SUPDRV_IDTE_TYPE2_INTERRUPT_GATE;
    3285     pPatch->ChangedIdt.u2DPL            = 3;
    3286     pPatch->ChangedIdt.u1Present        = 1;
    3287 
    3288     /*
    3289      * Generate the patch code.
    3290      */
    3291   {
    3292 #ifdef RT_ARCH_AMD64
    3293     union
    3294     {
    3295         uint8_t    *pb;
    3296         uint32_t   *pu32;
    3297         uint64_t   *pu64;
    3298     } u, uFixJmp, uFixCall, uNotNested;
    3299     u.pb = &pPatch->auCode[0];
    3300 
    3301     /* check the cookie */
    3302     *u.pb++ = 0x3d;                     //  cmp     eax, GLOBALCOOKIE
    3303     *u.pu32++ = pDevExt->u32Cookie;
    3304 
    3305     *u.pb++ = 0x74;                     //  jz      @VBoxCall
    3306     *u.pb++ = 2;
    3307 
    3308     /* jump to forwarder code. */
    3309     *u.pb++ = 0xeb;
    3310     uFixJmp = u;
    3311     *u.pb++ = 0xfe;
    3312 
    3313                                         //  @VBoxCall:
    3314     *u.pb++ = 0x0f;                     //  swapgs
    3315     *u.pb++ = 0x01;
    3316     *u.pb++ = 0xf8;
    3317 
    3318     /*
    3319      * Call VMMR0Entry
    3320      *      We don't have to push the arguments here, but we have top
    3321      *      reserve some stack space for the interrupt forwarding.
    3322      */
    3323 # ifdef RT_OS_WINDOWS
    3324     *u.pb++ = 0x50;                     //  push    rax                             ; alignment filler.
    3325     *u.pb++ = 0x41;                     //  push    r8                              ; uArg
    3326     *u.pb++ = 0x50;
    3327     *u.pb++ = 0x52;                     //  push    rdx                             ; uOperation
    3328     *u.pb++ = 0x51;                     //  push    rcx                             ; pVM
    3329 # else
    3330     *u.pb++ = 0x51;                     //  push    rcx                             ; alignment filler.
    3331     *u.pb++ = 0x52;                     //  push    rdx                             ; uArg
    3332     *u.pb++ = 0x56;                     //  push    rsi                             ; uOperation
    3333     *u.pb++ = 0x57;                     //  push    rdi                             ; pVM
    3334 # endif
    3335 
    3336     *u.pb++ = 0xff;                     //  call    qword [pfnVMMR0EntryInt wrt rip]
    3337     *u.pb++ = 0x15;
    3338     uFixCall = u;
    3339     *u.pu32++ = 0;
    3340 
    3341     *u.pb++ = 0x48;                     //  add     rsp, 20h                        ; remove call frame.
    3342     *u.pb++ = 0x81;
    3343     *u.pb++ = 0xc4;
    3344     *u.pu32++ = 0x20;
    3345 
    3346     *u.pb++ = 0x0f;                     // swapgs
    3347     *u.pb++ = 0x01;
    3348     *u.pb++ = 0xf8;
    3349 
    3350     /* Return to R3. */
    3351     uNotNested = u;
    3352     *u.pb++ = 0x48;                     //  iretq
    3353     *u.pb++ = 0xcf;
    3354 
    3355     while ((uintptr_t)u.pb & 0x7)       //  align 8
    3356         *u.pb++ = 0xcc;
    3357 
    3358     /* Pointer to the VMMR0Entry. */    //  pfnVMMR0EntryInt dq StubVMMR0Entry
    3359     *uFixCall.pu32 = (uint32_t)(u.pb - uFixCall.pb - 4);                uFixCall.pb = NULL;
    3360     pPatch->offVMMR0EntryFixup = (uint16_t)(u.pb - &pPatch->auCode[0]);
    3361     *u.pu64++ = pDevExt->pvVMMR0 ? (uint64_t)pDevExt->pfnVMMR0EntryInt : (uint64_t)u.pb + 8;
    3362 
    3363     /* stub entry. */                   //  StubVMMR0Entry:
    3364     pPatch->offStub = (uint16_t)(u.pb - &pPatch->auCode[0]);
    3365     *u.pb++ = 0x33;                     //  xor     eax, eax
    3366     *u.pb++ = 0xc0;
    3367 
    3368     *u.pb++ = 0x48;                     //  dec     rax
    3369     *u.pb++ = 0xff;
    3370     *u.pb++ = 0xc8;
    3371 
    3372     *u.pb++ = 0xc3;                     //  ret
    3373 
    3374     /* forward to the original handler using a retf. */
    3375     *uFixJmp.pb = (uint8_t)(u.pb - uFixJmp.pb - 1);                     uFixJmp.pb = NULL;
    3376 
    3377     *u.pb++ = 0x68;                     //  push    <target cs>
    3378     *u.pu32++ = !pPatch->SavedIdt.u5Type2 ? ASMGetCS() : pPatch->SavedIdt.u16SegSel;
    3379 
    3380     *u.pb++ = 0x68;                     //  push    <low target rip>
    3381     *u.pu32++ = !pPatch->SavedIdt.u5Type2
    3382               ? (uint32_t)(uintptr_t)uNotNested.pb
    3383               : (uint32_t)pPatch->SavedIdt.u16OffsetLow
    3384               | (uint32_t)pPatch->SavedIdt.u16OffsetHigh << 16;
    3385 
    3386     *u.pb++ = 0xc7;                     //  mov     dword [rsp + 4], <high target rip>
    3387     *u.pb++ = 0x44;
    3388     *u.pb++ = 0x24;
    3389     *u.pb++ = 0x04;
    3390     *u.pu32++ = !pPatch->SavedIdt.u5Type2
    3391               ? (uint32_t)((uint64_t)uNotNested.pb >> 32)
    3392               : pPatch->SavedIdt.u32OffsetTop;
    3393 
    3394     *u.pb++ = 0x48;                     //  retf        ; does this require prefix?
    3395     *u.pb++ = 0xcb;
    3396 
    3397 #else /* RT_ARCH_X86 */
    3398 
    3399     union
    3400     {
    3401         uint8_t    *pb;
    3402         uint16_t   *pu16;
    3403         uint32_t   *pu32;
    3404     } u, uFixJmpNotNested, uFixJmp, uFixCall, uNotNested;
    3405     u.pb = &pPatch->auCode[0];
    3406 
    3407     /* check the cookie */
    3408     *u.pb++ = 0x81;                     //  cmp     esi, GLOBALCOOKIE
    3409     *u.pb++ = 0xfe;
    3410     *u.pu32++ = pDevExt->u32Cookie;
    3411 
    3412     *u.pb++ = 0x74;                     //  jz      VBoxCall
    3413     uFixJmp = u;
    3414     *u.pb++ = 0;
    3415 
    3416     /* jump (far) to the original handler / not-nested-stub. */
    3417     *u.pb++ = 0xea;                     //  jmp far NotNested
    3418     uFixJmpNotNested = u;
    3419     *u.pu32++ = 0;
    3420     *u.pu16++ = 0;
    3421 
    3422     /* save selector registers. */      // VBoxCall:
    3423     *uFixJmp.pb = (uint8_t)(u.pb - uFixJmp.pb - 1);
    3424     *u.pb++ = 0x0f;                     //  push    fs
    3425     *u.pb++ = 0xa0;
    3426 
    3427     *u.pb++ = 0x1e;                     //  push    ds
    3428 
    3429     *u.pb++ = 0x06;                     //  push    es
    3430 
    3431     /* call frame */
    3432     *u.pb++ = 0x51;                     //  push    ecx
    3433 
    3434     *u.pb++ = 0x52;                     //  push    edx
    3435 
    3436     *u.pb++ = 0x50;                     //  push    eax
    3437 
    3438     /* load ds, es and perhaps fs before call. */
    3439     *u.pb++ = 0xb8;                     //  mov     eax, KernelDS
    3440     *u.pu32++ = ASMGetDS();
    3441 
    3442     *u.pb++ = 0x8e;                     //  mov     ds, eax
    3443     *u.pb++ = 0xd8;
    3444 
    3445     *u.pb++ = 0x8e;                     //  mov     es, eax
    3446     *u.pb++ = 0xc0;
    3447 
    3448 #ifdef RT_OS_WINDOWS
    3449     *u.pb++ = 0xb8;                     //  mov     eax, KernelFS
    3450     *u.pu32++ = ASMGetFS();
    3451 
    3452     *u.pb++ = 0x8e;                     //  mov     fs, eax
    3453     *u.pb++ = 0xe0;
    3454 #endif
    3455 
    3456     /* do the call. */
    3457     *u.pb++ = 0xe8;                     //  call    _VMMR0Entry / StubVMMR0Entry
    3458     uFixCall = u;
    3459     pPatch->offVMMR0EntryFixup = (uint16_t)(u.pb - &pPatch->auCode[0]);
    3460     *u.pu32++ = 0xfffffffb;
    3461 
    3462     *u.pb++ = 0x83;                     //  add     esp, 0ch   ; cdecl
    3463     *u.pb++ = 0xc4;
    3464     *u.pb++ = 0x0c;
    3465 
    3466     /* restore selector registers. */
    3467     *u.pb++ = 0x07;                     //  pop     es
    3468                                         //
    3469     *u.pb++ = 0x1f;                     //  pop     ds
    3470 
    3471     *u.pb++ = 0x0f;                     //  pop     fs
    3472     *u.pb++ = 0xa1;
    3473 
    3474     uNotNested = u;                     // NotNested:
    3475     *u.pb++ = 0xcf;                     //  iretd
    3476 
    3477     /* the stub VMMR0Entry. */          // StubVMMR0Entry:
    3478     pPatch->offStub = (uint16_t)(u.pb - &pPatch->auCode[0]);
    3479     *u.pb++ = 0x33;                     //  xor     eax, eax
    3480     *u.pb++ = 0xc0;
    3481 
    3482     *u.pb++ = 0x48;                     //  dec     eax
    3483 
    3484     *u.pb++ = 0xc3;                     //  ret
    3485 
    3486     /* Fixup the VMMR0Entry call. */
    3487     if (pDevExt->pvVMMR0)
    3488         *uFixCall.pu32 = (uint32_t)pDevExt->pfnVMMR0EntryInt - (uint32_t)(uFixCall.pu32 + 1);
    3489     else
    3490         *uFixCall.pu32 = (uint32_t)&pPatch->auCode[pPatch->offStub] - (uint32_t)(uFixCall.pu32 + 1);
    3491 
    3492     /* Fixup the forward / nested far jump. */
    3493     if (!pPatch->SavedIdt.u5Type2)
    3494     {
    3495         *uFixJmpNotNested.pu32++ = (uint32_t)uNotNested.pb;
    3496         *uFixJmpNotNested.pu16++ = ASMGetCS();
    3497     }
    3498     else
    3499     {
    3500         *uFixJmpNotNested.pu32++ = ((uint32_t)pPatch->SavedIdt.u16OffsetHigh << 16) | pPatch->SavedIdt.u16OffsetLow;
    3501         *uFixJmpNotNested.pu16++ = pPatch->SavedIdt.u16SegSel;
    3502     }
    3503 #endif /* RT_ARCH_X86 */
    3504     Assert(u.pb <= &pPatch->auCode[sizeof(pPatch->auCode)]);
    3505 #if 0
    3506     /* dump the patch code */
    3507     Log2(("patch code: %p\n", &pPatch->auCode[0]));
    3508     for (uFixCall.pb = &pPatch->auCode[0]; uFixCall.pb < u.pb; uFixCall.pb++)
    3509         Log2(("0x%02x,\n", *uFixCall.pb));
    3510 #endif
    3511   }
    3512 
    3513     /*
    3514      * Install the patch.
    3515      */
    3516     supdrvIdtWrite(pPatch->pIdtEntry, &pPatch->ChangedIdt);
    3517     AssertMsg(!memcmp((void *)pPatch->pIdtEntry, &pPatch->ChangedIdt, sizeof(pPatch->ChangedIdt)), ("The stupid change code didn't work!!!!!\n"));
    3518 
    3519     /*
    3520      * Link in the patch.
    3521      */
    3522     pPatch->pNext = pDevExt->pIdtPatches;
    3523     pDevExt->pIdtPatches = pPatch;
    3524 
    3525     return pPatch;
    3526 }
    3527 
    3528 
    3529 /**
    3530  * Removes the sessions IDT references.
    3531  * This will uninstall our IDT patch if we left unreferenced.
    3532  *
    3533  * @returns VINF_SUCCESS.
    3534  * @param   pDevExt     Device globals.
    3535  * @param   pSession    Session data.
    3536  */
    3537 static int supdrvIOCtl_IdtRemoveAll(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession)
    3538 {
    3539     PSUPDRVPATCHUSAGE   pUsage;
    3540     RTSPINLOCKTMP       SpinlockTmp = RTSPINLOCKTMP_INITIALIZER;
    3541     LogFlow(("supdrvIOCtl_IdtRemoveAll: pSession=%p\n", pSession));
    3542 
    3543     /*
    3544      * Take the spinlock.
    3545      */
    3546     RTSpinlockAcquireNoInts(pDevExt->Spinlock, &SpinlockTmp);
    3547 
    3548     /*
    3549      * Walk usage list, removing patches as their usage count reaches zero.
    3550      */
    3551     pUsage = pSession->pPatchUsage;
    3552     while (pUsage)
    3553     {
    3554         if (pUsage->pPatch->cUsage <= pUsage->cUsage)
    3555             supdrvIdtRemoveOne(pDevExt, pUsage->pPatch);
    3556         else
    3557             pUsage->pPatch->cUsage -= pUsage->cUsage;
    3558 
    3559         /* next */
    3560         pUsage = pUsage->pNext;
    3561     }
    3562 
    3563     /*
    3564      * Empty the usage chain and we're done inside the spinlock.
    3565      */
    3566     pUsage = pSession->pPatchUsage;
    3567     pSession->pPatchUsage = NULL;
    3568 
    3569     RTSpinlockReleaseNoInts(pDevExt->Spinlock, &SpinlockTmp);
    3570 
    3571     /*
    3572      * Free usage entries.
    3573      */
    3574     while (pUsage)
    3575     {
    3576         void *pvToFree = pUsage;
    3577         pUsage->cUsage = 0;
    3578         pUsage->pPatch = NULL;
    3579         pUsage = pUsage->pNext;
    3580         RTMemFree(pvToFree);
    3581     }
    3582 
    3583     return VINF_SUCCESS;
    3584 }
    3585 
    3586 
    3587 /**
    3588  * Remove one patch.
    3589  *
    3590  * Worker for supdrvIOCtl_IdtRemoveAll.
    3591  *
    3592  * @param   pDevExt     Device globals.
    3593  * @param   pPatch      Patch entry to remove.
    3594  * @remark  Caller must own SUPDRVDEVEXT::Spinlock!
    3595  */
    3596 static void supdrvIdtRemoveOne(PSUPDRVDEVEXT pDevExt, PSUPDRVPATCH pPatch)
    3597 {
    3598     LogFlow(("supdrvIdtRemoveOne: pPatch=%p\n", pPatch));
    3599 
    3600     pPatch->cUsage = 0;
    3601 
    3602     /*
    3603      * If the IDT entry was changed it have to kick around for ever!
    3604      * This will be attempted freed again, perhaps next time we'll succeed :-)
    3605      */
    3606     if (memcmp((void *)pPatch->pIdtEntry, &pPatch->ChangedIdt, sizeof(pPatch->ChangedIdt)))
    3607     {
    3608         AssertMsgFailed(("The hijacked IDT entry has CHANGED!!!\n"));
    3609         return;
    3610     }
    3611 
    3612     /*
    3613      * Unlink it.
    3614      */
    3615     if (pDevExt->pIdtPatches != pPatch)
    3616     {
    3617         PSUPDRVPATCH pPatchPrev = pDevExt->pIdtPatches;
    3618         while (pPatchPrev)
    3619         {
    3620             if (pPatchPrev->pNext == pPatch)
    3621             {
    3622                 pPatchPrev->pNext = pPatch->pNext;
    3623                 break;
    3624             }
    3625             pPatchPrev = pPatchPrev->pNext;
    3626         }
    3627         Assert(!pPatchPrev);
    3628     }
    3629     else
    3630         pDevExt->pIdtPatches = pPatch->pNext;
    3631     pPatch->pNext = NULL;
    3632 
    3633 
    3634     /*
    3635      * Verify and restore the IDT.
    3636      */
    3637     AssertMsg(!memcmp((void *)pPatch->pIdtEntry, &pPatch->ChangedIdt, sizeof(pPatch->ChangedIdt)), ("The hijacked IDT entry has CHANGED!!!\n"));
    3638     supdrvIdtWrite(pPatch->pIdtEntry, &pPatch->SavedIdt);
    3639     AssertMsg(!memcmp((void *)pPatch->pIdtEntry, &pPatch->SavedIdt,   sizeof(pPatch->SavedIdt)),   ("The hijacked IDT entry has CHANGED!!!\n"));
    3640 
    3641     /*
    3642      * Put it in the free list.
    3643      * (This free list stuff is to calm my paranoia.)
    3644      */
    3645     pPatch->pvIdt     = NULL;
    3646     pPatch->pIdtEntry = NULL;
    3647 
    3648     pPatch->pNext = pDevExt->pIdtPatchesFree;
    3649     pDevExt->pIdtPatchesFree = pPatch;
    3650 }
    3651 
    3652 
    3653 /**
    3654  * Write to an IDT entry.
    3655  *
    3656  * @param   pvIdtEntry      Where to write.
    3657  * @param   pNewIDTEntry    What to write.
    3658  */
    3659 static void supdrvIdtWrite(volatile void *pvIdtEntry, const SUPDRVIDTE *pNewIDTEntry)
    3660 {
    3661     RTR0UINTREG   uCR0;
    3662     RTR0UINTREG   uFlags;
    3663 
    3664     /*
    3665      * On SMP machines (P4 hyperthreading included) we must preform a
    3666      * 64-bit locked write when updating the IDT entry.
    3667      *
    3668      * The F00F bugfix for linux (and probably other OSes) causes
    3669      * the IDT to be pointing to an readonly mapping. We get around that
    3670      * by temporarily turning of WP. Since we're inside a spinlock at this
    3671      * point, interrupts are disabled and there isn't any way the WP bit
    3672      * flipping can cause any trouble.
    3673      */
    3674 
    3675     /* Save & Clear interrupt flag; Save & clear WP. */
    3676     uFlags = ASMGetFlags();
    3677     ASMSetFlags(uFlags & ~(RTR0UINTREG)(1 << 9)); /*X86_EFL_IF*/
    3678     Assert(!(ASMGetFlags() & (1 << 9)));
    3679     uCR0 = ASMGetCR0();
    3680     ASMSetCR0(uCR0 & ~(RTR0UINTREG)(1 << 16));    /*X86_CR0_WP*/
    3681 
    3682     /* Update IDT Entry */
    3683 #ifdef RT_ARCH_AMD64
    3684     ASMAtomicXchgU128((volatile uint128_t *)pvIdtEntry, *(uint128_t *)(uintptr_t)pNewIDTEntry);
    3685 #else
    3686     ASMAtomicXchgU64((volatile uint64_t *)pvIdtEntry, *(uint64_t *)(uintptr_t)pNewIDTEntry);
    3687 #endif
    3688 
    3689     /* Restore CR0 & Flags */
    3690     ASMSetCR0(uCR0);
    3691     ASMSetFlags(uFlags);
    3692 }
    3693 #endif /* VBOX_WITH_IDT_PATCHING */
    3694 
    3695 
    36962995/**
    36972996 * Opens an image. If it's the first time it's opened the call must upload
     
    39193218            break;
    39203219        case SUPLDRLOADEP_VMMR0:
    3921             rc = supdrvLdrSetR0EP(pDevExt, pReq->u.In.EP.VMMR0.pvVMMR0, pReq->u.In.EP.VMMR0.pvVMMR0EntryInt,
    3922                                   pReq->u.In.EP.VMMR0.pvVMMR0EntryFast, pReq->u.In.EP.VMMR0.pvVMMR0EntryEx);
     3220            rc = supdrvLdrSetVMMR0EPs(pDevExt, pReq->u.In.EP.VMMR0.pvVMMR0, pReq->u.In.EP.VMMR0.pvVMMR0EntryInt,
     3221                                      pReq->u.In.EP.VMMR0.pvVMMR0EntryFast, pReq->u.In.EP.VMMR0.pvVMMR0EntryEx);
    39233222            break;
    39243223        case SUPLDRLOADEP_SERVICE:
     
    39413240#endif
    39423241        if (rc && pDevExt->pvVMMR0 == pImage->pvImage)
    3943             supdrvLdrUnsetR0EP(pDevExt);
     3242            supdrvLdrUnsetVMMR0EPs(pDevExt);
    39443243    }
    39453244
     
    42163515
    42173516/**
    4218  * Updates the IDT patches to point to the specified VMM R0 entry
    4219  * point (i.e. VMMR0Enter()).
     3517 * Updates the VMMR0 entry point pointers.
    42203518 *
    42213519 * @returns IPRT status code.
     
    42283526 * @remark  Caller must own the loader mutex.
    42293527 */
    4230 static int supdrvLdrSetR0EP(PSUPDRVDEVEXT pDevExt, void *pvVMMR0, void *pvVMMR0EntryInt, void *pvVMMR0EntryFast, void *pvVMMR0EntryEx)
     3528static int supdrvLdrSetVMMR0EPs(PSUPDRVDEVEXT pDevExt, void *pvVMMR0, void *pvVMMR0EntryInt, void *pvVMMR0EntryFast, void *pvVMMR0EntryEx)
    42313529{
    42323530    int rc = VINF_SUCCESS;
     
    42393537    if (!pDevExt->pvVMMR0)
    42403538    {
    4241 #ifdef VBOX_WITH_IDT_PATCHING
    4242         PSUPDRVPATCH pPatch;
    4243 #endif
    4244 
    4245         /*
    4246          * Set it and update IDT patch code.
    4247          */
    42483539        pDevExt->pvVMMR0            = pvVMMR0;
    42493540        pDevExt->pfnVMMR0EntryInt   = pvVMMR0EntryInt;
    42503541        pDevExt->pfnVMMR0EntryFast  = pvVMMR0EntryFast;
    42513542        pDevExt->pfnVMMR0EntryEx    = pvVMMR0EntryEx;
    4252 #ifdef VBOX_WITH_IDT_PATCHING
    4253         for (pPatch = pDevExt->pIdtPatches; pPatch; pPatch = pPatch->pNext)
    4254         {
    4255 # ifdef RT_ARCH_AMD64
    4256             ASMAtomicXchgU64((volatile uint64_t *)&pPatch->auCode[pPatch->offVMMR0EntryFixup], (uint64_t)pvVMMR0);
    4257 # else /* RT_ARCH_X86 */
    4258             ASMAtomicXchgU32((volatile uint32_t *)&pPatch->auCode[pPatch->offVMMR0EntryFixup],
    4259                              (uint32_t)pvVMMR0 - (uint32_t)&pPatch->auCode[pPatch->offVMMR0EntryFixup + 4]);
    4260 # endif
    4261         }
    4262 #endif /* VBOX_WITH_IDT_PATCHING */
    42633543    }
    42643544    else
     
    42813561
    42823562/**
    4283  * Unsets the R0 entry point installed by supdrvLdrSetR0EP.
     3563 * Unsets the VMMR0 entry point installed by supdrvLdrSetR0EP.
    42843564 *
    42853565 * @param   pDevExt     Device globals.
    42863566 */
    4287 static void supdrvLdrUnsetR0EP(PSUPDRVDEVEXT pDevExt)
    4288 {
    4289 #ifdef VBOX_WITH_IDT_PATCHING
    4290     PSUPDRVPATCH pPatch;
    4291 #endif
    4292 
     3567static void supdrvLdrUnsetVMMR0EPs(PSUPDRVDEVEXT pDevExt)
     3568{
    42933569    pDevExt->pvVMMR0            = NULL;
    42943570    pDevExt->pfnVMMR0EntryInt   = NULL;
    42953571    pDevExt->pfnVMMR0EntryFast  = NULL;
    42963572    pDevExt->pfnVMMR0EntryEx    = NULL;
    4297 
    4298 #ifdef VBOX_WITH_IDT_PATCHING
    4299     for (pPatch = pDevExt->pIdtPatches; pPatch; pPatch = pPatch->pNext)
    4300     {
    4301 # ifdef RT_ARCH_AMD64
    4302         ASMAtomicXchgU64((volatile uint64_t *)&pPatch->auCode[pPatch->offVMMR0EntryFixup],
    4303                          (uint64_t)&pPatch->auCode[pPatch->offStub]);
    4304 # else /* RT_ARCH_X86 */
    4305         ASMAtomicXchgU32((volatile uint32_t *)&pPatch->auCode[pPatch->offVMMR0EntryFixup],
    4306                          (uint32_t)&pPatch->auCode[pPatch->offStub] - (uint32_t)&pPatch->auCode[pPatch->offVMMR0EntryFixup + 4]);
    4307 # endif
    4308     }
    4309 #endif /* VBOX_WITH_IDT_PATCHING */
    43103573}
    43113574
     
    43823645        pDevExt->pLdrImages = pImage->pNext;
    43833646
    4384     /* check if this is VMMR0.r0 and fix the Idt patches if it is. */
     3647    /* check if this is VMMR0.r0 unset its entry point pointers. */
    43853648    if (pDevExt->pvVMMR0 == pImage->pvImage)
    4386         supdrvLdrUnsetR0EP(pDevExt);
     3649        supdrvLdrUnsetVMMR0EPs(pDevExt);
    43873650
    43883651    /* check for objects with destructors in this image. (Shouldn't happen.) */
  • trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h

    r14332 r14515  
    298298typedef struct SUPDRVDEVEXT *PSUPDRVDEVEXT;
    299299
    300 #ifdef VBOX_WITH_IDT_PATCHING
    301 
    302 /**
    303  * An IDT Entry.
    304  */
    305 typedef struct SUPDRVIDTE
    306 {
    307     /** Low offset word. */
    308     uint32_t    u16OffsetLow : 16;
    309     /** Segment Selector. */
    310     uint32_t    u16SegSel : 16;
    311 #ifdef RT_ARCH_AMD64
    312     /** Interrupt Stack Table index. */
    313     uint32_t    u3IST : 3;
    314     /** Reserved, ignored. */
    315     uint32_t    u5Reserved : 5;
    316 #else
    317     /** Reserved. */
    318     uint32_t    u5Reserved : 5;
    319     /** IDT Type part one (not used for task gate). */
    320     uint32_t    u3Type1 : 3;
    321 #endif
    322     /** IDT Type part two. */
    323     uint32_t    u5Type2 : 5;
    324     /** Descriptor Privilege level. */
    325     uint32_t    u2DPL : 2;
    326     /** Present flag. */
    327     uint32_t    u1Present : 1;
    328     /** High offset word. */
    329     uint32_t    u16OffsetHigh : 16;
    330 #ifdef RT_ARCH_AMD64
    331     /** The upper top part of the address. */
    332     uint32_t    u32OffsetTop;
    333     /** Reserved dword for qword (aligning the struct), ignored. */
    334     uint32_t    u32Reserved;
    335 #endif
    336 } SUPDRVIDTE, *PSUPDRVIDTE;
    337 
    338 /** The u5Type2 value for an interrupt gate. */
    339 #define SUPDRV_IDTE_TYPE2_INTERRUPT_GATE    0x0e
    340 
    341 
    342 /**
    343  * Patch code.
    344  */
    345 typedef struct SUPDRVPATCH
    346 {
    347 #define SUPDRV_PATCH_CODE_SIZE  0x50
    348     /** Patch code. */
    349     uint8_t                         auCode[SUPDRV_PATCH_CODE_SIZE];
    350     /** Changed IDT entry (for parnoid UnpatchIdt()). */
    351     SUPDRVIDTE                      ChangedIdt;
    352     /** Saved IDT entry. */
    353     SUPDRVIDTE                      SavedIdt;
    354     /** Pointer to the IDT.
    355      * We ASSUME the IDT is not re(al)located after bootup and use this as key
    356      * for the patches rather than processor number. This prevents some
    357      * stupid nesting stuff from happening in case of processors sharing the
    358      * IDT.
    359      * We're fucked if the processors have different physical mapping for
    360      * the(se) page(s), but we'll find that out soon enough in VBOX_STRICT mode.
    361      */
    362     void                           *pvIdt;
    363     /** Pointer to the IDT entry. */
    364     SUPDRVIDTE volatile            *pIdtEntry;
    365     /** Usage counter. */
    366     uint32_t volatile               cUsage;
    367     /** The offset into auCode of the VMMR0Entry fixup. */
    368     uint16_t                        offVMMR0EntryFixup;
    369     /** The offset into auCode of the stub function. */
    370     uint16_t                        offStub;
    371     /** Pointer to the next patch. */
    372     struct SUPDRVPATCH * volatile pNext;
    373 } SUPDRVPATCH, *PSUPDRVPATCH;
    374 
    375 /**
    376  * Usage record for a patch.
    377  */
    378 typedef struct SUPDRVPATCHUSAGE
    379 {
    380     /** Next in the chain. */
    381     struct SUPDRVPATCHUSAGE * volatile pNext;
    382     /** The patch this usage applies to. */
    383     PSUPDRVPATCH                    pPatch;
    384     /** Usage count. */
    385     uint32_t volatile               cUsage;
    386 } SUPDRVPATCHUSAGE, *PSUPDRVPATCHUSAGE;
    387 
    388 #endif /* VBOX_WITH_IDT_PATCHING */
    389 
    390300
    391301/**
     
    566476    /** Load usage records. (protected by SUPDRVDEVEXT::mtxLdr) */
    567477    PSUPDRVLDRUSAGE volatile        pLdrUsage;
    568 #ifdef VBOX_WITH_IDT_PATCHING
    569     /** Patch usage records. (protected by SUPDRVDEVEXT::SpinLock) */
    570     PSUPDRVPATCHUSAGE volatile      pPatchUsage;
    571 #endif
    572478    /** The VM associated with the session. */
    573479    PVM                             pVM;
     
    619525     * usage counting and destruction of the IDT entry override and objects. */
    620526    RTSPINLOCK                      Spinlock;
    621 
    622 #ifdef VBOX_WITH_IDT_PATCHING
    623     /** List of patches. */
    624     PSUPDRVPATCH volatile           pIdtPatches;
    625     /** List of patches Free. */
    626     PSUPDRVPATCH volatile           pIdtPatchesFree;
    627 #endif
    628527
    629528    /** List of registered objects. Protected by the spinlock. */
  • trunk/src/VBox/HostDrivers/Support/SUPLib.cpp

    r14501 r14515  
    133133static PSUPQUERYFUNCS g_pFunctions;
    134134
    135 #ifdef VBOX_WITH_IDT_PATCHING
    136 /** The negotiated interrupt number. */
    137 static uint8_t      g_u8Interrupt = 3;
    138 /** Pointer to the generated code fore calling VMMR0. */
    139 static PFNCALLVMMR0 g_pfnCallVMMR0;
    140 #endif
    141135/** VMMR0 Load Address. */
    142136static RTR0PTR      g_pvVMMR0 = NIL_RTR0PTR;
     
    152146static int supInitFake(PSUPDRVSESSION *ppSession);
    153147static int supLoadModule(const char *pszFilename, const char *pszModule, const char *pszSrvReqHandler, void **ppvImageBase);
    154 #ifdef VBOX_WITH_IDT_PATCHING
    155 static int supInstallIDTE(void);
    156 #endif
    157148static DECLCALLBACK(int) supLoadModuleResolveImport(RTLDRMOD hLdrMod, const char *pszModule, const char *pszSymbol, unsigned uSymbol, RTUINTPTR *pValue, void *pvUser);
    158149
     
    463454        if (ppSession)
    464455            *ppSession = g_pSession;
    465 #ifdef VBOX_WITH_IDT_PATCHING
    466         Assert(g_u8Interrupt == 3);
    467 #endif
    468456
    469457        /* fake the GIP. */
     
    515503        g_u32Cookie         = 0;
    516504        g_u32SessionCookie  = 0;
    517 #ifdef VBOX_WITH_IDT_PATCHING
    518         g_u8Interrupt       = 3;
    519 #endif
    520505        g_cInits            = 0;
    521506    }
     
    646631SUPR3DECL(int) SUPCallVMMR0(PVMR0 pVMR0, unsigned uOperation, void *pvArg)
    647632{
    648 #if defined(VBOX_WITH_IDT_PATCHING)
    649     return g_pfnCallVMMR0(pVMR0, uOperation, pvArg);
    650 
    651 #else
    652633    /*
    653634     * The following operations don't belong here.
     
    659640                    VERR_INTERNAL_ERROR);
    660641    return SUPCallVMMR0Ex(pVMR0, uOperation, (uintptr_t)pvArg, NULL);
    661 #endif
    662642}
    663643
     
    12361216#endif
    12371217    if (RT_SUCCESS(rc))
    1238     {
    1239         /*
    1240          * Load the module.
    1241          * If it's VMMR0.r0 we need to install the IDTE.
    1242          */
    12431218        rc = supLoadModule(pszFilename, pszModule, NULL, ppvImageBase);
    1244 #ifdef VBOX_WITH_IDT_PATCHING
    1245         if (    RT_SUCCESS(rc)
    1246             &&  !strcmp(pszModule, "VMMR0.r0"))
    1247         {
    1248             rc = supInstallIDTE();
    1249             if (RT_FAILURE(rc))
    1250                 SUPFreeModule(*ppvImageBase);
    1251         }
    1252 #endif /* VBOX_WITH_IDT_PATCHING */
    1253     }
    12541219    else
    12551220        LogRel(("SUPLoadModule: Verification of \"%s\" failed, rc=%Rrc\n", rc));
     
    12711236#endif
    12721237    if (RT_SUCCESS(rc))
    1273     {
    1274         /*
    1275          * Load the module.
    1276          * If it's VMMR0.r0 we need to install the IDTE.
    1277          */
    12781238        rc = supLoadModule(pszFilename, pszModule, pszSrvReqHandler, ppvImageBase);
    1279     }
    12801239    else
    12811240        LogRel(("SUPR3LoadServiceModule: Verification of \"%s\" failed, rc=%Rrc\n", rc));
    12821241    return rc;
    12831242}
    1284 
    1285 
    1286 #ifdef VBOX_WITH_IDT_PATCHING
    1287 /**
    1288  * Generates the code for calling the interrupt gate.
    1289  *
    1290  * @returns VBox status code.
    1291  *          g_pfnCallVMMR0 is changed on success.
    1292  * @param   u8Interrupt     The interrupt number.
    1293  */
    1294 static int suplibGenerateCallVMMR0(uint8_t u8Interrupt)
    1295 {
    1296     /*
    1297      * Allocate memory.
    1298      */
    1299     uint8_t *pb = (uint8_t *)RTMemExecAlloc(256);
    1300     AssertReturn(pb, VERR_NO_MEMORY);
    1301     memset(pb, 0xcc, 256);
    1302     Assert(!g_pfnCallVMMR0);
    1303     g_pfnCallVMMR0 = *(PFNCALLVMMR0*)&pb;
    1304 
    1305     /*
    1306      * Generate the code.
    1307      */
    1308 #ifdef RT_ARCH_AMD64
    1309     /*
    1310      * reg params:
    1311      *      <GCC>   <MSC>   <argument>
    1312      *      rdi     rcx     pVMR0
    1313      *      esi     edx     uOperation
    1314      *      rdx     r8      pvArg
    1315      *
    1316      *      eax     eax     [g_u32Gookie]
    1317      */
    1318     *pb++ = 0xb8;                       /* mov eax, <g_u32Cookie> */
    1319     *(uint32_t *)pb = g_u32Cookie;
    1320     pb += sizeof(uint32_t);
    1321 
    1322     *pb++ = 0xcd;                       /* int <u8Interrupt> */
    1323     *pb++ = u8Interrupt;
    1324 
    1325     *pb++ = 0xc3;                       /* ret */
    1326 
    1327 #else
    1328     /*
    1329      * x86 stack:
    1330      *          0   saved esi
    1331      *      0   4   ret
    1332      *      4   8   pVM
    1333      *      8   c   uOperation
    1334      *      c  10   pvArg
    1335      */
    1336     *pb++ = 0x56;                       /* push esi */
    1337 
    1338     *pb++ = 0x8b;                       /* mov eax, [pVM] */
    1339     *pb++ = 0x44;
    1340     *pb++ = 0x24;
    1341     *pb++ = 0x08;                       /* esp+08h */
    1342 
    1343     *pb++ = 0x8b;                       /* mov edx, [uOperation] */
    1344     *pb++ = 0x54;
    1345     *pb++ = 0x24;
    1346     *pb++ = 0x0c;                       /* esp+0ch */
    1347 
    1348     *pb++ = 0x8b;                       /* mov ecx, [pvArg] */
    1349     *pb++ = 0x4c;
    1350     *pb++ = 0x24;
    1351     *pb++ = 0x10;                       /* esp+10h */
    1352 
    1353     *pb++ = 0xbe;                       /* mov esi, <g_u32Cookie> */
    1354     *(uint32_t *)pb = g_u32Cookie;
    1355     pb += sizeof(uint32_t);
    1356 
    1357     *pb++ = 0xcd;                       /* int <u8Interrupt> */
    1358     *pb++ = u8Interrupt;
    1359 
    1360     *pb++ = 0x5e;                       /* pop esi */
    1361 
    1362     *pb++ = 0xc3;                       /* ret */
    1363 #endif
    1364 
    1365     return VINF_SUCCESS;
    1366 }
    1367 
    1368 
    1369 /**
    1370  * Installs the IDTE patch.
    1371  *
    1372  * @return VBox status code.
    1373  */
    1374 static int supInstallIDTE(void)
    1375 {
    1376     /* already installed? */
    1377     if (g_u8Interrupt != 3 || g_u32FakeMode)
    1378         return VINF_SUCCESS;
    1379 
    1380     int rc = VINF_SUCCESS;
    1381     const RTCPUID cCpus = RTMpGetCount();
    1382     if (cCpus <= 1)
    1383     {
    1384         /* UNI */
    1385         SUPIDTINSTALL Req;
    1386         Req.Hdr.u32Cookie = g_u32Cookie;
    1387         Req.Hdr.u32SessionCookie = g_u32SessionCookie;
    1388         Req.Hdr.cbIn = SUP_IOCTL_IDT_INSTALL_SIZE_IN;
    1389         Req.Hdr.cbOut = SUP_IOCTL_IDT_INSTALL_SIZE_OUT;
    1390         Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
    1391         Req.Hdr.rc = VERR_INTERNAL_ERROR;
    1392         rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_IDT_INSTALL, &Req, SUP_IOCTL_IDT_INSTALL_SIZE);
    1393         if (RT_SUCCESS(rc))
    1394             rc = Req.Hdr.rc;
    1395         if (RT_SUCCESS(rc))
    1396         {
    1397             g_u8Interrupt = Req.u.Out.u8Idt;
    1398             rc = suplibGenerateCallVMMR0(Req.u.Out.u8Idt);
    1399         }
    1400     }
    1401     else
    1402     {
    1403         /* SMP */
    1404         uint64_t        u64AffMaskSaved = RTThreadGetAffinity();
    1405         RTCPUSET        OnlineSet;
    1406         uint64_t        u64AffMaskPatched = RTCpuSetToU64(RTMpGetOnlineSet(&OnlineSet)) & u64AffMaskSaved;
    1407         unsigned        cCpusPatched = 0;
    1408         AssertLogRelReturn(cCpus < 64, VERR_INTERNAL_ERROR);
    1409 
    1410         for (int i = 0; i < 64; i++)
    1411         {
    1412             /* Skip absent and inactive processors. */
    1413             uint64_t u64Mask = 1ULL << i;
    1414             if (!(u64Mask & u64AffMaskPatched))
    1415                 continue;
    1416 
    1417             /* Change CPU */
    1418             int rc2 = RTThreadSetAffinity(u64Mask);
    1419             if (RT_FAILURE(rc2))
    1420             {
    1421                 u64AffMaskPatched &= ~u64Mask;
    1422                 LogRel(("SUPLoadVMM: Failed to set affinity to cpu no. %d, rc=%Rrc.\n", i, rc2));
    1423                 continue;
    1424             }
    1425 
    1426             /* Patch the CPU. */
    1427             SUPIDTINSTALL Req;
    1428             Req.Hdr.u32Cookie = g_u32Cookie;
    1429             Req.Hdr.u32SessionCookie = g_u32SessionCookie;
    1430             Req.Hdr.cbIn = SUP_IOCTL_IDT_INSTALL_SIZE_IN;
    1431             Req.Hdr.cbOut = SUP_IOCTL_IDT_INSTALL_SIZE_OUT;
    1432             Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
    1433             Req.Hdr.rc = VERR_INTERNAL_ERROR;
    1434             rc2 = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_IDT_INSTALL, &Req, SUP_IOCTL_IDT_INSTALL_SIZE);
    1435             if (RT_SUCCESS(rc2))
    1436                 rc2 = Req.Hdr.rc;
    1437             if (RT_SUCCESS(rc2))
    1438             {
    1439                 if (!cCpusPatched)
    1440                 {
    1441                     g_u8Interrupt = Req.u.Out.u8Idt;
    1442                     rc2 = suplibGenerateCallVMMR0(Req.u.Out.u8Idt);
    1443                     if (RT_FAILURE(rc2))
    1444                     {
    1445                         LogRel(("suplibGenerateCallVMMR0 failed with rc=%Rrc.\n", i, rc2));
    1446                         rc = rc2;
    1447                     }
    1448                 }
    1449                 else
    1450                     Assert(g_u8Interrupt == Req.u.Out.u8Idt);
    1451                 cCpusPatched++;
    1452             }
    1453             else
    1454             {
    1455 
    1456                 LogRel(("SUPLoadVMM: Failed to patch cpu no. %d, rc=%Rrc.\n", i, rc2));
    1457                 if (RT_SUCCESS(rc))
    1458                     rc = rc2;
    1459             }
    1460         }
    1461 
    1462         /* Fail if no CPUs was patched! */
    1463         if (RT_SUCCESS(rc) && cCpusPatched <= 0)
    1464             rc = VERR_GENERAL_FAILURE;
    1465         /* Ignore failures if a CPU was patched. */
    1466         else if (RT_FAILURE(rc) && cCpusPatched > 0)
    1467             rc = VINF_SUCCESS;
    1468 
    1469         /* Set/restore the thread affinity. */
    1470         if (RT_SUCCESS(rc))
    1471         {
    1472             rc = RTThreadSetAffinity(u64AffMaskPatched);
    1473             AssertRC(rc);
    1474         }
    1475         else
    1476         {
    1477             int rc2 = RTThreadSetAffinity(u64AffMaskSaved);
    1478             AssertRC(rc2);
    1479         }
    1480     }
    1481     return rc;
    1482 }
    1483 #endif /* VBOX_WITH_IDT_PATCHING */
    14841243
    14851244
     
    18721631    if (RT_UNLIKELY(g_u32FakeMode))
    18731632    {
    1874 #ifdef VBOX_WITH_IDT_PATCHING
    1875         g_u8Interrupt = 3;
    1876         RTMemExecFree(*(void **)&g_pfnCallVMMR0);
    1877         g_pfnCallVMMR0 = NULL;
    1878 #endif
    18791633        g_pvVMMR0 = NIL_RTR0PTR;
    18801634        return VINF_SUCCESS;
    18811635    }
    1882 
    1883 #ifdef VBOX_WITH_IDT_PATCHING
    1884     /*
    1885      * There is one special module. When this is freed we'll
    1886      * free the IDT entry that goes with it.
    1887      *
    1888      * Note that we don't keep count of VMMR0.r0 loads here, so the
    1889      *      first unload will free it.
    1890      */
    1891     if (    (RTR0PTR)pvImageBase == g_pvVMMR0
    1892         &&  g_u8Interrupt != 3)
    1893     {
    1894         SUPIDTREMOVE Req;
    1895         Req.Hdr.u32Cookie = g_u32Cookie;
    1896         Req.Hdr.u32SessionCookie = g_u32SessionCookie;
    1897         Req.Hdr.cbIn = SUP_IOCTL_IDT_REMOVE_SIZE_IN;
    1898         Req.Hdr.cbOut = SUP_IOCTL_IDT_REMOVE_SIZE_OUT;
    1899         Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
    1900         Req.Hdr.rc = VERR_INTERNAL_ERROR;
    1901         int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_IDT_REMOVE, &Req, SUP_IOCTL_IDT_REMOVE_SIZE);
    1902         if (RT_SUCCESS(rc))
    1903             rc = Req.Hdr.rc;
    1904         AssertRC(rc);
    1905         g_u8Interrupt = 3;
    1906         RTMemExecFree(*(void **)&g_pfnCallVMMR0);
    1907         g_pfnCallVMMR0 = NULL;
    1908     }
    1909 #endif /* VBOX_WITH_IDT_PATCHING */
    19101636
    19111637    /*
  • trunk/src/VBox/HostDrivers/Support/testcase/Makefile.kmk

    r12252 r14515  
    5858tstInt_SOURCES        = tstInt.cpp
    5959tstInt_LIBS           = $(LIB_RUNTIME)
    60 ifdef VBOX_WITH_IDT_PATCHING
    61 tstInt_DEFS          += VBOX_WITH_IDT_PATCHING
    62 endif
    6360
    6461tstContiguous_TEMPLATE= VBOXR3TSTEXE
  • trunk/src/VBox/HostDrivers/Support/testcase/tstInt.cpp

    r13858 r14515  
    162162                                 i, NanoSecs, Ticks, NanoSecs / i, Ticks / i, MinTicks);
    163163
    164 #ifdef VBOX_WITH_IDT_PATCHING
    165                         /*
    166                          * The fast path.
    167                          */
    168                         RTTimeNanoTS();
    169                         StartTS = RTTimeNanoTS();
    170                         StartTick = ASMReadTSC();
    171                         MinTicks = UINT64_MAX;
    172                         for (i = 0; i < 1000000; i++)
    173                         {
    174                             uint64_t OneStartTick = ASMReadTSC();
    175                             rc = SUPCallVMMR0(pVMR0, VMMR0_DO_NOP, NULL);
    176                             uint64_t Ticks = ASMReadTSC() - OneStartTick;
    177                             if (Ticks < MinTicks)
    178                                 MinTicks = Ticks;
    179 
    180                             if (RT_UNLIKELY(rc != VINF_SUCCESS))
    181                             {
    182                                 RTPrintf("tstInt: SUPCallVMMR0/idt -> rc=%Rrc i=%d Expected VINF_SUCCESS!\n", rc, i);
    183                                 rcRet++;
    184                                 break;
    185                             }
    186                         }
    187                         Ticks = ASMReadTSC() - StartTick;
    188                         NanoSecs = RTTimeNanoTS() - StartTS;
    189 
    190                         RTPrintf("tstInt: SUPCallVMMR0/idt - %d iterations in %llu ns / %llu ticks. %llu ns / %#llu ticks per iteration. Min %llu ticks.\n",
    191                                  i, NanoSecs, Ticks, NanoSecs / i, Ticks / i, MinTicks);
    192 #endif /* VBOX_WITH_IDT_PATCHING */
    193 
    194164                        /*
    195165                         * The ordinary path.
  • trunk/src/VBox/VMM/Makefile.kmk

    r14167 r14515  
    3535VMMR3_DEFS      = IN_VMM_R3 IN_DIS IN_GMM_R3 IN_DBG
    3636## @todo eliminate IN_GMM_R3
    37 ifdef VBOX_WITH_IDT_PATCHING
    38 VMMR3_DEFS     += VBOX_WITH_IDT_PATCHING
    39 endif
    4037ifdef VBOX_WITH_PREALLOC_RAM_BY_DEFAULT
    4138VMMR3_DEFS     += VBOX_WITH_PREALLOC_RAM_BY_DEFAULT
     
    302299        PATM
    303300VMMGC_DEFS      = IN_VMM_RC IN_RT_GC IN_RT_RC IN_DIS DIS_CORE_ONLY
    304 ifdef VBOX_WITH_IDT_PATCHING
    305 VMMGC_DEFS     += VBOX_WITH_IDT_PATCHING
    306 endif
    307301ifdef VBOX_WITH_R0_LOGGING
    308302VMMGC_DEFS     += VBOX_WITH_R0_LOGGING
     
    400394VMMR0_DEFS      = IN_VMM_R0 IN_RT_R0 IN_DIS DIS_CORE_ONLY IN_GVMM_R0 IN_GMM_R0 IN_INTNET_R0 RTASSERT_HAVE_SHOULD_PANIC
    401395## @todo eliminate IN_GVMM_R0 IN_GMM_R0
    402 ifdef VBOX_WITH_IDT_PATCHING
    403 VMMR0_DEFS     += VBOX_WITH_IDT_PATCHING
    404 endif
    405396ifdef VBOX_WITH_R0_LOGGING
    406397VMMR0_DEFS     += VBOX_WITH_R0_LOGGING
  • trunk/src/VBox/VMM/TRPMInternal.h

    r14351 r14515  
    240240DECLASM(void) trpmR0DispatchHostInterruptSimple(RTUINT uActiveVector);
    241241
    242 # ifdef VBOX_WITH_IDT_PATCHING
    243 /**
    244  * Code used for the dispatching of interrupts in R0 upon return from RC.
    245  * @internal
    246  */
    247 DECLASM(int) trpmR0InterruptDispatcher(void);
    248 # endif /* VBOX_WITH_IDT_PATCHING */
    249 
    250242#endif /* IN_RING0 */
    251243
  • trunk/src/VBox/VMM/VMMR0/TRPMR0.cpp

    r12989 r14515  
    101101}
    102102
    103 
    104 #ifdef VBOX_WITH_IDT_PATCHING
    105 # ifdef VBOX_WITH_HYBIRD_32BIT_KERNEL
    106 #  error "VBOX_WITH_HYBIRD_32BIT_KERNEL with VBOX_WITH_IDT_PATCHING isn't supported"
    107 # endif
    108 
    109 /**
    110  * Changes the VMMR0Entry() call frame and stack used by the IDT patch code
    111  * so that we'll dispatch an interrupt rather than returning directly to Ring-3
    112  * when VMMR0Entry() returns.
    113  *
    114  * @param   pVM         Pointer to the VM.
    115  * @param   pvRet       Pointer to the return address of VMMR0Entry() on the stack.
    116  */
    117 VMMR0DECL(void) TRPMR0SetupInterruptDispatcherFrame(PVM pVM, void *pvRet)
    118 {
    119     RTUINT uActiveVector = pVM->trpm.s.uActiveVector;
    120     pVM->trpm.s.uActiveVector = ~0;
    121     AssertMsgReturnVoid(uActiveVector < 256, ("uActiveVector=%#x is invalid! (More assertions to come, please enjoy!)\n", uActiveVector));
    122 
    123 #if HC_ARCH_BITS == 32
    124     /*
    125      * Get the handler pointer (16:32 ptr).
    126      */
    127     RTIDTR      Idtr;
    128     ASMGetIDTR(&Idtr);
    129     PVBOXIDTE   pIdte = &((PVBOXIDTE)Idtr.pIdt)[uActiveVector];
    130     AssertMsgReturnVoid(pIdte->Gen.u1Present, ("The IDT entry (%d) is not present!\n", uActiveVector));
    131     AssertMsgReturnVoid(    pIdte->Gen.u3Type1 == VBOX_IDTE_TYPE1
    132                         &&  pIdte->Gen.u5Type2 == VBOX_IDTE_TYPE2_INT_32,
    133                         ("The IDT entry (%d) is not 32-bit int gate! type1=%#x type2=%#x\n",
    134                          uActiveVector, pIdte->Gen.u3Type1, pIdte->Gen.u5Type2));
    135 
    136     RTFAR32   pfnHandler;
    137     pfnHandler.off = VBOXIDTE_OFFSET(*pIdte);
    138     pfnHandler.sel = pIdte->Gen.u16SegSel;
    139 
    140     /*
    141      * The stack frame is as follows:
    142      *
    143      *      1c  iret frame
    144      *      18  fs
    145      *      14  ds
    146      *      10  es
    147      *       c  uArg
    148      *       8  uOperation
    149      *       4  pVM
    150      *       0  return address (pvRet points here)
    151      *
    152      * We'll change the stackframe so that we will not return
    153      * to the caller but to a interrupt dispatcher. We'll also
    154      * setup the frame so that ds and es are moved to give room
    155      * to a far return (to the handler).
    156      */
    157     unsigned *pau = (unsigned *)pvRet;
    158     pau[0] = (unsigned)trpmR0InterruptDispatcher; /* new return address */
    159     pau[3] = pau[6];                    /* uArg = fs */
    160     pau[2] = pau[5];                    /* uOperation = ds */
    161     pau[5] = pfnHandler.off;            /* ds = retf off */
    162     pau[6] = pfnHandler.sel;            /* fs = retf sel */
    163 
    164 #else /* 64-bit: */
    165 
    166     /*
    167      * Get the handler pointer (16:48 ptr).
    168      */
    169     RTIDTR      Idtr;
    170     ASMGetIDTR(&Idtr);
    171     PVBOXIDTE   pIdte = &((PVBOXIDTE)Idtr.pIdt)[uActiveVector * 2];
    172 
    173     AssertMsgReturnVoid(pIdte->Gen.u1Present, ("The IDT entry (%d) is not present!\n", uActiveVector));
    174     AssertMsgReturnVoid(    pIdte->Gen.u3Type1 == VBOX_IDTE_TYPE1
    175                         &&  pIdte->Gen.u5Type2 == VBOX_IDTE_TYPE2_INT_32, /* == 64 */
    176                         ("The IDT entry (%d) is not 64-bit int gate! type1=%#x type2=%#x\n",
    177                          uActiveVector, pIdte->Gen.u3Type1, pIdte->Gen.u5Type2));
    178 
    179     RTFAR64   pfnHandler;
    180     pfnHandler.off = VBOXIDTE_OFFSET(*pIdte);
    181     pfnHandler.off |= (uint64_t)(*(uint32_t *)(pIdte + 1)) << 32; //cleanup!
    182     pfnHandler.sel = pIdte->Gen.u16SegSel;
    183 
    184     if (pIdte->au32[1] & 0x7 /*IST*/)
    185     {
    186         /** @todo implement IST */
    187     }
    188 
    189     /*
    190      * The stack frame is as follows:
    191      *
    192      *      28  iret frame
    193      *      20  dummy
    194      *      14  uArg
    195      *      10  uOperation
    196      *       8  pVM
    197      *       0  return address (pvRet points here)
    198      *
    199      * We'll change the stackframe so that we will not return
    200      * to the caller but to a interrupt dispatcher. And we'll create
    201      * a 64-bit far return frame where dummy and uArg is.
    202      */
    203     uint64_t *pau = (uint64_t *)pvRet;
    204     Assert(pau[1] == (uint64_t)pVM);
    205     pau[0] = (uint64_t)trpmR0InterruptDispatcher; /* new return address */
    206     pau[3] = pfnHandler.off;            /* retf off */
    207     pau[4] = pfnHandler.sel;            /* retf sel */
    208 #endif
    209 }
    210 
    211 #endif /* VBOX_WITH_IDT_PATCHING */
  • trunk/src/VBox/VMM/VMMR0/TRPMR0A.asm

    r8155 r14515  
    119119
    120120
    121 %ifdef VBOX_WITH_IDT_PATCHING
    122 
    123     align 16
    124 ;;
    125 ; This is the alternative return from VMMR0Entry() used when
    126 ; we need to dispatch an interrupt to the Host (we received it in GC).
    127 ;
    128 ; As seen in TRPMR0SetupInterruptDispatcherFrame() the stack is different
    129 ; than for the normal VMMR0Entry() return.
    130 ;
    131 ; 32-bit:
    132 ;           18  iret frame
    133 ;           14  retf selector (interrupt handler)
    134 ;           10  retf offset   (interrupt handler)
    135 ;            c  es
    136 ;            8  fs
    137 ;            4  ds
    138 ;            0  pVM (esp here)
    139 ;
    140 ; 64-bit:
    141 ;           24  iret frame
    142 ;           18  retf selector (interrupt handler)
    143 ;           10  retf offset   (interrupt handler)
    144 ;            8  uOperation
    145 ;            0  pVM (rsp here)
    146 ;
    147 BEGINPROC trpmR0InterruptDispatcher
    148 %ifdef RT_ARCH_AMD64
    149     lea     rsp, [rsp + 10h]            ; skip pVM and uOperation
    150     swapgs
    151     db 48h
    152     retf
    153 %else  ; !RT_ARCH_AMD64
    154     add     esp, byte 4                 ; skip pVM
    155     pop     ds
    156     pop     fs
    157     pop     es
    158     retf
    159 %endif ; !RT_ARCH_AMD64
    160 ENDPROC   trpmR0InterruptDispatcher
    161 
    162 %endif ; VBOX_WITH_IDT_PATCHING
    163 
    164 
    165121;;
    166122; Issues a software interrupt to the specified interrupt vector.
  • trunk/src/VBox/VMM/VMMR0/VMMR0.cpp

    r14500 r14515  
    475475
    476476/**
    477  * The Ring 0 entry point, called by the interrupt gate.
     477 * Unused ring-0 entry point that used to be called from the interrupt gate.
     478 *
     479 * Will be removed one of the next times we do a major SUPDrv version bump.
    478480 *
    479481 * @returns VBox status code.
     
    487489    switch (enmOperation)
    488490    {
    489 #ifdef VBOX_WITH_IDT_PATCHING
    490         /*
    491          * Switch to GC.
    492          * These calls return whatever the GC returns.
    493          */
    494         case VMMR0_DO_RAW_RUN:
    495         {
    496             /* Safety precaution as VMX disables the switcher. */
    497             Assert(!pVM->vmm.s.fSwitcherDisabled);
    498             if (pVM->vmm.s.fSwitcherDisabled)
    499                 return VERR_NOT_SUPPORTED;
    500 
    501             STAM_COUNTER_INC(&pVM->vmm.s.StatRunRC);
    502             register int rc;
    503             pVM->vmm.s.iLastGZRc = rc = pVM->vmm.s.pfnHostToGuestR0(pVM);
    504 
    505 #ifdef VBOX_WITH_STATISTICS
    506             vmmR0RecordRC(pVM, rc);
    507 #endif
    508 
    509             /*
    510              * We'll let TRPM change the stack frame so our return is different.
    511              * Just keep in mind that after the call, things have changed!
    512              */
    513             if (    rc == VINF_EM_RAW_INTERRUPT
    514                 ||  rc == VINF_EM_RAW_INTERRUPT_HYPER)
    515             {
    516                 /*
    517                  * Don't trust the compiler to get this right.
    518                  * gcc -fomit-frame-pointer screws up big time here. This works fine in 64-bit
    519                  * mode too because we push the arguments on the stack in the IDT patch code.
    520                  */
    521 # if defined(__GNUC__)
    522                 void *pvRet = (uint8_t *)__builtin_frame_address(0) + sizeof(void *);
    523 # elif defined(_MSC_VER) && defined(RT_ARCH_AMD64) /** @todo check this with with VC7! */
    524                 void *pvRet = (uint8_t *)_AddressOfReturnAddress();
    525 # elif defined(RT_ARCH_X86)
    526                 void *pvRet = (uint8_t *)&pVM - sizeof(pVM);
    527 # else
    528 #  error "huh?"
    529 # endif
    530                 if (    ((uintptr_t *)pvRet)[1] == (uintptr_t)pVM
    531                     &&  ((uintptr_t *)pvRet)[2] == (uintptr_t)enmOperation
    532                     &&  ((uintptr_t *)pvRet)[3] == (uintptr_t)pvArg)
    533                     TRPMR0SetupInterruptDispatcherFrame(pVM, pvRet);
    534                 else
    535                 {
    536 # if defined(DEBUG) || defined(LOG_ENABLED)
    537                     static bool  s_fHaveWarned = false;
    538                     if (!s_fHaveWarned)
    539                     {
    540                          s_fHaveWarned = true;
    541                          RTLogPrintf("VMMR0.r0: The compiler can't find the stack frame!\n");
    542                          RTLogComPrintf("VMMR0.r0: The compiler can't find the stack frame!\n");
    543                     }
    544 # endif
    545                     TRPMR0DispatchHostInterrupt(pVM);
    546                 }
    547             }
    548             return rc;
    549         }
    550 
    551         /*
    552          * Switch to GC to execute Hypervisor function.
    553          */
    554         case VMMR0_DO_CALL_HYPERVISOR:
    555         {
    556             /* Safety precaution as VMX disables the switcher. */
    557             Assert(!pVM->vmm.s.fSwitcherDisabled);
    558             if (pVM->vmm.s.fSwitcherDisabled)
    559                 return VERR_NOT_SUPPORTED;
    560 
    561             RTCCUINTREG fFlags = ASMIntDisableFlags();
    562             int rc = pVM->vmm.s.pfnHostToGuestR0(pVM);
    563             /** @todo dispatch interrupts? */
    564             ASMSetFlags(fFlags);
    565             return rc;
    566         }
    567 
    568         /*
    569          * For profiling.
    570          */
    571         case VMMR0_DO_NOP:
    572             return VINF_SUCCESS;
    573 #endif /* VBOX_WITH_IDT_PATCHING */
    574 
    575491        default:
    576492            /*
  • trunk/src/VBox/VMM/testcase/Makefile.kmk

    r14118 r14515  
    8989tstVMStructGC_TEMPLATE  = VBOXGCEXE
    9090tstVMStructGC_DEFS      = IN_VMM_RC IN_DIS IN_RT_RC IN_RT_GC
    91 ifdef VBOX_WITH_IDT_PATCHING
    92 tstVMStructGC_DEFS     += VBOX_WITH_IDT_PATCHING
    93 endif
    9491ifdef VBOX_WITH_R0_LOGGING
    9592tstVMStructGC_DEFS     += VBOX_WITH_R0_LOGGING
     
    103100tstVMStructSize_SOURCES = tstVMStructSize.cpp
    104101tstVMStructSize.cpp_DEPS= $(VBOX_VMM_TESTCASE_OUT_DIR)/tstVMStructGC.h
    105 ifdef VBOX_WITH_IDT_PATCHING
    106 tstVMStructSize_DEFS   += VBOX_WITH_IDT_PATCHING
    107 endif
    108102ifdef VBOX_WITH_R0_LOGGING
    109103tstVMStructSize_DEFS   += VBOX_WITH_R0_LOGGING
     
    116110tstAsmStructs_TEMPLATE  = VBOXR3AUTOTST
    117111tstAsmStructs_DEFS      = IN_VMM_R3 IN_DIS
    118 ifdef VBOX_WITH_IDT_PATCHING
    119 tstAsmStructs_DEFS     += VBOX_WITH_IDT_PATCHING
    120 endif
    121112ifdef VBOX_WITH_R0_LOGGING
    122113tstAsmStructs_DEFS     += VBOX_WITH_R0_LOGGING
     
    127118tstAsmStructsGC_TEMPLATE= VBOXGCEXE
    128119tstAsmStructsGC_DEFS    = IN_VMM_RC IN_DIS IN_RT_RC IN_RT_GC
    129 ifdef VBOX_WITH_IDT_PATCHING
    130 tstAsmStructsGC_DEFS    += VBOX_WITH_IDT_PATCHING
    131 endif
    132120ifdef VBOX_WITH_R0_LOGGING
    133121tstAsmStructsGC_DEFS   += VBOX_WITH_R0_LOGGING
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