- Timestamp:
- Jun 17, 2016 7:39:35 AM (9 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/PC/DevIOAPIC_New.cpp
r61685 r61735 93 93 #define IOAPIC_RTE_VECTOR UINT64_C(0xff) 94 94 /** Redirection table entry - Delivery mode. */ 95 #define IOAPIC_RTE_DELIVERY_MODE (RT_BIT (8) | RT_BIT(9) | RT_BIT(10))95 #define IOAPIC_RTE_DELIVERY_MODE (RT_BIT_64(8) | RT_BIT_64(9) | RT_BIT_64(10)) 96 96 /** Redirection table entry - Destination mode. */ 97 #define IOAPIC_RTE_DEST_MODE RT_BIT (11)97 #define IOAPIC_RTE_DEST_MODE RT_BIT_64(11) 98 98 /** Redirection table entry - Delivery status. */ 99 #define IOAPIC_RTE_DELIVERY_STATUS RT_BIT (12)99 #define IOAPIC_RTE_DELIVERY_STATUS RT_BIT_64(12) 100 100 /** Redirection table entry - Interrupt input pin polarity. */ 101 #define IOAPIC_RTE_POLARITY RT_BIT (13)101 #define IOAPIC_RTE_POLARITY RT_BIT_64(13) 102 102 /** Redirection table entry - Remote IRR. */ 103 #define IOAPIC_RTE_REMOTE_IRR RT_BIT (14)103 #define IOAPIC_RTE_REMOTE_IRR RT_BIT_64(14) 104 104 /** Redirection table entry - Trigger Mode. */ 105 #define IOAPIC_RTE_TRIGGER_MODE RT_BIT (15)105 #define IOAPIC_RTE_TRIGGER_MODE RT_BIT_64(15) 106 106 /** Redirection table entry - the mask bit number. */ 107 107 #define IOAPIC_RTE_MASK_BIT 16 108 108 /** Redirection table entry - the mask. */ 109 #define IOAPIC_RTE_MASK RT_BIT (IOAPIC_RTE_MASK_BIT)109 #define IOAPIC_RTE_MASK RT_BIT_64(IOAPIC_RTE_MASK_BIT) 110 110 /** Redirection table entry - Extended Destination ID. */ 111 111 #define IOAPIC_RTE_EXT_DEST_ID UINT64_C(0x00ff000000000000) … … 176 176 #endif 177 177 178 /** @def IOAPIC_LOCK179 * Acquires the PDM lock. */180 #define IOAPIC_LOCK(pThis, rcBusy) \181 do { \182 int rcLock = (pThis)->CTX_SUFF(pIoApicHlp)->pfnLock((pThis)->CTX_SUFF(pDevIns), rcBusy); \183 if (rcLock != VINF_SUCCESS) \184 return rcLock; \185 } while (0)186 187 /** @def IOAPIC_LOCK_VOID188 * Acquires the PDM lock assumes success. */189 #define IOAPIC_LOCK_VOID(pThis) \190 do { \191 int rcLock = (pThis)->CTX_SUFF(pIoApicHlp)->pfnLock((pThis)->CTX_SUFF(pDevIns), VERR_INTERNAL_ERROR_2); \192 Assert(rcLock == VINF_SUCCESS); \193 } while (0)194 195 /** @def IOAPIC_UNLOCK196 * Releases the PDM lock. */197 #define IOAPIC_UNLOCK(pThis) (pThis)->CTX_SUFF(pIoApicHlp)->pfnUnlock((pThis)->CTX_SUFF(pDevIns))198 199 178 200 179 /********************************************************************************************************************************* 201 180 * Structures and Typedefs * 202 181 *********************************************************************************************************************************/ 203 /**204 * The I/O Redirection Table Entry (RTE).205 */206 typedef union RTE207 {208 /** Unsigned integer view. */209 uint64_t volatile u;210 /** 64 bit unsigned integer view. */211 uint64_t volatile au64[1];212 /** 32 bit unsigned integer view. */213 uint32_t volatile au32[2];214 } RTE;215 AssertCompileSize(RTE, sizeof(uint64_t));216 217 182 /** 218 183 * The per-VM I/O APIC device state. … … 245 210 246 211 /** The redirection table registers. */ 247 RTEau64RedirTable[IOAPIC_NUM_INTR_PINS];212 uint64_t au64RedirTable[IOAPIC_NUM_INTR_PINS]; 248 213 /** The IRQ tags and source IDs for each pin (tracing purposes). */ 249 214 uint32_t au32TagSrc[IOAPIC_NUM_INTR_PINS]; … … 252 217 uint32_t u32Padding2; 253 218 /** The internal IRR reflecting state of the interrupt lines. */ 254 uint32_t volatile uIrr; 219 uint32_t uIrr; 220 221 /** The critsect for updating to the RTEs. */ 222 PDMCRITSECT CritSect; 255 223 256 224 #ifdef VBOX_WITH_STATISTICS … … 289 257 /** Number of suppressed level-triggered interrupts (by remote IRR). */ 290 258 STAMCOUNTER StatSuppressedLevelIntr; 259 /** Number of returns to ring-3 due to EOI broadcast lock contention. */ 260 STAMCOUNTER StatEoiContention; 261 /** Number of returns to ring-3 due to Set RTE lock contention. */ 262 STAMCOUNTER StatSetRteContention; 291 263 #endif 292 264 } IOAPIC; … … 392 364 static void ioapicSignalIntrForRte(PIOAPIC pThis, uint8_t idxRte) 393 365 { 366 Assert(PDMCritSectIsOwner(&pThis->CritSect)); 367 394 368 /* Ensure the RTE isn't masked. */ 395 uint64_t const u64Rte = pThis->au64RedirTable[idxRte] .u;369 uint64_t const u64Rte = pThis->au64RedirTable[idxRte]; 396 370 if (!IOAPIC_RTE_IS_MASKED(u64Rte)) 397 371 { … … 445 419 { 446 420 Assert(u8TriggerMode == IOAPIC_RTE_TRIGGER_MODE_LEVEL); 447 ASMAtomicOrU32(&pThis->au64RedirTable[idxRte].au32[0], IOAPIC_RTE_REMOTE_IRR);421 pThis->au64RedirTable[idxRte] |= IOAPIC_RTE_REMOTE_IRR; 448 422 } 449 423 } … … 463 437 uint32_t uValue; 464 438 if (!(uIndex & 1)) 465 uValue = pThis->au64RedirTable[idxRte].au32[0]& RT_LO_U32(IOAPIC_RTE_VALID_READ_MASK);439 uValue = RT_LO_U32(pThis->au64RedirTable[idxRte]) & RT_LO_U32(IOAPIC_RTE_VALID_READ_MASK); 466 440 else 467 uValue = pThis->au64RedirTable[idxRte].au32[1]& RT_HI_U32(IOAPIC_RTE_VALID_READ_MASK);441 uValue = RT_HI_U32(pThis->au64RedirTable[idxRte]) & RT_HI_U32(IOAPIC_RTE_VALID_READ_MASK); 468 442 469 443 LogFlow(("IOAPIC: ioapicGetRedirTableEntry: uIndex=%#RX32 idxRte=%u returns %#RX32\n", uIndex, idxRte, uValue)); … … 479 453 * @param uValue The value to set. 480 454 */ 481 static voidioapicSetRedirTableEntry(PIOAPIC pThis, uint32_t uIndex, uint32_t uValue)455 static int ioapicSetRedirTableEntry(PIOAPIC pThis, uint32_t uIndex, uint32_t uValue) 482 456 { 483 457 uint8_t const idxRte = (uIndex - IOAPIC_INDIRECT_INDEX_REDIR_TBL_START) >> 1; … … 485 459 RT_ELEMENTS(pThis->au64RedirTable))); 486 460 487 /* 488 * Write the low or high 32-bit value into the specified 64-bit RTE register. 489 * Update only the valid, writable bits. 490 */ 491 uint64_t const u64Rte = pThis->au64RedirTable[idxRte].u; 492 if (!(uIndex & 1)) 493 { 494 uint32_t const u32RteNewLo = uValue & RT_LO_U32(IOAPIC_RTE_VALID_WRITE_MASK); 495 ASMAtomicWriteU32(&pThis->au64RedirTable[idxRte].au32[0], u32RteNewLo); 461 int rc = PDMCritSectEnter(&pThis->CritSect, VINF_IOM_R3_MMIO_WRITE); 462 if (rc == VINF_SUCCESS) 463 { 464 /* 465 * Write the low or high 32-bit value into the specified 64-bit RTE register. 466 * Update only the valid, writable bits. 467 */ 468 uint64_t const u64Rte = pThis->au64RedirTable[idxRte]; 469 if (!(uIndex & 1)) 470 { 471 uint32_t const u32RteNewLo = uValue & RT_LO_U32(IOAPIC_RTE_VALID_WRITE_MASK); 472 uint64_t const u64RteHi = u64Rte & UINT64_C(0xffffffff00000000); 473 pThis->au64RedirTable[idxRte] = u64RteHi | u32RteNewLo; 474 } 475 else 476 { 477 uint32_t const u32RteLo = RT_LO_U32(u64Rte); 478 uint64_t const u64RteNewHi = (uint64_t)(uValue & RT_HI_U32(IOAPIC_RTE_VALID_WRITE_MASK)) << 32; 479 pThis->au64RedirTable[idxRte] = u64RteNewHi | u32RteLo; 480 } 481 482 /* 483 * Signal the next pending interrupt for this RTE. 484 */ 485 uint32_t const uPinMask = UINT32_C(1) << idxRte; 486 if (pThis->uIrr & uPinMask) 487 ioapicSignalIntrForRte(pThis, idxRte); 488 489 PDMCritSectLeave(&pThis->CritSect); 490 LogFlow(("IOAPIC: ioapicSetRedirTableEntry: uIndex=%#RX32 idxRte=%u uValue=%#RX32\n", uIndex, idxRte, uValue)); 496 491 } 497 492 else 498 { 499 uint32_t const u32RteNewHi = uValue & RT_HI_U32(IOAPIC_RTE_VALID_WRITE_MASK); 500 ASMAtomicWriteU32(&pThis->au64RedirTable[idxRte].au32[1], u32RteNewHi); 501 } 502 503 /* 504 * Signal the next pending interrupt for this RTE. 505 */ 506 uint32_t const uPinMask = UINT32_C(1) << idxRte; 507 if (pThis->uIrr & uPinMask) 508 ioapicSignalIntrForRte(pThis, idxRte); 509 510 LogFlow(("IOAPIC: ioapicSetRedirTableEntry: uIndex=%#RX32 idxRte=%u uValue=%#RX32\n", uIndex, idxRte, uValue)); 493 STAM_COUNTER_INC(&pThis->StatSetRteContention); 494 495 return rc; 511 496 } 512 497 … … 521 506 { 522 507 uint8_t const uIndex = pThis->u8Index; 523 uint32_t uValue;524 508 if ( uIndex >= IOAPIC_INDIRECT_INDEX_REDIR_TBL_START 525 509 && uIndex <= IOAPIC_INDIRECT_INDEX_REDIR_TBL_END) 526 uValue =ioapicGetRedirTableEntry(pThis, uIndex);527 else 528 {529 530 531 532 533 534 535 536 537 510 return ioapicGetRedirTableEntry(pThis, uIndex); 511 512 uint32_t uValue; 513 switch (uIndex) 514 { 515 case IOAPIC_INDIRECT_INDEX_ID: 516 uValue = ioapicGetId(pThis); 517 break; 518 519 case IOAPIC_INDIRECT_INDEX_VERSION: 520 uValue = ioapicGetVersion(); 521 break; 538 522 539 523 #if IOAPIC_HARDWARE_VERSION == IOAPIC_HARDWARE_VERSION_82093AA 540 541 542 524 case IOAPIC_INDIRECT_INDEX_ARB: 525 uValue = ioapicGetArb(); 526 break; 543 527 #endif 544 528 545 default: 546 Log2(("IOAPIC: Attempt to read register at invalid index %#x\n", uIndex)); 547 uValue = UINT32_C(0xffffffff); 548 break; 549 } 550 } 551 529 default: 530 uValue = UINT32_C(0xffffffff); 531 Log2(("IOAPIC: Attempt to read register at invalid index %#x\n", uIndex)); 532 break; 533 } 552 534 return uValue; 553 535 } … … 560 542 * @param uValue The value to set. 561 543 */ 562 static voidioapicSetData(PIOAPIC pThis, uint32_t uValue)544 static int ioapicSetData(PIOAPIC pThis, uint32_t uValue) 563 545 { 564 546 uint8_t const uIndex = pThis->u8Index; 565 547 LogFlow(("IOAPIC: ioapicSetData: uIndex=%#x uValue=%#RX32\n", uIndex, uValue)); 566 548 549 if ( uIndex >= IOAPIC_INDIRECT_INDEX_REDIR_TBL_START 550 && uIndex <= IOAPIC_INDIRECT_INDEX_REDIR_TBL_END) 551 return ioapicSetRedirTableEntry(pThis, uIndex, uValue); 552 567 553 if (uIndex == IOAPIC_INDIRECT_INDEX_ID) 568 554 ioapicSetId(pThis, uValue); 569 else if ( uIndex >= IOAPIC_INDIRECT_INDEX_REDIR_TBL_START570 && uIndex <= IOAPIC_INDIRECT_INDEX_REDIR_TBL_END)571 ioapicSetRedirTableEntry(pThis, uIndex, uValue);572 555 else 573 556 Log2(("IOAPIC: ioapicSetData: Invalid index %#RX32, ignoring write request with uValue=%#RX32\n", uIndex, uValue)); 557 558 return VINF_SUCCESS; 574 559 } 575 560 … … 578 563 * @interface_method_impl{PDMIOAPICREG,pfnSetEoiR3} 579 564 */ 580 PDMBOTHCBDECL( void) ioapicSetEoi(PPDMDEVINS pDevIns, uint8_t u8Vector)565 PDMBOTHCBDECL(int) ioapicSetEoi(PPDMDEVINS pDevIns, uint8_t u8Vector) 581 566 { 582 567 PIOAPIC pThis = PDMINS_2_DATA(pDevIns, PIOAPIC); … … 584 569 LogFlow(("IOAPIC: ioapicSetEoi: u8Vector=%#x (%u)\n", u8Vector, u8Vector)); 585 570 586 for (uint8_t idxRte = 0; idxRte < RT_ELEMENTS(pThis->au64RedirTable); idxRte++)587 {588 uint64_t const u64Rte = pThis->au64RedirTable[idxRte].u;589 if (IOAPIC_RTE_GET_VECTOR(u64Rte) == u8Vector)571 int rc = PDMCritSectEnter(&pThis->CritSect, VINF_IOM_R3_MMIO_WRITE); 572 if (rc == VINF_SUCCESS) 573 { 574 for (uint8_t idxRte = 0; idxRte < RT_ELEMENTS(pThis->au64RedirTable); idxRte++) 590 575 { 591 ASMAtomicAndU32(&pThis->au64RedirTable[idxRte].au32[0], ~IOAPIC_RTE_REMOTE_IRR); 592 Log2(("IOAPIC: ioapicSetEoi: Cleared remote IRR for RTE %u\n", idxRte)); 593 594 /* 595 * Signal the next pending interrupt for this RTE. 596 */ 597 uint32_t const uPinMask = UINT32_C(1) << idxRte; 598 if (pThis->uIrr & uPinMask) 599 ioapicSignalIntrForRte(pThis, idxRte); 576 uint64_t const u64Rte = pThis->au64RedirTable[idxRte]; 577 if (IOAPIC_RTE_GET_VECTOR(u64Rte) == u8Vector) 578 { 579 pThis->au64RedirTable[idxRte] &= ~IOAPIC_RTE_REMOTE_IRR; 580 Log2(("IOAPIC: ioapicSetEoi: Cleared remote IRR, idxRte=%u vector=%#x (%u)\n", idxRte, u8Vector, u8Vector)); 581 582 /* 583 * Signal the next pending interrupt for this RTE. 584 */ 585 uint32_t const uPinMask = UINT32_C(1) << idxRte; 586 if (pThis->uIrr & uPinMask) 587 ioapicSignalIntrForRte(pThis, idxRte); 588 } 600 589 } 601 } 590 591 PDMCritSectLeave(&pThis->CritSect); 592 } 593 else 594 STAM_COUNTER_INC(&pThis->StatEoiContention); 595 596 return rc; 602 597 } 603 598 … … 615 610 if (RT_LIKELY(iIrq >= 0 && iIrq < (int)RT_ELEMENTS(pThis->au64RedirTable))) 616 611 { 612 int rc = PDMCritSectEnter(&pThis->CritSect, VINF_SUCCESS); 613 AssertRC(rc); 614 617 615 uint8_t const idxRte = iIrq; 618 616 uint32_t const uPinMask = UINT32_C(1) << idxRte; 619 uint32_t const u32RteLo = pThis->au64RedirTable[idxRte].au32[0];617 uint32_t const u32RteLo = RT_LO_U32(pThis->au64RedirTable[idxRte]); 620 618 uint8_t const u8TriggerMode = IOAPIC_RTE_GET_TRIGGER_MODE(u32RteLo); 621 619 … … 629 627 if (!fActive) 630 628 { 631 ASMAtomicAndU32(&pThis->uIrr, ~uPinMask); 629 pThis->uIrr &= ~uPinMask; 630 PDMCritSectLeave(&pThis->CritSect); 632 631 return; 633 632 } … … 635 634 /* 636 635 * If the device is flip-flopping the interrupt line, there's no need to 637 * set and unset the IRR as they're atomic operations and the fewer the 638 * better. 636 * set and unset the IRR. 639 637 */ 640 bool const fTouchIrr = !((iLevel & PDM_IRQ_LEVEL_FLIP_FLOP) == PDM_IRQ_LEVEL_FLIP_FLOP);641 638 bool const fFlipFlop = ((iLevel & PDM_IRQ_LEVEL_FLIP_FLOP) == PDM_IRQ_LEVEL_FLIP_FLOP); 639 uint32_t const uPrevIrr = pThis->uIrr & uPinMask; 642 640 if (u8TriggerMode == IOAPIC_RTE_TRIGGER_MODE_EDGE) 643 641 { … … 646 644 * See ICH9 spec. 13.5.7 "REDIR_TBL: Redirection Table (LPC I/F-D31:F0)" 647 645 */ 648 uint32_t const uPrevIrr = pThis->uIrr & uPinMask;649 646 if (!uPrevIrr) 650 647 { 651 if ( fTouchIrr)652 ASMAtomicOrU32(&pThis->uIrr, uPinMask);648 if (!fFlipFlop) 649 pThis->uIrr |= uPinMask; 653 650 654 651 if (!pThis->au32TagSrc[idxRte]) … … 674 671 * should not typically call us with no change to the level. 675 672 */ 676 uint32_t const uPrevIrr = pThis->uIrr & uPinMask;677 673 if (!uPrevIrr) 678 674 { /* likely */ } … … 683 679 } 684 680 685 if ( fTouchIrr)686 ASMAtomicOrU32(&pThis->uIrr, uPinMask);681 if (!fFlipFlop) 682 pThis->uIrr |= uPinMask; 687 683 688 684 if (!pThis->au32TagSrc[idxRte]) … … 693 689 ioapicSignalIntrForRte(pThis, idxRte); 694 690 } 691 692 PDMCritSectLeave(&pThis->CritSect); 695 693 } 696 694 } … … 786 784 787 785 LogFlow(("IOAPIC: ioapicMmioWrite: pThis=%p GCPhysAddr=%#RGp cb=%u uValue=%#RX32\n", pThis, GCPhysAddr, cb, uValue)); 788 786 int rc = VINF_SUCCESS; 789 787 switch (offReg) 790 788 { … … 794 792 795 793 case IOAPIC_DIRECT_OFF_DATA: 796 ioapicSetData(pThis, uValue);794 rc = ioapicSetData(pThis, uValue); 797 795 break; 798 796 799 797 #if IOAPIC_HARDWARE_VERSION == IOAPIC_HARDWARE_VERSION_ICH9 800 798 case IOAPIC_DIRECT_OFF_EOI: 801 ioapicSetEoi(pDevIns, uValue);799 rc = ioapicSetEoi(pDevIns, uValue); 802 800 break; 803 801 #endif … … 808 806 } 809 807 810 return VINF_SUCCESS;808 return rc; 811 809 } 812 810 … … 837 835 static DECLCALLBACK(int) ioapicDbgReg_SetData(void *pvUser, PCDBGFREGDESC pDesc, PCDBGFREGVAL pValue, PCDBGFREGVAL pfMask) 838 836 { 839 ioapicSetData(PDMINS_2_DATA((PPDMDEVINS)pvUser, PIOAPIC), pValue->u32); 840 return VINF_SUCCESS; 837 return ioapicSetData(PDMINS_2_DATA((PPDMDEVINS)pvUser, PIOAPIC), pValue->u32); 841 838 } 842 839 … … 872 869 { 873 870 PIOAPIC pThis = PDMINS_2_DATA((PPDMDEVINS)pvUser, PIOAPIC); 874 ioapicSetRedirTableEntry(pThis, pDesc->offRegister, pValue->u64); 875 return VINF_SUCCESS; 871 return ioapicSetRedirTableEntry(pThis, pDesc->offRegister, pValue->u64); 876 872 } 877 873 … … 976 972 }; 977 973 978 const uint64_t u64Rte = pThis->au64RedirTable[idxRte] .u;974 const uint64_t u64Rte = pThis->au64RedirTable[idxRte]; 979 975 const char *pszDestMode = IOAPIC_RTE_GET_DEST_MODE(u64Rte) == 0 ? "phys" : "log "; 980 976 const uint8_t uDest = IOAPIC_RTE_GET_DEST(u64Rte); … … 1018 1014 SSMR3PutU8(pSSM, pThis->u8Index); 1019 1015 for (uint8_t idxRte = 0; idxRte < RT_ELEMENTS(pThis->au64RedirTable); idxRte++) 1020 SSMR3PutU64(pSSM, pThis->au64RedirTable[idxRte] .u);1016 SSMR3PutU64(pSSM, pThis->au64RedirTable[idxRte]); 1021 1017 1022 1018 return VINF_SUCCESS; … … 1049 1045 SSMR3GetU8(pSSM, (uint8_t *)&pThis->u8Index); 1050 1046 for (uint8_t idxRte = 0; idxRte < RT_ELEMENTS(pThis->au64RedirTable); idxRte++) 1051 SSMR3GetU64(pSSM, (uint64_t *)&pThis->au64RedirTable[idxRte].u);1047 SSMR3GetU64(pSSM, &pThis->au64RedirTable[idxRte]); 1052 1048 1053 1049 return VINF_SUCCESS; … … 1063 1059 LogFlow(("IOAPIC: ioapicR3Reset: pThis=%p\n", pThis)); 1064 1060 1065 /* There might be devices threads calling ioapicSetIrq() in parallel, hence the atomics. */ 1066 ASMAtomicWriteU32(&pThis->uIrr, 0); 1067 ASMAtomicWriteU8(&pThis->u8Index, 0); 1068 ASMAtomicWriteU8(&pThis->u8Id, 0); 1061 /* There might be devices threads calling ioapicSetIrq() in parallel, hence the lock. */ 1062 PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED); 1063 1064 pThis->uIrr = 0; 1065 pThis->u8Index = 0; 1066 pThis->u8Id = 0; 1069 1067 1070 1068 for (uint8_t idxRte = 0; idxRte < RT_ELEMENTS(pThis->au64RedirTable); idxRte++) 1071 1069 { 1072 ASMAtomicWriteU64(&pThis->au64RedirTable[idxRte].u, IOAPIC_RTE_MASK);1070 pThis->au64RedirTable[idxRte] = IOAPIC_RTE_MASK; 1073 1071 pThis->au32TagSrc[idxRte] = 0; 1074 1072 } 1073 1074 PDMCritSectLeave(&pThis->CritSect); 1075 1075 } 1076 1076 … … 1086 1086 pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns); 1087 1087 pThis->pIoApicHlpRC = pThis->pIoApicHlpR3->pfnGetRCHelpers(pDevIns); 1088 } 1089 1090 1091 /** 1092 * @interface_method_impl{PDMDEVREG,pfnDestruct} 1093 */ 1094 static DECLCALLBACK(int) ioapicR3Destruct(PPDMDEVINS pDevIns) 1095 { 1096 PIOAPIC pThis = PDMINS_2_DATA(pDevIns, PIOAPIC); 1097 LogFlow(("IOAPIC: ioapicR3Destruct: pThis=%p\n", pThis)); 1098 PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns); 1099 1100 /* 1101 * Destroy the RTE critical section. 1102 */ 1103 if (PDMCritSectIsInitialized(&pThis->CritSect)) 1104 PDMR3CritSectDelete(&pThis->CritSect); 1105 1106 return VINF_SUCCESS; 1088 1107 } 1089 1108 … … 1127 1146 1128 1147 /* 1129 * We don't do any lockingfor the IOAPIC device.1148 * We will use our own critical section for the IOAPIC device. 1130 1149 */ 1131 1150 rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns)); 1132 1151 AssertRCReturn(rc, rc); 1152 1153 /* 1154 * Setup the critical section to protect concurrent writes to the RTEs. 1155 */ 1156 rc = PDMDevHlpCritSectInit(pDevIns, &pThis->CritSect, RT_SRC_POS, "IOAPIC"); 1157 if (RT_FAILURE(rc)) 1158 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, N_("IOAPIC: Failed to create critical section. rc=%Rrc"), rc); 1133 1159 1134 1160 /* … … 1230 1256 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRedundantLevelIntr, STAMTYPE_COUNTER, "/Devices/IOAPIC/RedundantLevelIntr", STAMUNIT_OCCURENCES, "Number of redundant level-triggered interrupts (no IRR change)."); 1231 1257 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatSuppressedLevelIntr, STAMTYPE_COUNTER, "/Devices/IOAPIC/SuppressedLevelIntr", STAMUNIT_OCCURENCES, "Number of suppressed level-triggered interrupts by remote IRR."); 1258 1259 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatEoiContention, STAMTYPE_COUNTER, "/Devices/IOAPIC/Contention/SetEoi", STAMUNIT_OCCURENCES, "Number of times the critsect is busy during EOI writes causing trips to R3."); 1260 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatSetRteContention, STAMTYPE_COUNTER, "/Devices/IOAPIC/Contention/SetRte", STAMUNIT_OCCURENCES, "Number of times the critsect is busy during RTE writes causing trips to R3."); 1232 1261 #endif 1233 1262 … … 1269 1298 ioapicR3Construct, 1270 1299 /* pfnDestruct */ 1271 NULL,1300 ioapicR3Destruct, 1272 1301 /* pfnRelocate */ 1273 1302 ioapicR3Relocate, -
trunk/src/VBox/VMM/VMMAll/APICAll.cpp
r61608 r61735 471 471 * @param uVector The interrupt vector corresponding to the EOI. 472 472 */ 473 DECLINLINE( void) apicBusBroadcastEoi(PVMCPU pVCpu, uint8_t uVector)473 DECLINLINE(int) apicBusBroadcastEoi(PVMCPU pVCpu, uint8_t uVector) 474 474 { 475 475 PVM pVM = pVCpu->CTX_SUFF(pVM); 476 476 PAPICDEV pApicDev = VM_TO_APICDEV(pVM); 477 pApicDev->CTX_SUFF(pApicHlp)->pfnBusBroadcastEoi(pApicDev->CTX_SUFF(pDevIns), uVector);477 return pApicDev->CTX_SUFF(pApicHlp)->pfnBusBroadcastEoi(pApicDev->CTX_SUFF(pDevIns), uVector); 478 478 } 479 479 … … 1202 1202 if (isrv >= 0) 1203 1203 { 1204 /* 1205 * Broadcast the EOI to the I/O APIC(s). 1206 * 1207 * We'll handle the EOI broadcast first as there is tiny chance we get rescheduled to 1208 * ring-3 due to contention on the I/O APIC lock. This way we don't mess with the rest 1209 * of the APIC state and simply restart the EOI write operation from ring-3. 1210 */ 1204 1211 Assert(isrv <= (int)UINT8_MAX); 1205 uint8_t const uVector = isrv; 1206 apicClearVectorInReg(&pXApicPage->isr, uVector); 1207 apicUpdatePpr(pVCpu); 1208 Log2(("APIC%u: apicSetEoi: Cleared interrupt from ISR. uVector=%#x\n", pVCpu->idCpu, uVector)); 1209 1210 bool fLevelTriggered = apicTestVectorInReg(&pXApicPage->tmr, uVector); 1212 uint8_t const uVector = isrv; 1213 bool const fLevelTriggered = apicTestVectorInReg(&pXApicPage->tmr, uVector); 1211 1214 if (fLevelTriggered) 1212 1215 { 1216 int rc = apicBusBroadcastEoi(pVCpu, uVector); 1217 if (rc == VINF_SUCCESS) 1218 { /* likely */ } 1219 else 1220 return XAPIC_IN_X2APIC_MODE(pVCpu) ? VINF_CPUM_R3_MSR_WRITE : VINF_IOM_R3_MMIO_WRITE; 1221 1222 /* 1223 * Clear the vector from the TMR. 1224 * 1225 * The broadcast to I/O APIC can re-trigger new interrupts to arrive via the bus. However, 1226 * APICUpdatePendingInterrupts() which updates TMR can only be done from EMT which we 1227 * currently are on, so no possibility of concurrent updates. 1228 */ 1213 1229 apicClearVectorInReg(&pXApicPage->tmr, uVector); 1214 apicBusBroadcastEoi(pVCpu, uVector);1215 1230 1216 1231 /* … … 1231 1246 } 1232 1247 1248 /* 1249 * Mark interrupt as serviced, update the PPR and signal pending interrupts. 1250 */ 1251 Log2(("APIC%u: apicSetEoi: Clearing interrupt from ISR. uVector=%#x\n", pVCpu->idCpu, uVector)); 1252 apicClearVectorInReg(&pXApicPage->isr, uVector); 1253 apicUpdatePpr(pVCpu); 1233 1254 apicSignalNextPendingIntr(pVCpu); 1234 1255 } -
trunk/src/VBox/VMM/VMMR0/PDMR0Device.cpp
r61685 r61735 606 606 607 607 /** @interface_method_impl{PDMAPICHLPR0,pfnBusBroadcastEoi} */ 608 static DECLCALLBACK( void) pdmR0ApicHlp_BusBroadcastEoi(PPDMDEVINS pDevIns, uint8_t u8Vector)608 static DECLCALLBACK(int) pdmR0ApicHlp_BusBroadcastEoi(PPDMDEVINS pDevIns, uint8_t u8Vector) 609 609 { 610 610 /* pfnSetEoi will be NULL in the old IOAPIC code as it's not implemented. */ … … 618 618 { 619 619 Assert(pVM->pdm.s.IoApic.CTX_SUFF(pfnSetEoi)); 620 pVM->pdm.s.IoApic.CTX_SUFF(pfnSetEoi)(pVM->pdm.s.IoApic.CTX_SUFF(pDevIns), u8Vector);620 return pVM->pdm.s.IoApic.CTX_SUFF(pfnSetEoi)(pVM->pdm.s.IoApic.CTX_SUFF(pDevIns), u8Vector); 621 621 } 622 622 #endif 623 return VINF_SUCCESS; 623 624 } 624 625 -
trunk/src/VBox/VMM/VMMR3/PDMDevMiscHlp.cpp
r61685 r61735 269 269 270 270 /** @interface_method_impl{PDMAPICHLPR3,pfnBusBroadcastEoi} */ 271 static DECLCALLBACK( void) pdmR3ApicHlp_BusBroadcastEoi(PPDMDEVINS pDevIns, uint8_t u8Vector)271 static DECLCALLBACK(int) pdmR3ApicHlp_BusBroadcastEoi(PPDMDEVINS pDevIns, uint8_t u8Vector) 272 272 { 273 273 /* pfnSetEoi will be NULL in the old IOAPIC code as it's not implemented. */ … … 281 281 { 282 282 Assert(pVM->pdm.s.IoApic.CTX_SUFF(pfnSetEoi)); 283 pVM->pdm.s.IoApic.CTX_SUFF(pfnSetEoi)(pVM->pdm.s.IoApic.CTX_SUFF(pDevIns), u8Vector); 284 } 285 #endif 283 return pVM->pdm.s.IoApic.CTX_SUFF(pfnSetEoi)(pVM->pdm.s.IoApic.CTX_SUFF(pDevIns), u8Vector); 284 } 285 #endif 286 return VINF_SUCCESS; 286 287 } 287 288 -
trunk/src/VBox/VMM/VMMRC/PDMRCDevice.cpp
r61685 r61735 561 561 562 562 /** @interface_method_impl{PDMAPICHLPRC,pfnBusBroadcastEoi} */ 563 static DECLCALLBACK( void) pdmRCApicHlp_BusBroadcastEoi(PPDMDEVINS pDevIns, uint8_t u8Vector)563 static DECLCALLBACK(int) pdmRCApicHlp_BusBroadcastEoi(PPDMDEVINS pDevIns, uint8_t u8Vector) 564 564 { 565 565 /* pfnSetEoi will be NULL in the old IOAPIC code as it's not implemented. */ … … 573 573 { 574 574 Assert(pVM->pdm.s.IoApic.CTX_SUFF(pfnSetEoi)); 575 pVM->pdm.s.IoApic.CTX_SUFF(pfnSetEoi)(pVM->pdm.s.IoApic.CTX_SUFF(pDevIns), u8Vector);575 return pVM->pdm.s.IoApic.CTX_SUFF(pfnSetEoi)(pVM->pdm.s.IoApic.CTX_SUFF(pDevIns), u8Vector); 576 576 } 577 577 #endif 578 return VINF_SUCCESS; 578 579 } 579 580 -
trunk/src/VBox/VMM/include/PDMInternal.h
r61339 r61735 659 659 DECLR3CALLBACKMEMBER(void, pfnSendMsiR3,(PPDMDEVINS pDevIns, RTGCPHYS GCAddr, uint32_t uValue, uint32_t uTagSrc)); 660 660 /** @copydoc PDMIOAPICREG::pfnSetEoiR3 */ 661 DECLR3CALLBACKMEMBER( void,pfnSetEoiR3,(PPDMDEVINS pDevIns, uint8_t u8Vector));661 DECLR3CALLBACKMEMBER(int, pfnSetEoiR3,(PPDMDEVINS pDevIns, uint8_t u8Vector)); 662 662 663 663 /** Pointer to the PIC device instance - R0. */ … … 668 668 DECLR0CALLBACKMEMBER(void, pfnSendMsiR0,(PPDMDEVINS pDevIns, RTGCPHYS GCAddr, uint32_t uValue, uint32_t uTagSrc)); 669 669 /** @copydoc PDMIOAPICREG::pfnSetEoiR3 */ 670 DECLR0CALLBACKMEMBER( void,pfnSetEoiR0,(PPDMDEVINS pDevIns, uint8_t u8Vector));670 DECLR0CALLBACKMEMBER(int, pfnSetEoiR0,(PPDMDEVINS pDevIns, uint8_t u8Vector)); 671 671 672 672 /** Pointer to the APIC device instance - RC Ptr. */ … … 677 677 DECLRCCALLBACKMEMBER(void, pfnSendMsiRC,(PPDMDEVINS pDevIns, RTGCPHYS GCAddr, uint32_t uValue, uint32_t uTagSrc)); 678 678 /** @copydoc PDMIOAPICREG::pfnSendMsiR3 */ 679 DECLRCCALLBACKMEMBER( void,pfnSetEoiRC,(PPDMDEVINS pDevIns, uint8_t u8Vector));679 DECLRCCALLBACKMEMBER(int, pfnSetEoiRC,(PPDMDEVINS pDevIns, uint8_t u8Vector)); 680 680 } PDMIOAPIC; 681 681
Note:
See TracChangeset
for help on using the changeset viewer.