Changeset 14515 in vbox for trunk/src/VBox
- Timestamp:
- Nov 24, 2008 12:33:00 PM (16 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/Makefile.kmk
r14015 r14515 76 76 endif 77 77 SUPR3_DEFS = IN_SUP_R3 IN_RT_R3 78 ifdef VBOX_WITH_IDT_PATCHING79 SUPR3_DEFS += VBOX_WITH_IDT_PATCHING80 endif81 78 ifdef VBOX_WITH_SUPSVC 82 79 SUPR3_DEFS += VBOX_WITH_SUPSVC … … 166 163 endif 167 164 VBoxDrv_DEFS = IN_RT_R0 IN_SUP_R0 SUPDRV_WITH_RELEASE_LOGGER 168 ifdef VBOX_WITH_IDT_PATCHING169 VBoxDrv_DEFS += VBOX_WITH_IDT_PATCHING170 endif171 165 VBoxDrv_DEFS.amd64 = RT_WITH_W64_UNWIND_HACK 172 166 VBoxDrv_SDKS = W2K3DDK WINPSDKINCS … … 220 214 vboxdrv_NOINST = true 221 215 vboxdrv_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_PATCHING223 vboxdrv_DEFS += VBOX_WITH_IDT_PATCHING224 endif225 216 ifdef VBOX_LINUX_VERSION_2_4 226 217 vboxdrv_DEFS += EXPORT_SYMTAB … … 304 295 VBoxDrv_TEMPLATE = VBOXR0DRV 305 296 VBoxDrv_DEFS = IN_RT_R0 IN_SUP_R0 SUPDRV_WITH_RELEASE_LOGGER VBOX_SVN_REV=$(VBOX_SVN_REV) 306 ifdef VBOX_WITH_IDT_PATCHING307 VBoxDrv_DEFS += VBOX_WITH_IDT_PATCHING308 endif309 297 VBoxDrv_DEFS += DEBUG_DARWIN_GIP 310 298 VBoxDrv_INCS := $(PATH_SUB_CURRENT) … … 378 366 vboxdrv_TEMPLATE = VBOXR0DRV 379 367 vboxdrv_DEFS = IN_RT_R0 IN_SUP_R0 SUPDRV_WITH_RELEASE_LOGGER VBOX_SVN_REV=$(VBOX_SVN_REV) 380 ifdef VBOX_WITH_IDT_PATCHING381 vboxdrv_DEFS += VBOX_WITH_IDT_PATCHING382 endif383 368 vboxdrv_INCS := $(PATH_SUB_CURRENT) 384 369 vboxdrv_LIBS = $(PATH_LIB)/RuntimeR0Drv$(VBOX_SUFF_LIB) … … 397 382 vboxdrv_TEMPLATE = VBOXR0DRV 398 383 vboxdrv_DEFS = IN_RT_R0 IN_SUP_R0 SUPDRV_WITH_RELEASE_LOGGER 399 ifdef VBOX_WITH_IDT_PATCHING400 vboxdrv_DEFS += VBOX_WITH_IDT_PATCHING401 endif402 384 ifdef VBOX_WITH_NETFLT 403 vboxdrv_DEFS 385 vboxdrv_DEFS += VBOX_WITH_NETFLT 404 386 endif 405 387 vboxdrv_DEFS += VBOX_SVN_REV=$(VBOX_SVN_REV) -
trunk/src/VBox/HostDrivers/Support/SUPDrv.c
r14512 r14515 65 65 * Log - useful stuff, like failures. 66 66 * LogFlow - program flow, except the really noisy bits. 67 * Log2 - Cleanup and IDTE67 * Log2 - Cleanup. 68 68 * Log3 - Loader flow noise. 69 69 * Log4 - Call VMMR0 flow noise. … … 125 125 static int supdrvMemAdd(PSUPDRVMEMREF pMem, PSUPDRVSESSION pSession); 126 126 static int supdrvMemRelease(PSUPDRVSESSION pSession, RTHCUINTPTR uPtr, SUPDRVMEMREFTYPE eType); 127 #ifdef VBOX_WITH_IDT_PATCHING128 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 */134 127 static int supdrvIOCtl_LdrOpen(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPLDROPEN pReq); 135 128 static int supdrvIOCtl_LdrLoad(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPLDRLOAD pReq); … … 137 130 static int supdrvIOCtl_LdrGetSymbol(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPLDRGETSYMBOL pReq); 138 131 static int supdrvIDC_LdrGetSymbol(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPDRVIDCREQGETSYM pReq); 139 static int supdrvLdrSet R0EP(PSUPDRVDEVEXT pDevExt, void *pvVMMR0, void *pvVMMR0EntryInt, void *pvVMMR0EntryFast, void *pvVMMR0EntryEx);140 static void supdrvLdrUnset R0EP(PSUPDRVDEVEXT pDevExt);132 static int supdrvLdrSetVMMR0EPs(PSUPDRVDEVEXT pDevExt, void *pvVMMR0, void *pvVMMR0EntryInt, void *pvVMMR0EntryFast, void *pvVMMR0EntryEx); 133 static void supdrvLdrUnsetVMMR0EPs(PSUPDRVDEVEXT pDevExt); 141 134 static int supdrvLdrAddUsage(PSUPDRVSESSION pSession, PSUPDRVLDRIMAGE pImage); 142 135 static void supdrvLdrFree(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage); … … 503 496 void VBOXCALL supdrvDeleteDevExt(PSUPDRVDEVEXT pDevExt) 504 497 { 505 #ifdef VBOX_WITH_IDT_PATCHING506 PSUPDRVPATCH pPatch;507 #endif508 498 PSUPDRVOBJ pObj; 509 499 PSUPDRVUSAGE pUsage; … … 524 514 * Free lists. 525 515 */ 526 #ifdef VBOX_WITH_IDT_PATCHING527 /* 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 539 516 /* objects. */ 540 517 pObj = pDevExt->pObjs; … … 596 573 pSession->u32Cookie = BIRD_INV; 597 574 /*pSession->pLdrUsage = NULL; 598 pSession->pPatchUsage = NULL;599 575 pSession->pVM = NULL; 600 576 pSession->pUsage = NULL; … … 672 648 */ 673 649 RTLogSetDefaultInstanceThread(NULL, (uintptr_t)pSession); 674 675 #ifdef VBOX_WITH_IDT_PATCHING676 /*677 * Uninstall any IDT patches installed for this session.678 */679 supdrvIOCtl_IdtRemoveAll(pDevExt, pSession);680 #endif681 650 682 651 /* … … 1125 1094 1126 1095 /* execute */ 1127 #ifdef VBOX_WITH_IDT_PATCHING1128 pReq->Hdr.rc = supdrvIOCtl_IdtInstall(pDevExt, pSession, pReq);1129 #else1130 1096 pReq->u.Out.u8Idt = 3; 1131 1097 pReq->Hdr.rc = VERR_NOT_SUPPORTED; 1132 #endif1133 1098 return 0; 1134 1099 } … … 1141 1106 1142 1107 /* execute */ 1143 #ifdef VBOX_WITH_IDT_PATCHING1144 pReq->Hdr.rc = supdrvIOCtl_IdtRemoveAll(pDevExt, pSession);1145 #else1146 1108 pReq->Hdr.rc = VERR_NOT_SUPPORTED; 1147 #endif1148 1109 return 0; 1149 1110 } … … 3032 2993 3033 2994 3034 #ifdef VBOX_WITH_IDT_PATCHING3035 /**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 do3057 * 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 else3083 {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 else3104 {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 else3132 {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 entry3164 * 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 on3171 * 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 of3200 * these 48 entries is unused (which is not a problem on Win32 and3201 * Linux to my knowledge).3202 */3203 /** @todo we MUST change this detection to try grab an entry which is NOT in use. This can be3204 * 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 #endif3213 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 #endif3230 /* 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.cbIdt3235 && ( !paIdt[u8Idt].u1Present3236 || 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.cbIdt3247 && paIdt[u8Idt].u1Present3248 && paIdt[u8Idt].u5Type2 == SUPDRV_IDTE_TYPE2_INTERRUPT_GATE3249 && !(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 patch3265 */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_AMD643274 pPatch->ChangedIdt.u32OffsetTop = (uint32_t)((uintptr_t)&pPatch->auCode[0] >> 32);3275 #endif3276 pPatch->ChangedIdt.u16SegSel = ASMGetCS();3277 #ifdef RT_ARCH_AMD643278 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_AMD643293 union3294 {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, GLOBALCOOKIE3303 *u.pu32++ = pDevExt->u32Cookie;3304 3305 *u.pb++ = 0x74; // jz @VBoxCall3306 *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; // swapgs3315 *u.pb++ = 0x01;3316 *u.pb++ = 0xf8;3317 3318 /*3319 * Call VMMR0Entry3320 * We don't have to push the arguments here, but we have top3321 * reserve some stack space for the interrupt forwarding.3322 */3323 # ifdef RT_OS_WINDOWS3324 *u.pb++ = 0x50; // push rax ; alignment filler.3325 *u.pb++ = 0x41; // push r8 ; uArg3326 *u.pb++ = 0x50;3327 *u.pb++ = 0x52; // push rdx ; uOperation3328 *u.pb++ = 0x51; // push rcx ; pVM3329 # else3330 *u.pb++ = 0x51; // push rcx ; alignment filler.3331 *u.pb++ = 0x52; // push rdx ; uArg3332 *u.pb++ = 0x56; // push rsi ; uOperation3333 *u.pb++ = 0x57; // push rdi ; pVM3334 # endif3335 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; // swapgs3347 *u.pb++ = 0x01;3348 *u.pb++ = 0xf8;3349 3350 /* Return to R3. */3351 uNotNested = u;3352 *u.pb++ = 0x48; // iretq3353 *u.pb++ = 0xcf;3354 3355 while ((uintptr_t)u.pb & 0x7) // align 83356 *u.pb++ = 0xcc;3357 3358 /* Pointer to the VMMR0Entry. */ // pfnVMMR0EntryInt dq StubVMMR0Entry3359 *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, eax3366 *u.pb++ = 0xc0;3367 3368 *u.pb++ = 0x48; // dec rax3369 *u.pb++ = 0xff;3370 *u.pb++ = 0xc8;3371 3372 *u.pb++ = 0xc3; // ret3373 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.u5Type23382 ? (uint32_t)(uintptr_t)uNotNested.pb3383 : (uint32_t)pPatch->SavedIdt.u16OffsetLow3384 | (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.u5Type23391 ? (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 union3400 {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, GLOBALCOOKIE3409 *u.pb++ = 0xfe;3410 *u.pu32++ = pDevExt->u32Cookie;3411 3412 *u.pb++ = 0x74; // jz VBoxCall3413 uFixJmp = u;3414 *u.pb++ = 0;3415 3416 /* jump (far) to the original handler / not-nested-stub. */3417 *u.pb++ = 0xea; // jmp far NotNested3418 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 fs3425 *u.pb++ = 0xa0;3426 3427 *u.pb++ = 0x1e; // push ds3428 3429 *u.pb++ = 0x06; // push es3430 3431 /* call frame */3432 *u.pb++ = 0x51; // push ecx3433 3434 *u.pb++ = 0x52; // push edx3435 3436 *u.pb++ = 0x50; // push eax3437 3438 /* load ds, es and perhaps fs before call. */3439 *u.pb++ = 0xb8; // mov eax, KernelDS3440 *u.pu32++ = ASMGetDS();3441 3442 *u.pb++ = 0x8e; // mov ds, eax3443 *u.pb++ = 0xd8;3444 3445 *u.pb++ = 0x8e; // mov es, eax3446 *u.pb++ = 0xc0;3447 3448 #ifdef RT_OS_WINDOWS3449 *u.pb++ = 0xb8; // mov eax, KernelFS3450 *u.pu32++ = ASMGetFS();3451 3452 *u.pb++ = 0x8e; // mov fs, eax3453 *u.pb++ = 0xe0;3454 #endif3455 3456 /* do the call. */3457 *u.pb++ = 0xe8; // call _VMMR0Entry / StubVMMR0Entry3458 uFixCall = u;3459 pPatch->offVMMR0EntryFixup = (uint16_t)(u.pb - &pPatch->auCode[0]);3460 *u.pu32++ = 0xfffffffb;3461 3462 *u.pb++ = 0x83; // add esp, 0ch ; cdecl3463 *u.pb++ = 0xc4;3464 *u.pb++ = 0x0c;3465 3466 /* restore selector registers. */3467 *u.pb++ = 0x07; // pop es3468 //3469 *u.pb++ = 0x1f; // pop ds3470 3471 *u.pb++ = 0x0f; // pop fs3472 *u.pb++ = 0xa1;3473 3474 uNotNested = u; // NotNested:3475 *u.pb++ = 0xcf; // iretd3476 3477 /* the stub VMMR0Entry. */ // StubVMMR0Entry:3478 pPatch->offStub = (uint16_t)(u.pb - &pPatch->auCode[0]);3479 *u.pb++ = 0x33; // xor eax, eax3480 *u.pb++ = 0xc0;3481 3482 *u.pb++ = 0x48; // dec eax3483 3484 *u.pb++ = 0xc3; // ret3485 3486 /* Fixup the VMMR0Entry call. */3487 if (pDevExt->pvVMMR0)3488 *uFixCall.pu32 = (uint32_t)pDevExt->pfnVMMR0EntryInt - (uint32_t)(uFixCall.pu32 + 1);3489 else3490 *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 else3499 {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 03506 /* 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 #endif3511 }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 else3557 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 else3630 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 a3666 * 64-bit locked write when updating the IDT entry.3667 *3668 * The F00F bugfix for linux (and probably other OSes) causes3669 * the IDT to be pointing to an readonly mapping. We get around that3670 * by temporarily turning of WP. Since we're inside a spinlock at this3671 * point, interrupts are disabled and there isn't any way the WP bit3672 * 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_AMD643684 ASMAtomicXchgU128((volatile uint128_t *)pvIdtEntry, *(uint128_t *)(uintptr_t)pNewIDTEntry);3685 #else3686 ASMAtomicXchgU64((volatile uint64_t *)pvIdtEntry, *(uint64_t *)(uintptr_t)pNewIDTEntry);3687 #endif3688 3689 /* Restore CR0 & Flags */3690 ASMSetCR0(uCR0);3691 ASMSetFlags(uFlags);3692 }3693 #endif /* VBOX_WITH_IDT_PATCHING */3694 3695 3696 2995 /** 3697 2996 * Opens an image. If it's the first time it's opened the call must upload … … 3919 3218 break; 3920 3219 case SUPLDRLOADEP_VMMR0: 3921 rc = supdrvLdrSet R0EP(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); 3923 3222 break; 3924 3223 case SUPLDRLOADEP_SERVICE: … … 3941 3240 #endif 3942 3241 if (rc && pDevExt->pvVMMR0 == pImage->pvImage) 3943 supdrvLdrUnset R0EP(pDevExt);3242 supdrvLdrUnsetVMMR0EPs(pDevExt); 3944 3243 } 3945 3244 … … 4216 3515 4217 3516 /** 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. 4220 3518 * 4221 3519 * @returns IPRT status code. … … 4228 3526 * @remark Caller must own the loader mutex. 4229 3527 */ 4230 static int supdrvLdrSet R0EP(PSUPDRVDEVEXT pDevExt, void *pvVMMR0, void *pvVMMR0EntryInt, void *pvVMMR0EntryFast, void *pvVMMR0EntryEx)3528 static int supdrvLdrSetVMMR0EPs(PSUPDRVDEVEXT pDevExt, void *pvVMMR0, void *pvVMMR0EntryInt, void *pvVMMR0EntryFast, void *pvVMMR0EntryEx) 4231 3529 { 4232 3530 int rc = VINF_SUCCESS; … … 4239 3537 if (!pDevExt->pvVMMR0) 4240 3538 { 4241 #ifdef VBOX_WITH_IDT_PATCHING4242 PSUPDRVPATCH pPatch;4243 #endif4244 4245 /*4246 * Set it and update IDT patch code.4247 */4248 3539 pDevExt->pvVMMR0 = pvVMMR0; 4249 3540 pDevExt->pfnVMMR0EntryInt = pvVMMR0EntryInt; 4250 3541 pDevExt->pfnVMMR0EntryFast = pvVMMR0EntryFast; 4251 3542 pDevExt->pfnVMMR0EntryEx = pvVMMR0EntryEx; 4252 #ifdef VBOX_WITH_IDT_PATCHING4253 for (pPatch = pDevExt->pIdtPatches; pPatch; pPatch = pPatch->pNext)4254 {4255 # ifdef RT_ARCH_AMD644256 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 # endif4261 }4262 #endif /* VBOX_WITH_IDT_PATCHING */4263 3543 } 4264 3544 else … … 4281 3561 4282 3562 /** 4283 * Unsets the R0 entry point installed by supdrvLdrSetR0EP.3563 * Unsets the VMMR0 entry point installed by supdrvLdrSetR0EP. 4284 3564 * 4285 3565 * @param pDevExt Device globals. 4286 3566 */ 4287 static void supdrvLdrUnsetR0EP(PSUPDRVDEVEXT pDevExt) 4288 { 4289 #ifdef VBOX_WITH_IDT_PATCHING 4290 PSUPDRVPATCH pPatch; 4291 #endif 4292 3567 static void supdrvLdrUnsetVMMR0EPs(PSUPDRVDEVEXT pDevExt) 3568 { 4293 3569 pDevExt->pvVMMR0 = NULL; 4294 3570 pDevExt->pfnVMMR0EntryInt = NULL; 4295 3571 pDevExt->pfnVMMR0EntryFast = NULL; 4296 3572 pDevExt->pfnVMMR0EntryEx = NULL; 4297 4298 #ifdef VBOX_WITH_IDT_PATCHING4299 for (pPatch = pDevExt->pIdtPatches; pPatch; pPatch = pPatch->pNext)4300 {4301 # ifdef RT_ARCH_AMD644302 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 # endif4308 }4309 #endif /* VBOX_WITH_IDT_PATCHING */4310 3573 } 4311 3574 … … 4382 3645 pDevExt->pLdrImages = pImage->pNext; 4383 3646 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. */ 4385 3648 if (pDevExt->pvVMMR0 == pImage->pvImage) 4386 supdrvLdrUnset R0EP(pDevExt);3649 supdrvLdrUnsetVMMR0EPs(pDevExt); 4387 3650 4388 3651 /* check for objects with destructors in this image. (Shouldn't happen.) */ -
trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h
r14332 r14515 298 298 typedef struct SUPDRVDEVEXT *PSUPDRVDEVEXT; 299 299 300 #ifdef VBOX_WITH_IDT_PATCHING301 302 /**303 * An IDT Entry.304 */305 typedef struct SUPDRVIDTE306 {307 /** Low offset word. */308 uint32_t u16OffsetLow : 16;309 /** Segment Selector. */310 uint32_t u16SegSel : 16;311 #ifdef RT_ARCH_AMD64312 /** Interrupt Stack Table index. */313 uint32_t u3IST : 3;314 /** Reserved, ignored. */315 uint32_t u5Reserved : 5;316 #else317 /** Reserved. */318 uint32_t u5Reserved : 5;319 /** IDT Type part one (not used for task gate). */320 uint32_t u3Type1 : 3;321 #endif322 /** 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_AMD64331 /** 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 #endif336 } SUPDRVIDTE, *PSUPDRVIDTE;337 338 /** The u5Type2 value for an interrupt gate. */339 #define SUPDRV_IDTE_TYPE2_INTERRUPT_GATE 0x0e340 341 342 /**343 * Patch code.344 */345 typedef struct SUPDRVPATCH346 {347 #define SUPDRV_PATCH_CODE_SIZE 0x50348 /** 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 key356 * for the patches rather than processor number. This prevents some357 * stupid nesting stuff from happening in case of processors sharing the358 * IDT.359 * We're fucked if the processors have different physical mapping for360 * 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 SUPDRVPATCHUSAGE379 {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 390 300 391 301 /** … … 566 476 /** Load usage records. (protected by SUPDRVDEVEXT::mtxLdr) */ 567 477 PSUPDRVLDRUSAGE volatile pLdrUsage; 568 #ifdef VBOX_WITH_IDT_PATCHING569 /** Patch usage records. (protected by SUPDRVDEVEXT::SpinLock) */570 PSUPDRVPATCHUSAGE volatile pPatchUsage;571 #endif572 478 /** The VM associated with the session. */ 573 479 PVM pVM; … … 619 525 * usage counting and destruction of the IDT entry override and objects. */ 620 526 RTSPINLOCK Spinlock; 621 622 #ifdef VBOX_WITH_IDT_PATCHING623 /** List of patches. */624 PSUPDRVPATCH volatile pIdtPatches;625 /** List of patches Free. */626 PSUPDRVPATCH volatile pIdtPatchesFree;627 #endif628 527 629 528 /** List of registered objects. Protected by the spinlock. */ -
trunk/src/VBox/HostDrivers/Support/SUPLib.cpp
r14501 r14515 133 133 static PSUPQUERYFUNCS g_pFunctions; 134 134 135 #ifdef VBOX_WITH_IDT_PATCHING136 /** 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 #endif141 135 /** VMMR0 Load Address. */ 142 136 static RTR0PTR g_pvVMMR0 = NIL_RTR0PTR; … … 152 146 static int supInitFake(PSUPDRVSESSION *ppSession); 153 147 static int supLoadModule(const char *pszFilename, const char *pszModule, const char *pszSrvReqHandler, void **ppvImageBase); 154 #ifdef VBOX_WITH_IDT_PATCHING155 static int supInstallIDTE(void);156 #endif157 148 static DECLCALLBACK(int) supLoadModuleResolveImport(RTLDRMOD hLdrMod, const char *pszModule, const char *pszSymbol, unsigned uSymbol, RTUINTPTR *pValue, void *pvUser); 158 149 … … 463 454 if (ppSession) 464 455 *ppSession = g_pSession; 465 #ifdef VBOX_WITH_IDT_PATCHING466 Assert(g_u8Interrupt == 3);467 #endif468 456 469 457 /* fake the GIP. */ … … 515 503 g_u32Cookie = 0; 516 504 g_u32SessionCookie = 0; 517 #ifdef VBOX_WITH_IDT_PATCHING518 g_u8Interrupt = 3;519 #endif520 505 g_cInits = 0; 521 506 } … … 646 631 SUPR3DECL(int) SUPCallVMMR0(PVMR0 pVMR0, unsigned uOperation, void *pvArg) 647 632 { 648 #if defined(VBOX_WITH_IDT_PATCHING)649 return g_pfnCallVMMR0(pVMR0, uOperation, pvArg);650 651 #else652 633 /* 653 634 * The following operations don't belong here. … … 659 640 VERR_INTERNAL_ERROR); 660 641 return SUPCallVMMR0Ex(pVMR0, uOperation, (uintptr_t)pvArg, NULL); 661 #endif662 642 } 663 643 … … 1236 1216 #endif 1237 1217 if (RT_SUCCESS(rc)) 1238 {1239 /*1240 * Load the module.1241 * If it's VMMR0.r0 we need to install the IDTE.1242 */1243 1218 rc = supLoadModule(pszFilename, pszModule, NULL, ppvImageBase); 1244 #ifdef VBOX_WITH_IDT_PATCHING1245 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 }1254 1219 else 1255 1220 LogRel(("SUPLoadModule: Verification of \"%s\" failed, rc=%Rrc\n", rc)); … … 1271 1236 #endif 1272 1237 if (RT_SUCCESS(rc)) 1273 {1274 /*1275 * Load the module.1276 * If it's VMMR0.r0 we need to install the IDTE.1277 */1278 1238 rc = supLoadModule(pszFilename, pszModule, pszSrvReqHandler, ppvImageBase); 1279 }1280 1239 else 1281 1240 LogRel(("SUPR3LoadServiceModule: Verification of \"%s\" failed, rc=%Rrc\n", rc)); 1282 1241 return rc; 1283 1242 } 1284 1285 1286 #ifdef VBOX_WITH_IDT_PATCHING1287 /**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_AMD641309 /*1310 * reg params:1311 * <GCC> <MSC> <argument>1312 * rdi rcx pVMR01313 * esi edx uOperation1314 * rdx r8 pvArg1315 *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 #else1328 /*1329 * x86 stack:1330 * 0 saved esi1331 * 0 4 ret1332 * 4 8 pVM1333 * 8 c uOperation1334 * c 10 pvArg1335 */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 #endif1364 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 else1402 {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 else1450 Assert(g_u8Interrupt == Req.u.Out.u8Idt);1451 cCpusPatched++;1452 }1453 else1454 {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 else1476 {1477 int rc2 = RTThreadSetAffinity(u64AffMaskSaved);1478 AssertRC(rc2);1479 }1480 }1481 return rc;1482 }1483 #endif /* VBOX_WITH_IDT_PATCHING */1484 1243 1485 1244 … … 1872 1631 if (RT_UNLIKELY(g_u32FakeMode)) 1873 1632 { 1874 #ifdef VBOX_WITH_IDT_PATCHING1875 g_u8Interrupt = 3;1876 RTMemExecFree(*(void **)&g_pfnCallVMMR0);1877 g_pfnCallVMMR0 = NULL;1878 #endif1879 1633 g_pvVMMR0 = NIL_RTR0PTR; 1880 1634 return VINF_SUCCESS; 1881 1635 } 1882 1883 #ifdef VBOX_WITH_IDT_PATCHING1884 /*1885 * There is one special module. When this is freed we'll1886 * free the IDT entry that goes with it.1887 *1888 * Note that we don't keep count of VMMR0.r0 loads here, so the1889 * first unload will free it.1890 */1891 if ( (RTR0PTR)pvImageBase == g_pvVMMR01892 && 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 */1910 1636 1911 1637 /* -
trunk/src/VBox/HostDrivers/Support/testcase/Makefile.kmk
r12252 r14515 58 58 tstInt_SOURCES = tstInt.cpp 59 59 tstInt_LIBS = $(LIB_RUNTIME) 60 ifdef VBOX_WITH_IDT_PATCHING61 tstInt_DEFS += VBOX_WITH_IDT_PATCHING62 endif63 60 64 61 tstContiguous_TEMPLATE= VBOXR3TSTEXE -
trunk/src/VBox/HostDrivers/Support/testcase/tstInt.cpp
r13858 r14515 162 162 i, NanoSecs, Ticks, NanoSecs / i, Ticks / i, MinTicks); 163 163 164 #ifdef VBOX_WITH_IDT_PATCHING165 /*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 194 164 /* 195 165 * The ordinary path. -
trunk/src/VBox/VMM/Makefile.kmk
r14167 r14515 35 35 VMMR3_DEFS = IN_VMM_R3 IN_DIS IN_GMM_R3 IN_DBG 36 36 ## @todo eliminate IN_GMM_R3 37 ifdef VBOX_WITH_IDT_PATCHING38 VMMR3_DEFS += VBOX_WITH_IDT_PATCHING39 endif40 37 ifdef VBOX_WITH_PREALLOC_RAM_BY_DEFAULT 41 38 VMMR3_DEFS += VBOX_WITH_PREALLOC_RAM_BY_DEFAULT … … 302 299 PATM 303 300 VMMGC_DEFS = IN_VMM_RC IN_RT_GC IN_RT_RC IN_DIS DIS_CORE_ONLY 304 ifdef VBOX_WITH_IDT_PATCHING305 VMMGC_DEFS += VBOX_WITH_IDT_PATCHING306 endif307 301 ifdef VBOX_WITH_R0_LOGGING 308 302 VMMGC_DEFS += VBOX_WITH_R0_LOGGING … … 400 394 VMMR0_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 401 395 ## @todo eliminate IN_GVMM_R0 IN_GMM_R0 402 ifdef VBOX_WITH_IDT_PATCHING403 VMMR0_DEFS += VBOX_WITH_IDT_PATCHING404 endif405 396 ifdef VBOX_WITH_R0_LOGGING 406 397 VMMR0_DEFS += VBOX_WITH_R0_LOGGING -
trunk/src/VBox/VMM/TRPMInternal.h
r14351 r14515 240 240 DECLASM(void) trpmR0DispatchHostInterruptSimple(RTUINT uActiveVector); 241 241 242 # ifdef VBOX_WITH_IDT_PATCHING243 /**244 * Code used for the dispatching of interrupts in R0 upon return from RC.245 * @internal246 */247 DECLASM(int) trpmR0InterruptDispatcher(void);248 # endif /* VBOX_WITH_IDT_PATCHING */249 250 242 #endif /* IN_RING0 */ 251 243 -
trunk/src/VBox/VMM/VMMR0/TRPMR0.cpp
r12989 r14515 101 101 } 102 102 103 104 #ifdef VBOX_WITH_IDT_PATCHING105 # ifdef VBOX_WITH_HYBIRD_32BIT_KERNEL106 # error "VBOX_WITH_HYBIRD_32BIT_KERNEL with VBOX_WITH_IDT_PATCHING isn't supported"107 # endif108 109 /**110 * Changes the VMMR0Entry() call frame and stack used by the IDT patch code111 * so that we'll dispatch an interrupt rather than returning directly to Ring-3112 * 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 == 32124 /*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_TYPE1132 && 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 frame144 * 18 fs145 * 14 ds146 * 10 es147 * c uArg148 * 8 uOperation149 * 4 pVM150 * 0 return address (pvRet points here)151 *152 * We'll change the stackframe so that we will not return153 * to the caller but to a interrupt dispatcher. We'll also154 * setup the frame so that ds and es are moved to give room155 * 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_TYPE1175 && 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 frame193 * 20 dummy194 * 14 uArg195 * 10 uOperation196 * 8 pVM197 * 0 return address (pvRet points here)198 *199 * We'll change the stackframe so that we will not return200 * to the caller but to a interrupt dispatcher. And we'll create201 * 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 #endif209 }210 211 #endif /* VBOX_WITH_IDT_PATCHING */ -
trunk/src/VBox/VMM/VMMR0/TRPMR0A.asm
r8155 r14515 119 119 120 120 121 %ifdef VBOX_WITH_IDT_PATCHING122 123 align 16124 ;;125 ; This is the alternative return from VMMR0Entry() used when126 ; we need to dispatch an interrupt to the Host (we received it in GC).127 ;128 ; As seen in TRPMR0SetupInterruptDispatcherFrame() the stack is different129 ; than for the normal VMMR0Entry() return.130 ;131 ; 32-bit:132 ; 18 iret frame133 ; 14 retf selector (interrupt handler)134 ; 10 retf offset (interrupt handler)135 ; c es136 ; 8 fs137 ; 4 ds138 ; 0 pVM (esp here)139 ;140 ; 64-bit:141 ; 24 iret frame142 ; 18 retf selector (interrupt handler)143 ; 10 retf offset (interrupt handler)144 ; 8 uOperation145 ; 0 pVM (rsp here)146 ;147 BEGINPROC trpmR0InterruptDispatcher148 %ifdef RT_ARCH_AMD64149 lea rsp, [rsp + 10h] ; skip pVM and uOperation150 swapgs151 db 48h152 retf153 %else ; !RT_ARCH_AMD64154 add esp, byte 4 ; skip pVM155 pop ds156 pop fs157 pop es158 retf159 %endif ; !RT_ARCH_AMD64160 ENDPROC trpmR0InterruptDispatcher161 162 %endif ; VBOX_WITH_IDT_PATCHING163 164 165 121 ;; 166 122 ; Issues a software interrupt to the specified interrupt vector. -
trunk/src/VBox/VMM/VMMR0/VMMR0.cpp
r14500 r14515 475 475 476 476 /** 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. 478 480 * 479 481 * @returns VBox status code. … … 487 489 switch (enmOperation) 488 490 { 489 #ifdef VBOX_WITH_IDT_PATCHING490 /*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_STATISTICS506 vmmR0RecordRC(pVM, rc);507 #endif508 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_INTERRUPT514 || 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-bit519 * 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 # else528 # error "huh?"529 # endif530 if ( ((uintptr_t *)pvRet)[1] == (uintptr_t)pVM531 && ((uintptr_t *)pvRet)[2] == (uintptr_t)enmOperation532 && ((uintptr_t *)pvRet)[3] == (uintptr_t)pvArg)533 TRPMR0SetupInterruptDispatcherFrame(pVM, pvRet);534 else535 {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 # endif545 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 575 491 default: 576 492 /* -
trunk/src/VBox/VMM/testcase/Makefile.kmk
r14118 r14515 89 89 tstVMStructGC_TEMPLATE = VBOXGCEXE 90 90 tstVMStructGC_DEFS = IN_VMM_RC IN_DIS IN_RT_RC IN_RT_GC 91 ifdef VBOX_WITH_IDT_PATCHING92 tstVMStructGC_DEFS += VBOX_WITH_IDT_PATCHING93 endif94 91 ifdef VBOX_WITH_R0_LOGGING 95 92 tstVMStructGC_DEFS += VBOX_WITH_R0_LOGGING … … 103 100 tstVMStructSize_SOURCES = tstVMStructSize.cpp 104 101 tstVMStructSize.cpp_DEPS= $(VBOX_VMM_TESTCASE_OUT_DIR)/tstVMStructGC.h 105 ifdef VBOX_WITH_IDT_PATCHING106 tstVMStructSize_DEFS += VBOX_WITH_IDT_PATCHING107 endif108 102 ifdef VBOX_WITH_R0_LOGGING 109 103 tstVMStructSize_DEFS += VBOX_WITH_R0_LOGGING … … 116 110 tstAsmStructs_TEMPLATE = VBOXR3AUTOTST 117 111 tstAsmStructs_DEFS = IN_VMM_R3 IN_DIS 118 ifdef VBOX_WITH_IDT_PATCHING119 tstAsmStructs_DEFS += VBOX_WITH_IDT_PATCHING120 endif121 112 ifdef VBOX_WITH_R0_LOGGING 122 113 tstAsmStructs_DEFS += VBOX_WITH_R0_LOGGING … … 127 118 tstAsmStructsGC_TEMPLATE= VBOXGCEXE 128 119 tstAsmStructsGC_DEFS = IN_VMM_RC IN_DIS IN_RT_RC IN_RT_GC 129 ifdef VBOX_WITH_IDT_PATCHING130 tstAsmStructsGC_DEFS += VBOX_WITH_IDT_PATCHING131 endif132 120 ifdef VBOX_WITH_R0_LOGGING 133 121 tstAsmStructsGC_DEFS += VBOX_WITH_R0_LOGGING
Note:
See TracChangeset
for help on using the changeset viewer.