Changeset 2201 in vbox for trunk/src/VBox/VMM/VMMGC/IOMGC.cpp
- Timestamp:
- Apr 19, 2007 8:54:41 AM (18 years ago)
- svn:sync-xref-src-repo-rev:
- 20546
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMGC/IOMGC.cpp
r2116 r2201 420 420 } 421 421 422 423 /**424 * [REP*] INSB/INSW/INSD425 * ES:EDI,DX[,ECX]426 *427 * @returns VBox status code.428 *429 * @param pVM The virtual machine (GC pointer ofcourse).430 * @param pRegFrame Pointer to CPUMCTXCORE guest registers structure.431 * @param pCpu Disassembler CPU state.432 */433 IOMDECL(int) IOMInterpretINS(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu)434 {435 #ifdef VBOX_WITH_STATISTICS436 STAM_COUNTER_INC(&pVM->iom.s.StatGCInstIns);437 #endif438 439 /*440 * We do not support REPNE, 16-bit addressing or decrementing destination441 * pointer. Segment prefixes are deliberately ignored, as per the instruction specification.442 */443 if ( pCpu->prefix & PREFIX_REPNE444 || (pCpu->addrmode != CPUMODE_32BIT)445 || pRegFrame->eflags.Bits.u1DF)446 return VINF_IOM_HC_IOPORT_READ;447 448 /*449 * Get port number directly from the register (no need to bother the450 * disassembler). And get the I/O register size from the opcode / prefix.451 */452 uint32_t uPort = pRegFrame->edx & 0xffff;453 unsigned cbSize = 0;454 if (pCpu->pCurInstr->opcode == OP_INSB)455 cbSize = 1;456 else457 cbSize = pCpu->opmode == CPUMODE_32BIT ? 4 : 2;458 459 int rc = IOMInterpretCheckPortIOAccess(pVM, pRegFrame, uPort, cbSize);460 if (rc == VINF_SUCCESS)461 {462 /*463 * Get bytes/words/dwords count to transfer.464 */465 RTGCUINTREG cTransfers = 1;466 if (pCpu->prefix & PREFIX_REP)467 {468 cTransfers = pRegFrame->ecx;469 if (!cTransfers)470 return VINF_SUCCESS;471 }472 473 /* Convert destination address es:edi. */474 RTGCPTR GCPtrDst;475 rc = SELMToFlatEx(pVM, pRegFrame->eflags, pRegFrame->es, (RTGCPTR)pRegFrame->edi, &pRegFrame->esHid,476 SELMTOFLAT_FLAGS_HYPER | SELMTOFLAT_FLAGS_NO_PL,477 &GCPtrDst, NULL);478 if (VBOX_FAILURE(rc))479 {480 Log(("INS destination address conversion failed -> fallback, rc=%d\n", rc));481 return VINF_IOM_HC_IOPORT_READ;482 }483 484 /* Access verification first; we can't recover from traps inside this instruction, as the port read cannot be repeated. */485 uint32_t cpl = CPUMGetGuestCPL(pVM, pRegFrame);486 487 rc = PGMVerifyAccess(pVM, (RTGCUINTPTR)GCPtrDst, cTransfers * cbSize,488 X86_PTE_RW | ((cpl == 3) ? X86_PTE_US : 0));489 if (rc != VINF_SUCCESS)490 {491 Log(("INS will generate a trap -> fallback, rc=%d\n", rc));492 return VINF_IOM_HC_IOPORT_READ;493 }494 495 Log(("IOMGC: rep ins%d port %#x count %d\n", cbSize * 8, uPort, cTransfers));496 MMGCRamRegisterTrapHandler(pVM);497 498 /* If the device supports string transfers, ask it to do as499 * much as it wants. The rest is done with single-word transfers. */500 const RTGCUINTREG cTransfersOrg = cTransfers;501 rc = IOMIOPortReadString(pVM, uPort, &GCPtrDst, &cTransfers, cbSize);502 AssertRC(rc); Assert(cTransfers <= cTransfersOrg);503 pRegFrame->edi += (cTransfersOrg - cTransfers) * cbSize;504 505 while (cTransfers && rc == VINF_SUCCESS)506 {507 uint32_t u32Value;508 rc = IOMIOPortRead(pVM, uPort, &u32Value, cbSize);509 if (rc == VINF_IOM_HC_IOPORT_READ || VBOX_FAILURE(rc))510 break;511 int rc2 = MMGCRamWriteNoTrapHandler(GCPtrDst, &u32Value, cbSize);512 Assert(rc2 == VINF_SUCCESS); NOREF(rc2);513 GCPtrDst = (RTGCPTR)((RTGCUINTPTR)GCPtrDst + cbSize);514 pRegFrame->edi += cbSize;515 cTransfers--;516 }517 MMGCRamDeregisterTrapHandler(pVM);518 519 /* Update ecx on exit. */520 if (pCpu->prefix & PREFIX_REP)521 pRegFrame->ecx = cTransfers;522 }523 return rc;524 }525 526 527 /**528 * [REP*] OUTSB/OUTSW/OUTSD529 * DS:ESI,DX[,ECX]530 *531 * @returns VBox status code.532 *533 * @param pVM The virtual machine (GC pointer ofcourse).534 * @param pRegFrame Pointer to CPUMCTXCORE guest registers structure.535 * @param pCpu Disassembler CPU state.536 */537 IOMDECL(int) IOMInterpretOUTS(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu)538 {539 #ifdef VBOX_WITH_STATISTICS540 STAM_COUNTER_INC(&pVM->iom.s.StatGCInstOuts);541 #endif542 543 /*544 * We do not support segment prefixes, REPNE, 16-bit addressing or545 * decrementing source pointer.546 */547 if ( pCpu->prefix & (PREFIX_SEG | PREFIX_REPNE)548 || (pCpu->addrmode != CPUMODE_32BIT)549 || pRegFrame->eflags.Bits.u1DF)550 return VINF_IOM_HC_IOPORT_WRITE;551 552 /*553 * Get port number from the first parameter.554 * And get the I/O register size from the opcode / prefix.555 */556 uint32_t uPort = 0;557 unsigned cbSize = 0;558 bool fRc = iomGCGetRegImmData(pCpu, &pCpu->param1, pRegFrame, &uPort, &cbSize);559 AssertMsg(fRc, ("Failed to get reg/imm port number!\n")); NOREF(fRc);560 if (pCpu->pCurInstr->opcode == OP_OUTSB)561 cbSize = 1;562 else563 cbSize = pCpu->opmode == CPUMODE_32BIT ? 4 : 2;564 565 int rc = IOMInterpretCheckPortIOAccess(pVM, pRegFrame, uPort, cbSize);566 if (rc == VINF_SUCCESS)567 {568 /*569 * Get bytes/words/dwords count to transfer.570 */571 RTGCUINTREG cTransfers = 1;572 if (pCpu->prefix & PREFIX_REP)573 {574 cTransfers = pRegFrame->ecx;575 if (!cTransfers)576 return VINF_SUCCESS;577 }578 579 /* Convert source address ds:esi. */580 RTGCPTR GCPtrSrc;581 rc = SELMToFlatEx(pVM, pRegFrame->eflags, pRegFrame->ds, (RTGCPTR)pRegFrame->esi, &pRegFrame->dsHid,582 SELMTOFLAT_FLAGS_HYPER | SELMTOFLAT_FLAGS_NO_PL,583 &GCPtrSrc, NULL);584 if (VBOX_FAILURE(rc))585 {586 Log(("OUTS source address conversion failed -> fallback, rc=%d\n", rc));587 return VINF_IOM_HC_IOPORT_WRITE;588 }589 590 /* Access verification first; we currently can't recover properly from traps inside this instruction */591 uint32_t cpl = CPUMGetGuestCPL(pVM, pRegFrame);592 rc = PGMVerifyAccess(pVM, (RTGCUINTPTR)GCPtrSrc, cTransfers * cbSize,593 (cpl == 3) ? X86_PTE_US : 0);594 if (rc != VINF_SUCCESS)595 {596 Log(("OUTS will generate a trap -> fallback, rc=%d\n", rc));597 return VINF_IOM_HC_IOPORT_WRITE;598 }599 600 Log(("IOMGC: rep outs%d port %#x count %d\n", cbSize * 8, uPort, cTransfers));601 MMGCRamRegisterTrapHandler(pVM);602 603 /*604 * If the device supports string transfers, ask it to do as605 * much as it wants. The rest is done with single-word transfers.606 */607 const RTGCUINTREG cTransfersOrg = cTransfers;608 rc = IOMIOPortWriteString(pVM, uPort, &GCPtrSrc, &cTransfers, cbSize);609 AssertRC(rc); Assert(cTransfers <= cTransfersOrg);610 pRegFrame->esi += (cTransfersOrg - cTransfers) * cbSize;611 612 while (cTransfers && rc == VINF_SUCCESS)613 {614 uint32_t u32Value;615 rc = MMGCRamReadNoTrapHandler(&u32Value, GCPtrSrc, cbSize);616 if (rc != VINF_SUCCESS)617 break;618 rc = IOMIOPortWrite(pVM, uPort, u32Value, cbSize);619 if (rc == VINF_IOM_HC_IOPORT_WRITE)620 break;621 GCPtrSrc = (RTGCPTR)((RTUINTPTR)GCPtrSrc + cbSize);622 pRegFrame->esi += cbSize;623 cTransfers--;624 }625 626 MMGCRamDeregisterTrapHandler(pVM);627 628 /* Update ecx on exit. */629 if (pCpu->prefix & PREFIX_REP)630 pRegFrame->ecx = cTransfers;631 }632 return rc;633 }634 635 636 422 /** 637 423 * Attempts to service an IN/OUT instruction.
Note:
See TracChangeset
for help on using the changeset viewer.