Changeset 61685 in vbox for trunk/src/VBox/Devices/PC
- Timestamp:
- Jun 13, 2016 4:04:42 PM (9 years ago)
- svn:sync-xref-src-repo-rev:
- 108043
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/PC/DevIOAPIC_New.cpp
r61375 r61685 81 81 #define IOAPIC_VER_HAS_PRQ(a_Reg) RT_BOOL((a_Reg) & RT_BIT_32(15)) 82 82 83 /** Index register - Valid write mask. */ 84 #define IOAPIC_INDEX_VALID_WRITE_MASK UINT32_C(0xff) 85 83 86 /** Arbitration register - Gets the ID. */ 84 87 #define IOAPIC_ARB_GET_ID(a_Reg) ((a_Reg) >> 24 & 0xf) … … 90 93 #define IOAPIC_RTE_VECTOR UINT64_C(0xff) 91 94 /** Redirection table entry - Delivery mode. */ 92 #define IOAPIC_RTE_DELIVERY_MODE (RT_BIT _64(8) | RT_BIT_64(9) | RT_BIT_64(10))95 #define IOAPIC_RTE_DELIVERY_MODE (RT_BIT(8) | RT_BIT(9) | RT_BIT(10)) 93 96 /** Redirection table entry - Destination mode. */ 94 #define IOAPIC_RTE_DEST_MODE RT_BIT _64(11)97 #define IOAPIC_RTE_DEST_MODE RT_BIT(11) 95 98 /** Redirection table entry - Delivery status. */ 96 #define IOAPIC_RTE_DELIVERY_STATUS RT_BIT _64(12)99 #define IOAPIC_RTE_DELIVERY_STATUS RT_BIT(12) 97 100 /** Redirection table entry - Interrupt input pin polarity. */ 98 #define IOAPIC_RTE_POLARITY RT_BIT _64(13)101 #define IOAPIC_RTE_POLARITY RT_BIT(13) 99 102 /** Redirection table entry - Remote IRR. */ 100 #define IOAPIC_RTE_REMOTE_IRR RT_BIT _64(14)103 #define IOAPIC_RTE_REMOTE_IRR RT_BIT(14) 101 104 /** Redirection table entry - Trigger Mode. */ 102 #define IOAPIC_RTE_TRIGGER_MODE RT_BIT _64(15)105 #define IOAPIC_RTE_TRIGGER_MODE RT_BIT(15) 103 106 /** Redirection table entry - the mask bit number. */ 104 107 #define IOAPIC_RTE_MASK_BIT 16 105 108 /** Redirection table entry - the mask. */ 106 #define IOAPIC_RTE_MASK RT_BIT _64(IOAPIC_RTE_MASK_BIT)109 #define IOAPIC_RTE_MASK RT_BIT(IOAPIC_RTE_MASK_BIT) 107 110 /** Redirection table entry - Extended Destination ID. */ 108 111 #define IOAPIC_RTE_EXT_DEST_ID UINT64_C(0x00ff000000000000) … … 151 154 /** Redirection table entry - Trigger mode level. */ 152 155 #define IOAPIC_RTE_TRIGGER_MODE_LEVEL 1 156 /** Redirection table entry - Destination mode physical. */ 157 #define IOAPIC_RTE_DEST_MODE_PHYSICAL 0 158 /** Redirection table entry - Destination mode logical. */ 159 #define IOAPIC_RTE_DEST_MODE_LOGICAL 1 160 153 161 154 162 /** Index of indirect registers in the I/O APIC register table. */ … … 193 201 * Structures and Typedefs * 194 202 *********************************************************************************************************************************/ 203 /** 204 * The I/O Redirection Table Entry (RTE). 205 */ 206 typedef union RTE 207 { 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 /** 218 * The per-VM I/O APIC device state. 219 */ 195 220 typedef struct IOAPIC 196 221 { … … 211 236 212 237 /** The ID register. */ 213 uint8_t 238 uint8_t volatile u8Id; 214 239 /** The index register. */ 215 uint8_t 240 uint8_t volatile u8Index; 216 241 /** Number of CPUs. */ 217 242 uint8_t cCpus; 218 243 /* Alignment padding. */ 219 244 uint8_t u8Padding0[5]; 220 #if IOAPIC_HARDWARE_VERSION == IOAPIC_HARDWARE_VERSION_ICH9221 /** The EOI register. */222 uint32_t u32Eoi;223 uint32_t u32Padding1;224 #else225 uint64_t u64Padding0;226 #endif227 245 228 246 /** The redirection table registers. */ 229 uint64_tau64RedirTable[IOAPIC_NUM_INTR_PINS];247 RTE au64RedirTable[IOAPIC_NUM_INTR_PINS]; 230 248 /** The IRQ tags and source IDs for each pin (tracing purposes). */ 231 249 uint32_t au32TagSrc[IOAPIC_NUM_INTR_PINS]; … … 233 251 /** Alignment padding. */ 234 252 uint32_t u32Padding2; 235 /** The internal IRR reflecting interrupt lines. */236 uint32_t 253 /** The internal IRR reflecting state of the interrupt lines. */ 254 uint32_t volatile uIrr; 237 255 238 256 #ifdef VBOX_WITH_STATISTICS … … 264 282 /** Number of SetEoi calls in RC. */ 265 283 STAMCOUNTER StatSetEoiRC; 284 285 /** Number of redundant edge-triggered interrupts. */ 286 STAMCOUNTER StatRedundantEdgeIntr; 287 /** Number of redundant level-triggered interrupts. */ 288 STAMCOUNTER StatRedundantLevelIntr; 289 /** Number of suppressed level-triggered interrupts (by remote IRR). */ 290 STAMCOUNTER StatSuppressedLevelIntr; 266 291 #endif 267 292 } IOAPIC; … … 310 335 { 311 336 Log2(("IOAPIC: ioapicSetId: uValue=%#RX32\n", uValue)); 312 pThis->u8Id = (uValue >> 24) & IOAPIC_ID_MASK;337 ASMAtomicWriteU8(&pThis->u8Id, (uValue >> 24) & IOAPIC_ID_MASK); 313 338 } 314 339 … … 337 362 { 338 363 LogFlow(("IOAPIC: ioapicSetIndex: uValue=%#RX32\n", uValue)); 339 pThis->u8Index = uValue & 0xff;364 ASMAtomicWriteU8(&pThis->u8Index, uValue & IOAPIC_INDEX_VALID_WRITE_MASK); 340 365 } 341 366 … … 360 385 * @param pThis The IOAPIC instance. 361 386 * @param idxRte The index of the RTE. 362 */ 363 static void ioapicSignalIrqForRte(PIOAPIC pThis, uint8_t idxRte) 364 { 365 /* Check if there's an interrupt on the corresponding interrupt input pin. */ 366 uint32_t const uPinMask = UINT32_C(1) << idxRte; 367 if (pThis->uIrr & uPinMask) 368 { 369 /* Ensure the RTE isn't masked. */ 370 uint64_t const u64Rte = pThis->au64RedirTable[idxRte]; 371 if (!IOAPIC_RTE_IS_MASKED(u64Rte)) 387 * 388 * @remarks It is the responsibility of the caller to verify that an interrupt is 389 * pending for the pin corresponding to the RTE before calling this 390 * function. 391 */ 392 static void ioapicSignalIntrForRte(PIOAPIC pThis, uint8_t idxRte) 393 { 394 /* Ensure the RTE isn't masked. */ 395 uint64_t const u64Rte = pThis->au64RedirTable[idxRte].u; 396 if (!IOAPIC_RTE_IS_MASKED(u64Rte)) 397 { 398 /* We cannot accept another level-triggered interrupt until remote IRR has been cleared. */ 399 uint8_t const u8TriggerMode = IOAPIC_RTE_GET_TRIGGER_MODE(u64Rte); 400 if (u8TriggerMode == IOAPIC_RTE_TRIGGER_MODE_LEVEL) 372 401 { 373 uint32_t const u32TagSrc = pThis->au32TagSrc[idxRte]; 374 uint8_t const u8Vector = IOAPIC_RTE_GET_VECTOR(u64Rte); 375 uint8_t const u8DeliveryMode = IOAPIC_RTE_GET_DELIVERY_MODE(u64Rte); 376 uint8_t const u8DestMode = IOAPIC_RTE_GET_DEST_MODE(u64Rte); 377 uint8_t const u8Polarity = IOAPIC_RTE_GET_POLARITY(u64Rte); 378 uint8_t const u8TriggerMode = IOAPIC_RTE_GET_TRIGGER_MODE(u64Rte); 379 uint8_t const u8Dest = IOAPIC_RTE_GET_DEST(u64Rte); 380 381 /* We cannot accept another level-triggered interrupt until remote IRR has been cleared. */ 382 if (u8TriggerMode == IOAPIC_RTE_TRIGGER_MODE_LEVEL) 402 uint8_t const u8RemoteIrr = IOAPIC_RTE_GET_REMOTE_IRR(u64Rte); 403 if (u8RemoteIrr) 383 404 { 384 uint8_t const u8RemoteIrr = IOAPIC_RTE_GET_REMOTE_IRR(u64Rte); 385 if (u8RemoteIrr) 386 return; 405 STAM_COUNTER_INC(&pThis->StatSuppressedLevelIntr); 406 return; 387 407 } 388 389 /* 390 * Deliver to the local APIC via the system/3-wire-APIC bus. 391 */ 392 int rc = pThis->CTX_SUFF(pIoApicHlp)->pfnApicBusDeliver(pThis->CTX_SUFF(pDevIns), 393 u8Dest, 394 u8DestMode, 395 u8DeliveryMode, 396 u8Vector, 397 u8Polarity, 398 u8TriggerMode, 399 u32TagSrc); 400 /* Can't reschedule to R3. */ 401 Assert(rc == VINF_SUCCESS); 402 403 /* 404 * For edge triggered interrupts, we can clear our IRR bit to receive further 405 * edge-triggered interrupts, as the local APIC has accepted the interrupt. 406 */ 407 if (u8TriggerMode == IOAPIC_RTE_TRIGGER_MODE_EDGE) 408 { 409 pThis->uIrr &= ~uPinMask; 410 pThis->au32TagSrc[idxRte] = 0; 411 } 412 else 413 { 414 /* 415 * For level triggered interrupts, we set the remote IRR bit to indicate 416 * the local APIC has accepted the interrupt. 417 */ 418 Assert(u8TriggerMode == IOAPIC_RTE_TRIGGER_MODE_LEVEL); 419 pThis->au64RedirTable[idxRte] |= IOAPIC_RTE_REMOTE_IRR; 420 } 408 } 409 410 uint8_t const u8Vector = IOAPIC_RTE_GET_VECTOR(u64Rte); 411 uint8_t const u8DeliveryMode = IOAPIC_RTE_GET_DELIVERY_MODE(u64Rte); 412 uint8_t const u8DestMode = IOAPIC_RTE_GET_DEST_MODE(u64Rte); 413 uint8_t const u8Polarity = IOAPIC_RTE_GET_POLARITY(u64Rte); 414 uint8_t const u8Dest = IOAPIC_RTE_GET_DEST(u64Rte); 415 uint32_t const u32TagSrc = pThis->au32TagSrc[idxRte]; 416 417 Log2(("IOAPIC: Signaling %s-triggered interrupt. Dest=%#x DestMode=%s Vector=%#x (%u)", 418 u8TriggerMode == IOAPIC_RTE_TRIGGER_MODE_EDGE ? "edge" : "level", u8Dest, 419 u8DestMode == IOAPIC_RTE_DEST_MODE_PHYSICAL ? "physical" : "logical", u8Vector, u8Vector)); 420 421 /* 422 * Deliver to the local APIC via the system/3-wire-APIC bus. 423 */ 424 int rc = pThis->CTX_SUFF(pIoApicHlp)->pfnApicBusDeliver(pThis->CTX_SUFF(pDevIns), 425 u8Dest, 426 u8DestMode, 427 u8DeliveryMode, 428 u8Vector, 429 u8Polarity, 430 u8TriggerMode, 431 u32TagSrc); 432 /* Can't reschedule to R3. */ 433 Assert(rc == VINF_SUCCESS); 434 435 /* 436 * For level-triggered interrupts, we set the remote IRR bit to indicate 437 * the local APIC has accepted the interrupt. 438 * 439 * For edge-triggered interrupts, we should not clear the IRR bit as it 440 * should remain intact to reflect the state of the interrupt line. 441 * The device will explicitly transition to inactive state via the 442 * ioapicSetIrq() callback. 443 */ 444 if (u8TriggerMode == IOAPIC_RTE_TRIGGER_MODE_LEVEL) 445 { 446 Assert(u8TriggerMode == IOAPIC_RTE_TRIGGER_MODE_LEVEL); 447 ASMAtomicOrU32(&pThis->au64RedirTable[idxRte].au32[0], IOAPIC_RTE_REMOTE_IRR); 421 448 } 422 449 } … … 436 463 uint32_t uValue; 437 464 if (!(uIndex & 1)) 438 uValue = RT_LO_U32(pThis->au64RedirTable[idxRte])& RT_LO_U32(IOAPIC_RTE_VALID_READ_MASK);465 uValue = pThis->au64RedirTable[idxRte].au32[0] & RT_LO_U32(IOAPIC_RTE_VALID_READ_MASK); 439 466 else 440 uValue = RT_HI_U32(pThis->au64RedirTable[idxRte])& RT_HI_U32(IOAPIC_RTE_VALID_READ_MASK);467 uValue = pThis->au64RedirTable[idxRte].au32[1] & RT_HI_U32(IOAPIC_RTE_VALID_READ_MASK); 441 468 442 469 LogFlow(("IOAPIC: ioapicGetRedirTableEntry: uIndex=%#RX32 idxRte=%u returns %#RX32\n", uIndex, idxRte, uValue)); … … 462 489 * Update only the valid, writable bits. 463 490 */ 464 uint64_t const u64Rte = pThis->au64RedirTable[idxRte] ;491 uint64_t const u64Rte = pThis->au64RedirTable[idxRte].u; 465 492 if (!(uIndex & 1)) 466 493 { 467 494 uint32_t const u32RteNewLo = uValue & RT_LO_U32(IOAPIC_RTE_VALID_WRITE_MASK); 468 uint64_t const u64RteHi = u64Rte & UINT64_C(0xffffffff00000000); 469 pThis->au64RedirTable[idxRte] = u64RteHi | u32RteNewLo; 495 ASMAtomicWriteU32(&pThis->au64RedirTable[idxRte].au32[0], u32RteNewLo); 470 496 } 471 497 else 472 498 { 473 uint32_t const u32RteLo = RT_LO_U32(u64Rte); 474 uint64_t const u64RteNewHi = (uint64_t)(uValue & RT_HI_U32(IOAPIC_RTE_VALID_WRITE_MASK)) << 32; 475 pThis->au64RedirTable[idxRte] = u64RteNewHi | u32RteLo; 476 } 477 478 ioapicSignalIrqForRte(pThis, idxRte); 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); 479 509 480 510 LogFlow(("IOAPIC: ioapicSetRedirTableEntry: uIndex=%#RX32 idxRte=%u uValue=%#RX32\n", uIndex, idxRte, uValue)); … … 547 577 /** 548 578 * @interface_method_impl{PDMIOAPICREG,pfnSetEoiR3} 549 * @remarks The device critsect is entered by the caller(s).550 579 */ 551 580 PDMBOTHCBDECL(void) ioapicSetEoi(PPDMDEVINS pDevIns, uint8_t u8Vector) … … 557 586 for (uint8_t idxRte = 0; idxRte < RT_ELEMENTS(pThis->au64RedirTable); idxRte++) 558 587 { 559 uint64_t const u64Rte = pThis->au64RedirTable[idxRte] ;588 uint64_t const u64Rte = pThis->au64RedirTable[idxRte].u; 560 589 if (IOAPIC_RTE_GET_VECTOR(u64Rte) == u8Vector) 561 590 { 562 pThis->au64RedirTable[idxRte] &= ~IOAPIC_RTE_REMOTE_IRR;591 ASMAtomicAndU32(&pThis->au64RedirTable[idxRte].au32[0], ~IOAPIC_RTE_REMOTE_IRR); 563 592 Log2(("IOAPIC: ioapicSetEoi: Cleared remote IRR for RTE %u\n", idxRte)); 564 ioapicSignalIrqForRte(pThis, 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); 565 600 } 566 601 } … … 570 605 /** 571 606 * @interface_method_impl{PDMIOAPICREG,pfnSetIrqR3} 572 * @remarks The device critsect is entered by the caller(s).573 607 */ 574 608 PDMBOTHCBDECL(void) ioapicSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc) … … 579 613 STAM_COUNTER_INC(&pThis->CTX_SUFF(StatSetIrq)); 580 614 581 if (iIrq >= 0 && iIrq < (int)RT_ELEMENTS(pThis->au64RedirTable)) 582 { 583 uint8_t const idxRte = iIrq; 584 uint64_t const u64Rte = pThis->au64RedirTable[idxRte]; 585 uint8_t const u8TriggerMode = IOAPIC_RTE_GET_TRIGGER_MODE(u64Rte); 586 uint32_t const uPinMask = UINT32_C(1) << idxRte; 615 if (RT_LIKELY(iIrq >= 0 && iIrq < (int)RT_ELEMENTS(pThis->au64RedirTable))) 616 { 617 uint8_t const idxRte = iIrq; 618 uint32_t const uPinMask = UINT32_C(1) << idxRte; 619 uint32_t const u32RteLo = pThis->au64RedirTable[idxRte].au32[0]; 620 uint8_t const u8TriggerMode = IOAPIC_RTE_GET_TRIGGER_MODE(u32RteLo); 621 622 bool fActive = RT_BOOL(iLevel & 1); 623 /** @todo Polarity is busted elsewhere, we need to fix that 624 * first. See @bugref{8386#c7}. */ 625 #if 0 626 uint8_t const u8Polarity = IOAPIC_RTE_GET_POLARITY(u32RteLo); 627 fActive ^= u8Polarity; */ 628 #endif 629 if (!fActive) 630 { 631 ASMAtomicAndU32(&pThis->uIrr, ~uPinMask); 632 return; 633 } 634 635 /* 636 * 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. 639 */ 640 bool const fTouchIrr = !((iLevel & PDM_IRQ_LEVEL_FLIP_FLOP) == PDM_IRQ_LEVEL_FLIP_FLOP); 587 641 588 642 if (u8TriggerMode == IOAPIC_RTE_TRIGGER_MODE_EDGE) 589 643 { 590 /** @todo Consider polarity for edge-triggered interrupts? There 591 * seems to be a conflict between "The Unabridged Pentium" 592 * book and the I/O APIC specs. */ 593 if (iLevel) 644 /* 645 * For edge-triggered interrupts, we need to act only on an edge transition. 646 * See ICH9 spec. 13.5.7 "REDIR_TBL: Redirection Table (LPC I/F-D31:F0)" 647 */ 648 uint32_t const uPrevIrr = pThis->uIrr & uPinMask; 649 if (!uPrevIrr) 594 650 { 595 pThis->uIrr |= uPinMask; 651 if (fTouchIrr) 652 ASMAtomicOrU32(&pThis->uIrr, uPinMask); 653 596 654 if (!pThis->au32TagSrc[idxRte]) 597 655 pThis->au32TagSrc[idxRte] = uTagSrc; … … 599 657 pThis->au32TagSrc[idxRte] = RT_BIT_32(31); 600 658 601 ioapicSignalI rqForRte(pThis, idxRte);659 ioapicSignalIntrForRte(pThis, idxRte); 602 660 } 603 661 else 604 pThis->uIrr &= ~uPinMask; 662 { 663 STAM_COUNTER_INC(&pThis->StatRedundantEdgeIntr); 664 Log2(("IOAPIC: Redundant edge-triggered interrupt %#x (%u)\n", idxRte, idxRte)); 665 } 605 666 } 606 667 else … … 608 669 Assert(u8TriggerMode == IOAPIC_RTE_TRIGGER_MODE_LEVEL); 609 670 610 bool fActive = RT_BOOL(iLevel & 1);611 /** @todo Polarity is busted elsewhere, we need to fix that612 * first. See @bugref{8386#c7}. */613 #if 0 614 uint8_t const u8Polarity = IOAPIC_RTE_GET_POLARITY(u64Rte);615 fActive ^= u8Polarity; */616 #endif 617 618 if (fActive)671 /* 672 * For level-triggered interrupts, redundant interrupts are not a problem 673 * and will eventually be delivered anyway after an EOI, but our PDM devices 674 * should not typically call us with no change to the level. 675 */ 676 uint32_t const uPrevIrr = pThis->uIrr & uPinMask; 677 if (!uPrevIrr) 678 { /* likely */ } 679 else 619 680 { 620 pThis->uIrr |= uPinMask; 621 if (!pThis->au32TagSrc[idxRte]) 622 pThis->au32TagSrc[idxRte] = uTagSrc; 623 else 624 pThis->au32TagSrc[idxRte] = RT_BIT_32(31); 625 626 ioapicSignalIrqForRte(pThis, idxRte); 627 628 if ((iLevel & PDM_IRQ_LEVEL_FLIP_FLOP) == PDM_IRQ_LEVEL_FLIP_FLOP) 629 { 630 pThis->uIrr &= ~uPinMask; 631 pThis->au32TagSrc[idxRte] = 0; 632 } 681 STAM_COUNTER_INC(&pThis->StatRedundantLevelIntr); 682 Log2(("IOAPIC: Redundant level-triggered interrupt %#x (%u)\n", idxRte, idxRte)); 633 683 } 684 685 if (fTouchIrr) 686 ASMAtomicOrU32(&pThis->uIrr, uPinMask); 687 688 if (!pThis->au32TagSrc[idxRte]) 689 pThis->au32TagSrc[idxRte] = uTagSrc; 634 690 else 635 pThis->uIrr &= ~uPinMask; 691 pThis->au32TagSrc[idxRte] = RT_BIT_32(31); 692 693 ioapicSignalIntrForRte(pThis, idxRte); 636 694 } 637 695 } … … 641 699 /** 642 700 * @interface_method_impl{PDMIOAPICREG,pfnSendMsiR3} 643 * @remarks The device critsect is entered by the caller(s).644 701 */ 645 702 PDMBOTHCBDECL(void) ioapicSendMsi(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t uValue, uint32_t uTagSrc) … … 689 746 STAM_COUNTER_INC(&pThis->CTX_SUFF(StatMmioRead)); 690 747 691 IOAPIC_LOCK(pThis, VINF_IOM_R3_MMIO_READ);692 693 748 int rc = VINF_SUCCESS; 694 749 uint32_t *puValue = (uint32_t *)pv; … … 710 765 } 711 766 712 IOAPIC_UNLOCK(pThis);713 714 767 LogFlow(("IOAPIC: ioapicMmioRead: offReg=%#x, returns %#RX32\n", offReg, *puValue)); 715 768 return rc; … … 725 778 726 779 STAM_COUNTER_INC(&pThis->CTX_SUFF(StatMmioWrite)); 727 728 IOAPIC_LOCK(pThis, VINF_IOM_R3_MMIO_WRITE);729 780 730 781 Assert(!(GCPhysAddr & 3)); … … 757 808 } 758 809 759 IOAPIC_UNLOCK(pThis);760 810 return VINF_SUCCESS; 761 811 } … … 926 976 }; 927 977 928 const uint64_t u Entry = pThis->au64RedirTable[idxRte];929 const char *pszDestMode = IOAPIC_RTE_GET_DEST_MODE(u Entry) == 0 ? "phys" : "log ";930 const uint8_t uDest = IOAPIC_RTE_GET_DEST(u Entry);931 const uint8_t uMask = IOAPIC_RTE_GET_MASK(u Entry);932 const char *pszTriggerMode = IOAPIC_RTE_GET_TRIGGER_MODE(u Entry) == 0 ? "edge " : "level";933 const uint8_t uRemoteIrr = IOAPIC_RTE_GET_REMOTE_IRR(u Entry);934 const char *pszPolarity = IOAPIC_RTE_GET_POLARITY(u Entry) == 0 ? "acthi" : "actlo";935 const char *pszDeliveryStatus = IOAPIC_RTE_GET_DELIVERY_STATUS(u Entry) == 0 ? "idle" : "pend";936 const uint8_t uDeliveryMode = IOAPIC_RTE_GET_DELIVERY_MODE(u Entry);937 978 const uint64_t u64Rte = pThis->au64RedirTable[idxRte].u; 979 const char *pszDestMode = IOAPIC_RTE_GET_DEST_MODE(u64Rte) == 0 ? "phys" : "log "; 980 const uint8_t uDest = IOAPIC_RTE_GET_DEST(u64Rte); 981 const uint8_t uMask = IOAPIC_RTE_GET_MASK(u64Rte); 982 const char *pszTriggerMode = IOAPIC_RTE_GET_TRIGGER_MODE(u64Rte) == 0 ? "edge " : "level"; 983 const uint8_t uRemoteIrr = IOAPIC_RTE_GET_REMOTE_IRR(u64Rte); 984 const char *pszPolarity = IOAPIC_RTE_GET_POLARITY(u64Rte) == 0 ? "acthi" : "actlo"; 985 const char *pszDeliveryStatus = IOAPIC_RTE_GET_DELIVERY_STATUS(u64Rte) == 0 ? "idle" : "pend"; 986 const uint8_t uDeliveryMode = IOAPIC_RTE_GET_DELIVERY_MODE(u64Rte); 987 Assert(uDeliveryMode < RT_ELEMENTS(s_apszDeliveryModes)); 938 988 const char *pszDeliveryMode = s_apszDeliveryModes[uDeliveryMode]; 939 const uint8_t uVector = IOAPIC_RTE_GET_VECTOR(u Entry);989 const uint8_t uVector = IOAPIC_RTE_GET_VECTOR(u64Rte); 940 990 941 991 pHlp->pfnPrintf(pHlp, " %02d %s %02x %u %u %s %u %s %s %s %3u (%016llx)\n", … … 951 1001 pszDeliveryMode, 952 1002 uVector, 953 pThis->au64RedirTable[idxRte]);1003 u64Rte); 954 1004 } 955 1005 } … … 968 1018 SSMR3PutU8(pSSM, pThis->u8Index); 969 1019 for (uint8_t idxRte = 0; idxRte < RT_ELEMENTS(pThis->au64RedirTable); idxRte++) 970 SSMR3PutU64(pSSM, pThis->au64RedirTable[idxRte] );1020 SSMR3PutU64(pSSM, pThis->au64RedirTable[idxRte].u); 971 1021 972 1022 return VINF_SUCCESS; … … 994 1044 995 1045 if (uVersion == IOAPIC_SAVED_STATE_VERSION) 996 SSMR3GetU32(pSSM, &pThis->uIrr);997 998 SSMR3GetU8(pSSM, &pThis->u8Id);999 SSMR3GetU8(pSSM, &pThis->u8Index);1046 SSMR3GetU32(pSSM, (uint32_t *)&pThis->uIrr); 1047 1048 SSMR3GetU8(pSSM, (uint8_t *)&pThis->u8Id); 1049 SSMR3GetU8(pSSM, (uint8_t *)&pThis->u8Index); 1000 1050 for (uint8_t idxRte = 0; idxRte < RT_ELEMENTS(pThis->au64RedirTable); idxRte++) 1001 SSMR3GetU64(pSSM, &pThis->au64RedirTable[idxRte]);1051 SSMR3GetU64(pSSM, (uint64_t *)&pThis->au64RedirTable[idxRte].u); 1002 1052 1003 1053 return VINF_SUCCESS; … … 1013 1063 LogFlow(("IOAPIC: ioapicR3Reset: pThis=%p\n", pThis)); 1014 1064 1015 /* We lock here to prevent concurrent writes from ioapicSetIrq() from device threads. */ 1016 IOAPIC_LOCK_VOID(pThis); 1017 1018 pThis->uIrr = 0; 1019 pThis->u8Index = 0; 1020 pThis->u8Id = 0; 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); 1021 1069 1022 1070 for (uint8_t idxRte = 0; idxRte < RT_ELEMENTS(pThis->au64RedirTable); idxRte++) 1023 1071 { 1024 pThis->au64RedirTable[idxRte] = IOAPIC_RTE_MASK; 1025 pThis->au32TagSrc[idxRte] = 0; 1026 } 1027 1028 IOAPIC_UNLOCK(pThis); 1072 ASMAtomicWriteU64(&pThis->au64RedirTable[idxRte].u, IOAPIC_RTE_MASK); 1073 pThis->au32TagSrc[idxRte] = 0; 1074 } 1029 1075 } 1030 1076 … … 1064 1110 PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "NumCPUs|RZEnabled", ""); 1065 1111 1112 /* The number of CPUs is currently unused, but left in CFGM and saved-state in case an ID of 0 is 1113 upsets some guest which we haven't yet tested. */ 1066 1114 uint32_t cCpus; 1067 1115 int rc = CFGMR3QueryU32Def(pCfg, "NumCPUs", &cCpus, 1); 1068 1116 if (RT_FAILURE(rc)) 1069 1117 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to query integer value \"NumCPUs\"")); 1070 if (cCpus > UINT8_MAX - 2) /* ID 255 is broadcast and the IO-APIC needs one (ID=cCpus). */1071 {1072 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,1073 N_("Configuration error: Max %u CPUs, %u specified"), UINT8_MAX - 1, cCpus);1074 }1075 1118 pThis->cCpus = (uint8_t)cCpus; 1076 1119 … … 1084 1127 1085 1128 /* 1086 * We shall do locking for this device via IOAPIC helpers.1129 * We don't do any locking for the IOAPIC device. 1087 1130 */ 1088 1131 rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns)); … … 1183 1226 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatSetIrqRC, STAMTYPE_COUNTER, "/Devices/IOAPIC/RC/SetIrqRC", STAMUNIT_OCCURENCES, "Number of IOAPIC SetIrq calls in RC."); 1184 1227 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatSetEoiRC, STAMTYPE_COUNTER, "/Devices/IOAPIC/RC/SetEoiRC", STAMUNIT_OCCURENCES, "Number of IOAPIC SetEoi calls in RC."); 1228 1229 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRedundantEdgeIntr, STAMTYPE_COUNTER, "/Devices/IOAPIC/RedundantEdgeIntr", STAMUNIT_OCCURENCES, "Number of redundant edge-triggered interrupts (no IRR change)."); 1230 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRedundantLevelIntr, STAMTYPE_COUNTER, "/Devices/IOAPIC/RedundantLevelIntr", STAMUNIT_OCCURENCES, "Number of redundant level-triggered interrupts (no IRR change)."); 1231 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatSuppressedLevelIntr, STAMTYPE_COUNTER, "/Devices/IOAPIC/SuppressedLevelIntr", STAMUNIT_OCCURENCES, "Number of suppressed level-triggered interrupts by remote IRR."); 1185 1232 #endif 1186 1233
Note:
See TracChangeset
for help on using the changeset viewer.