Changeset 41766 in vbox for trunk/src/VBox/VMM
- Timestamp:
- Jun 15, 2012 6:36:19 PM (13 years ago)
- svn:sync-xref-src-repo-rev:
- 78583
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/EMAll.cpp
r41760 r41766 66 66 #endif 67 67 68 /** Used to pass information during instruction disassembly. */69 typedef struct70 {71 PVM pVM;72 PVMCPU pVCpu;73 RTGCPTR GCPtr;74 uint8_t aOpcode[8];75 } EMDISSTATE, *PEMDISSTATE;76 68 77 69 /******************************************************************************* … … 286 278 static DECLCALLBACK(int) emReadBytes(PDISCPUSTATE pDis, uint8_t offInstr, uint8_t cbMinRead, uint8_t cbMaxRead) 287 279 { 288 PEMDISSTATE pState = (PEMDISSTATE)pDis->pvUser; 289 # ifndef IN_RING0 290 PVM pVM = pState->pVM; 280 PVMCPU pVCpu = (PVMCPU)pDis->pvUser; 281 #if defined(IN_RC) || defined(IN_RING3) 282 PVM pVM = pVCpu->CTX_SUFF(pVM); 283 #endif 284 RTUINTPTR uSrcAddr = pDis->uInstrAddr + offInstr; 285 int rc; 286 287 /* 288 * Figure how much we can or must read. 289 */ 290 size_t cbToRead = PAGE_SIZE - (uSrcAddr & PAGE_OFFSET_MASK); 291 if (cbToRead > cbMaxRead) 292 cbToRead = cbMaxRead; 293 else if (cbToRead < cbMinRead) 294 cbToRead = cbMinRead; 295 296 #if defined(IN_RC) || defined(IN_RING3) 297 /* 298 * We might be called upon to interpret an instruction in a patch. 299 */ 300 if (PATMIsPatchGCAddr(pVCpu->CTX_SUFF(pVM), uSrcAddr)) 301 { 302 # ifdef IN_RC 303 memcpy(&pDis->abInstr[offInstr], (void *)(uintptr_t)uSrcAddr, cbToRead); 304 # else 305 memcpy(&pDis->abInstr[offInstr], PATMR3GCPtrToHCPtr(pVCpu->CTX_SUFF(pVM), uSrcAddr), cbToRead); 291 306 # endif 292 PVMCPU pVCpu = pState->pVCpu; 293 /** @todo Rewrite this to make full use of the abInstr buffer and drop our extra 294 * caching buffer. Just playing safe at first... */ 295 uint8_t *pbDst = &pDis->abInstr[offInstr]; 296 RTUINTPTR uSrcAddr = pDis->uInstrAddr + offInstr; 297 size_t cbToRead = cbMinRead; 298 299 # ifdef IN_RING0 300 int rc; 301 302 if ( pState->GCPtr 303 && uSrcAddr + cbToRead <= pState->GCPtr + sizeof(pState->aOpcode)) 304 { 305 unsigned offset = uSrcAddr - pState->GCPtr; 306 Assert(uSrcAddr >= pState->GCPtr); 307 308 for (unsigned i = 0; i < cbToRead; i++) 309 pbDst[i] = pState->aOpcode[offset + i]; 310 pDis->cbCachedInstr = offInstr + cbToRead; 311 return VINF_SUCCESS; 312 } 313 314 rc = PGMPhysSimpleReadGCPtr(pVCpu, pbDst, uSrcAddr, cbToRead); 315 AssertMsgRC(rc, ("PGMPhysSimpleReadGCPtr failed for uSrcAddr=%RTptr cbToRead=%x rc=%d\n", uSrcAddr, cbToRead, rc)); 316 317 # elif defined(IN_RING3) 318 if (!PATMIsPatchGCAddr(pVM, uSrcAddr)) 319 { 320 int rc = PGMPhysSimpleReadGCPtr(pVCpu, pbDst, uSrcAddr, cbToRead); 321 AssertRC(rc); 307 rc = VINF_SUCCESS; 322 308 } 323 309 else 324 memcpy(pbDst, PATMR3GCPtrToHCPtr(pVM, uSrcAddr), cbToRead); 325 326 # elif defined(IN_RC) 327 if (!PATMIsPatchGCAddr(pVM, uSrcAddr)) 328 { 329 int rc = MMGCRamRead(pVM, pbDst, (void *)(uintptr_t)uSrcAddr, cbToRead); 310 #endif 311 { 312 # ifdef IN_RC 313 /* 314 * Try access it thru the shadow page tables first. Fall back on the 315 * slower PGM method if it fails because the TLB or page table was 316 * modified recently. 317 */ 318 rc = MMGCRamRead(pVCpu->pVMRC, &pDis->abInstr[offInstr], (void *)(uintptr_t)uSrcAddr, cbToRead); 319 if (rc == VERR_ACCESS_DENIED && cbToRead > cbMinRead) 320 { 321 cbToRead = cbMinRead; 322 rc = MMGCRamRead(pVCpu->pVMRC, &pDis->abInstr[offInstr], (void *)(uintptr_t)uSrcAddr, cbToRead); 323 } 330 324 if (rc == VERR_ACCESS_DENIED) 325 #endif 331 326 { 332 /* Recently flushed; access the data manually. */ 333 rc = PGMPhysSimpleReadGCPtr(pVCpu, pbDst, uSrcAddr, cbToRead); 334 AssertRC(rc); 327 rc = PGMPhysSimpleReadGCPtr(pVCpu, &pDis->abInstr[offInstr], uSrcAddr, cbToRead); 328 if (RT_FAILURE(rc)) 329 { 330 if (cbToRead > cbMinRead) 331 { 332 cbToRead = cbMinRead; 333 rc = PGMPhysSimpleReadGCPtr(pVCpu, &pDis->abInstr[offInstr], uSrcAddr, cbToRead); 334 } 335 if (RT_FAILURE(rc)) 336 { 337 #ifndef IN_RC 338 /* 339 * If we fail to find the page via the guest's page tables 340 * we invalidate the page in the host TLB (pertaining to 341 * the guest in the NestedPaging case). See #6043. 342 */ 343 if (rc == VERR_PAGE_TABLE_NOT_PRESENT || rc == VERR_PAGE_NOT_PRESENT) 344 { 345 HWACCMInvalidatePage(pVCpu, uSrcAddr); 346 if (((uSrcAddr + cbToRead - 1) >> PAGE_SHIFT) != (uSrcAddr >> PAGE_SHIFT)) 347 HWACCMInvalidatePage(pVCpu, uSrcAddr + cbToRead - 1); 348 } 349 #endif 350 } 351 } 335 352 } 336 353 } 337 else /* the hypervisor region is always present. */ 338 memcpy(pbDst, (RTRCPTR)(uintptr_t)uSrcAddr, cbToRead); 339 340 # endif /* IN_RING3 */ 354 341 355 pDis->cbCachedInstr = offInstr + cbToRead; 342 return VINF_SUCCESS; 343 } 344 345 #ifndef IN_RC 356 return rc; 357 } 358 346 359 347 360 DECLINLINE(int) emDisCoreOne(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, RTGCUINTPTR InstrGC, uint32_t *pOpsize) 348 361 { 349 EMDISSTATE State; 350 351 State.pVM = pVM; 352 State.pVCpu = pVCpu; 353 int rc = PGMPhysSimpleReadGCPtr(pVCpu, &State.aOpcode, InstrGC, sizeof(State.aOpcode)); 354 if (RT_SUCCESS(rc)) 355 { 356 State.GCPtr = InstrGC; 357 } 358 else 359 { 360 if (PAGE_ADDRESS(InstrGC) == PAGE_ADDRESS(InstrGC + sizeof(State.aOpcode) - 1)) 361 { 362 /* 363 * If we fail to find the page via the guest's page tables we invalidate the page 364 * in the host TLB (pertaining to the guest in the NestedPaging case). See #6043 365 */ 366 if (rc == VERR_PAGE_TABLE_NOT_PRESENT || rc == VERR_PAGE_NOT_PRESENT) 367 HWACCMInvalidatePage(pVCpu, InstrGC); 368 369 Log(("emDisCoreOne: read failed with %d\n", rc)); 370 return rc; 371 } 372 State.GCPtr = NIL_RTGCPTR; 373 } 374 return DISInstrWithReader(InstrGC, (DISCPUMODE)pDis->uCpuMode, emReadBytes, &State, pDis, pOpsize); 375 } 376 377 #else /* IN_RC */ 378 379 DECLINLINE(int) emDisCoreOne(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, RTGCUINTPTR InstrGC, uint32_t *pOpsize) 380 { 381 EMDISSTATE State; 382 383 State.pVM = pVM; 384 State.pVCpu = pVCpu; 385 State.GCPtr = InstrGC; 386 387 return DISInstrWithReader(InstrGC, (DISCPUMODE)pDis->uCpuMode, emReadBytes, &State, pDis, pOpsize); 388 } 389 390 #endif /* IN_RC */ 362 return DISInstrWithReader(InstrGC, (DISCPUMODE)pDis->uCpuMode, emReadBytes, pVCpu, pDis, pOpsize); 363 } 391 364 392 365 … … 435 408 VMMDECL(int) EMInterpretDisasOneEx(PVM pVM, PVMCPU pVCpu, RTGCUINTPTR GCPtrInstr, PCCPUMCTXCORE pCtxCore, PDISCPUSTATE pDis, unsigned *pcbInstr) 436 409 { 437 int rc;438 EMDISSTATE State;439 440 State.pVM = pVM;441 State.pVCpu = pVCpu;442 443 #ifdef IN_RC444 State.GCPtr = GCPtrInstr;445 #else /* ring 0/3 */446 rc = PGMPhysSimpleReadGCPtr(pVCpu, &State.aOpcode, GCPtrInstr, sizeof(State.aOpcode));447 if (RT_SUCCESS(rc))448 {449 State.GCPtr = GCPtrInstr;450 }451 else452 {453 if (PAGE_ADDRESS(GCPtrInstr) == PAGE_ADDRESS(GCPtrInstr + sizeof(State.aOpcode) - 1))454 {455 /*456 * If we fail to find the page via the guest's page tables we invalidate the page457 * in the host TLB (pertaining to the guest in the NestedPaging case). See #6043458 */459 if (rc == VERR_PAGE_TABLE_NOT_PRESENT || rc == VERR_PAGE_NOT_PRESENT)460 HWACCMInvalidatePage(pVCpu, GCPtrInstr);461 462 Log(("EMInterpretDisasOneEx: read failed with %d\n", rc));463 return rc;464 }465 State.GCPtr = NIL_RTGCPTR;466 }467 #endif468 469 410 DISCPUMODE enmCpuMode = SELMGetCpuModeFromSelector(pVCpu, pCtxCore->eflags, pCtxCore->cs, (PCPUMSELREGHID)&pCtxCore->csHid); 470 rc = DISInstrWithReader(GCPtrInstr, enmCpuMode, emReadBytes, &State, pDis, pcbInstr);411 int rc = DISInstrWithReader(GCPtrInstr, enmCpuMode, emReadBytes, pVCpu, pDis, pcbInstr); 471 412 if (RT_SUCCESS(rc)) 472 413 return VINF_SUCCESS; -
trunk/src/VBox/VMM/VMMRC/MMRamRC.cpp
r39402 r41766 79 79 * @param pDst Where to store the read data. 80 80 * @param pSrc Pointer to the data to read. 81 * @param cb Size of data to read , only 1/2/4/8 is valid.81 * @param cb Size of data to read. 82 82 */ 83 83 VMMRCDECL(int) MMGCRamRead(PVM pVM, void *pDst, void *pSrc, size_t cb) … … 86 86 PVMCPU pVCpu = VMMGetCpu0(pVM); 87 87 88 TRPMSaveTrap(pVCpu); /* save the current trap info, because it will get trashed if our access failed. */ 88 /* 89 * Save the current trap info, because it will get trashed if our access failed. 90 */ 91 TRPMSaveTrap(pVCpu); 89 92 93 /* 94 * Need to serve the request in a silly loop because the assembly code wasn't 95 * written for abrbitrary sizes, only 1/2/4/8. 96 */ 90 97 MMGCRamRegisterTrapHandler(pVM); 91 rc = MMGCRamReadNoTrapHandler(pDst, pSrc, cb); 98 for (;;) 99 { 100 size_t cbThisRead; 101 switch (cb) 102 { 103 case 1: cbThisRead = 1; break; 104 case 2: cbThisRead = 2; break; 105 case 3: cbThisRead = 2; break; 106 case 4: cbThisRead = 4; break; 107 case 5: cbThisRead = 4; break; 108 case 6: cbThisRead = 4; break; 109 case 7: cbThisRead = 4; break; 110 default: 111 case 8: cbThisRead = 8; break; 112 } 113 rc = MMGCRamReadNoTrapHandler(pDst, pSrc, cbThisRead); 114 if (RT_FAILURE(rc) || cbThisRead == cb) 115 break; 116 117 /* advance */ 118 cb -= cbThisRead; 119 pDst = (uint8_t *)pDst + cbThisRead; 120 pSrc = (uint8_t *)pSrc + cbThisRead; 121 } 92 122 MMGCRamDeregisterTrapHandler(pVM); 123 93 124 if (RT_FAILURE(rc)) 94 125 TRPMRestoreTrap(pVCpu);
Note:
See TracChangeset
for help on using the changeset viewer.