Changeset 86204 in vbox for trunk/src/VBox
- Timestamp:
- Sep 21, 2020 5:31:18 PM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Bus/DevIommuAmd.cpp
r86145 r86204 43 43 /** The IOTLB entry magic. */ 44 44 #define IOMMU_IOTLBE_MAGIC 0x10acce55 45 46 #ifndef DEBUG_ramshankar 47 /** Temporary, make permanent later (get rid of define entirely and remove old 48 * code). This allow ssub-qword accesses to qword registers. Write accesses 49 * seems to work (needs testing one sub-path of the code), Read accesses not yet 50 * converted. */ 51 # define IOMMU_NEW_REGISTER_ACCESS 52 #endif 45 53 46 54 … … 195 203 /** @} */ 196 204 197 /** @name MMIO: P PRLog registers.205 /** @name MMIO: Peripheral Page Request (PPR) Log registers. 198 206 * @{ */ 199 207 PPR_LOG_BAR_T PprLogBaseAddr; /**< PPR Log base address register. */ … … 241 249 /** @} */ 242 250 243 /** @name MMIO: M ARCregisters.251 /** @name MMIO: Memory Address Routing & Control (MARC) registers. 244 252 * @{ */ 245 253 MARC_APER_T aMarcApers[4]; /**< MARC Aperture Registers. */ … … 378 386 379 387 /** 380 * IOMMU register access routines.381 */ 382 typedef struct 388 * IOMMU register access. 389 */ 390 typedef struct IOMMUREGACC 383 391 { 384 392 const char *pszName; 385 VBOXSTRICTRC (*pfnRead )(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t *pu64Value);386 VBOXSTRICTRC (*pfnWrite)(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value);387 bool f64BitReg;393 VBOXSTRICTRC (*pfnRead)(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value); 394 VBOXSTRICTRC (*pfnWrite)(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value); 395 uint8_t cb; 388 396 } IOMMUREGACC; 397 /** Pointer to an IOMMU register access. */ 398 typedef IOMMUREGACC *PIOMMUREGACC; 399 /** Pointer to a const IOMMU register access. */ 400 typedef IOMMUREGACC const *PCIOMMUREGACC; 389 401 390 402 … … 546 558 547 559 /** 548 * Writes to a read-only register. 549 */ 550 static VBOXSTRICTRC iommuAmdIgnore_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value) 551 { 552 RT_NOREF(pDevIns, pThis, iReg, u64Value); 553 LogFunc(("Write to read-only register (%#x) with value %#RX64 ignored\n", iReg, u64Value)); 554 return VINF_SUCCESS; 555 } 560 * Reads the Device Table Base Address Register. 561 */ 562 static VBOXSTRICTRC iommuAmdDevTabBar_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value) 563 { 564 RT_NOREF(pDevIns, offReg); 565 *pu64Value = pThis->aDevTabBaseAddrs[0].u64; 566 return VINF_SUCCESS; 567 } 568 569 570 /** 571 * Reads the Command Buffer Base Address Register. 572 */ 573 static VBOXSTRICTRC iommuAmdCmdBufBar_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value) 574 { 575 RT_NOREF(pDevIns, offReg); 576 *pu64Value = pThis->CmdBufBaseAddr.u64; 577 return VINF_SUCCESS; 578 } 579 580 581 /** 582 * Reads the Event Log Base Address Register. 583 */ 584 static VBOXSTRICTRC iommuAmdEvtLogBar_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value) 585 { 586 RT_NOREF(pDevIns, offReg); 587 *pu64Value = pThis->EvtLogBaseAddr.u64; 588 return VINF_SUCCESS; 589 } 590 591 592 /** 593 * Reads the Control Register. 594 */ 595 static VBOXSTRICTRC iommuAmdCtrl_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value) 596 { 597 RT_NOREF(pDevIns, offReg); 598 *pu64Value = pThis->Ctrl.u64; 599 return VINF_SUCCESS; 600 } 601 602 603 /** 604 * Reads the Exclusion Range Base Address Register. 605 */ 606 static VBOXSTRICTRC iommuAmdExclRangeBar_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value) 607 { 608 RT_NOREF(pDevIns, offReg); 609 *pu64Value = pThis->ExclRangeBaseAddr.u64; 610 return VINF_SUCCESS; 611 } 612 613 614 /** 615 * Reads to the Exclusion Range Limit Register. 616 */ 617 static VBOXSTRICTRC iommuAmdExclRangeLimit_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value) 618 { 619 RT_NOREF(pDevIns, offReg); 620 *pu64Value = pThis->ExclRangeLimit.u64; 621 return VINF_SUCCESS; 622 } 623 624 625 /** 626 * Reads to the Extended Feature Register. 627 */ 628 static VBOXSTRICTRC iommuAmdExtFeat_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value) 629 { 630 RT_NOREF(pDevIns, offReg); 631 *pu64Value = pThis->ExtFeat.u64; 632 return VINF_SUCCESS; 633 } 634 635 636 /** 637 * Reads to the PPR Log Base Address Register. 638 */ 639 static VBOXSTRICTRC iommuAmdPprLogBar_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value) 640 { 641 RT_NOREF(pDevIns, offReg); 642 *pu64Value = pThis->PprLogBaseAddr.u64; 643 return VINF_SUCCESS; 644 } 645 646 647 /** 648 * Writes the Hardware Event Register (Hi). 649 */ 650 static VBOXSTRICTRC iommuAmdHwEvtHi_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value) 651 { 652 RT_NOREF(pDevIns, offReg); 653 *pu64Value = pThis->HwEvtHi.u64; 654 return VINF_SUCCESS; 655 } 656 657 658 /** 659 * Reads the Hardware Event Register (Lo). 660 */ 661 static VBOXSTRICTRC iommuAmdHwEvtLo_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value) 662 { 663 RT_NOREF(pDevIns, offReg); 664 *pu64Value = pThis->HwEvtLo; 665 return VINF_SUCCESS; 666 } 667 668 669 /** 670 * Reads the Hardware Event Status Register. 671 */ 672 static VBOXSTRICTRC iommuAmdHwEvtStatus_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value) 673 { 674 RT_NOREF(pDevIns, offReg); 675 *pu64Value = pThis->HwEvtStatus.u64; 676 return VINF_SUCCESS; 677 } 678 679 680 /** 681 * Reads to the GA Log Base Address Register. 682 */ 683 static VBOXSTRICTRC iommuAmdGALogBar_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value) 684 { 685 RT_NOREF(pDevIns, offReg); 686 *pu64Value = pThis->GALogBaseAddr.u64; 687 return VINF_SUCCESS; 688 } 689 690 691 /** 692 * Reads to the PPR Log B Base Address Register. 693 */ 694 static VBOXSTRICTRC iommuAmdPprLogBBaseAddr_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value) 695 { 696 RT_NOREF(pDevIns, offReg); 697 *pu64Value = pThis->PprLogBBaseAddr.u64; 698 return VINF_SUCCESS; 699 } 700 701 702 /** 703 * Reads to the Event Log B Base Address Register. 704 */ 705 static VBOXSTRICTRC iommuAmdEvtLogBBaseAddr_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value) 706 { 707 RT_NOREF(pDevIns, offReg); 708 *pu64Value = pThis->EvtLogBBaseAddr.u64; 709 return VINF_SUCCESS; 710 } 711 712 713 /** 714 * Reads the Device Table Segment Base Address Register. 715 */ 716 static VBOXSTRICTRC iommuAmdDevTabSegBar_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value) 717 { 718 RT_NOREF(pDevIns); 719 720 /* Figure out which segment is being written. */ 721 uint8_t const offSegment = (offReg - IOMMU_MMIO_OFF_DEV_TAB_SEG_FIRST) >> 3; 722 uint8_t const idxSegment = offSegment + 1; 723 Assert(idxSegment < RT_ELEMENTS(pThis->aDevTabBaseAddrs)); 724 725 *pu64Value = pThis->aDevTabBaseAddrs[idxSegment].u64; 726 return VINF_SUCCESS; 727 } 728 729 730 /** 731 * Reads the Device Specific Feature Extension (DSFX) Register. 732 */ 733 static VBOXSTRICTRC iommuAmdDevSpecificFeat_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value) 734 { 735 RT_NOREF(pDevIns, offReg); 736 *pu64Value = pThis->DevSpecificFeat.u64; 737 return VINF_SUCCESS; 738 } 739 740 /** 741 * Reads the Device Specific Control Extension (DSCX) Register. 742 */ 743 static VBOXSTRICTRC iommuAmdDevSpecificCtrl_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value) 744 { 745 RT_NOREF(pDevIns, offReg); 746 *pu64Value = pThis->DevSpecificCtrl.u64; 747 return VINF_SUCCESS; 748 } 749 750 751 /** 752 * Reads the Device Specific Status Extension (DSSX) Register. 753 */ 754 static VBOXSTRICTRC iommuAmdDevSpecificStatus_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value) 755 { 756 RT_NOREF(pDevIns, offReg); 757 *pu64Value = pThis->DevSpecificStatus.u64; 758 return VINF_SUCCESS; 759 } 760 761 762 /** 763 * Reads the MSI Vector Register 0 (32-bit) or the MSI Vector Register 1 (32-bit). 764 */ 765 static VBOXSTRICTRC iommuAmdDevMsiVector_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value) 766 { 767 RT_NOREF(pDevIns, offReg); 768 if (offReg == IOMMU_MMIO_OFF_MSI_VECTOR_0) 769 *pu64Value = pThis->MiscInfo.au32[0]; 770 else 771 { 772 AssertMsg(offReg == IOMMU_MMIO_OFF_MSI_VECTOR_1, ("%#x\n", offReg)); 773 *pu64Value = pThis->MiscInfo.au32[1]; 774 } 775 return VINF_SUCCESS; 776 } 777 778 779 #ifdef IOMMU_NEW_REGISTER_ACCESS 780 /** 781 * Reads the MSI Capability Header Register (32-bit) or the MSI Address (Lo) 782 * Register (32-bit). 783 */ 784 static VBOXSTRICTRC iommuAmdMsiCapHdrOrAddrLo_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value) 785 { 786 RT_NOREF(pThis); 787 PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0]; 788 PDMPCIDEV_ASSERT_VALID(pDevIns, pPciDev); 789 if (offReg == IOMMU_MMIO_OFF_MSI_CAP_HDR) 790 *pu64Value = PDMPciDevGetDWord(pPciDev, IOMMU_PCI_OFF_MSI_CAP_HDR); 791 else 792 { 793 AssertMsg(offReg == IOMMU_MMIO_OFF_MSI_ADDR_LO, ("%#x\n", offReg)); 794 *pu64Value = PDMPciDevGetDWord(pPciDev, IOMMU_PCI_OFF_MSI_ADDR_LO); 795 } 796 return VINF_SUCCESS; 797 } 798 799 800 /** 801 * Reads the MSI Address (Hi) Register (32-bit) or the MSI data register (32-bit). 802 */ 803 static VBOXSTRICTRC iommuAmdMsiAddrHiOrData_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value) 804 { 805 RT_NOREF(pThis); 806 PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0]; 807 PDMPCIDEV_ASSERT_VALID(pDevIns, pPciDev); 808 809 if (offReg == IOMMU_MMIO_OFF_MSI_ADDR_HI) 810 *pu64Value = PDMPciDevGetDWord(pPciDev, IOMMU_PCI_OFF_MSI_ADDR_HI); 811 else 812 { 813 AssertMsg(offReg == IOMMU_MMIO_OFF_MSI_DATA, ("%#x\n", offReg)); 814 *pu64Value = PDMPciDevGetDWord(pPciDev, IOMMU_PCI_OFF_MSI_DATA); 815 } 816 return VINF_SUCCESS; 817 } 818 #endif 819 820 /** 821 * Reads the Command Buffer Head Pointer Register. 822 */ 823 static VBOXSTRICTRC iommuAmdCmdBufHeadPtr_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value) 824 { 825 RT_NOREF(pDevIns, offReg); 826 *pu64Value = pThis->CmdBufHeadPtr.u64; 827 return VINF_SUCCESS; 828 } 829 830 831 /** 832 * Reads the Command Buffer Tail Pointer Register. 833 */ 834 static VBOXSTRICTRC iommuAmdCmdBufTailPtr_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value) 835 { 836 RT_NOREF(pDevIns, offReg); 837 *pu64Value = pThis->CmdBufTailPtr.u64; 838 return VINF_SUCCESS; 839 } 840 841 842 /** 843 * Reads the Event Log Head Pointer Register. 844 */ 845 static VBOXSTRICTRC iommuAmdEvtLogHeadPtr_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value) 846 { 847 RT_NOREF(pDevIns, offReg); 848 *pu64Value = pThis->EvtLogHeadPtr.u64; 849 return VINF_SUCCESS; 850 } 851 852 853 /** 854 * Reads the Event Log Tail Pointer Register. 855 */ 856 static VBOXSTRICTRC iommuAmdEvtLogTailPtr_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value) 857 { 858 RT_NOREF(pDevIns, offReg); 859 *pu64Value = pThis->EvtLogTailPtr.u64; 860 return VINF_SUCCESS; 861 } 862 863 864 /** 865 * Reads the Status Register. 866 */ 867 static VBOXSTRICTRC iommuAmdStatus_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value) 868 { 869 RT_NOREF(pDevIns, offReg); 870 *pu64Value = pThis->Status.u64; 871 return VINF_SUCCESS; 872 } 873 874 #ifndef IOMMU_NEW_REGISTER_ACCESS 875 static VBOXSTRICTRC iommuAmdIgnore_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value) 876 { 877 RT_NOREF(pDevIns, pThis, offReg, u64Value); 878 return VINF_SUCCESS; 879 } 880 #endif 556 881 557 882 … … 559 884 * Writes the Device Table Base Address Register. 560 885 */ 561 static VBOXSTRICTRC iommuAmdDevTabBar_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)562 { 563 RT_NOREF(pDevIns, iReg);886 static VBOXSTRICTRC iommuAmdDevTabBar_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value) 887 { 888 RT_NOREF(pDevIns, offReg); 564 889 565 890 /* Mask out all unrecognized bits. */ … … 575 900 * Writes the Command Buffer Base Address Register. 576 901 */ 577 static VBOXSTRICTRC iommuAmdCmdBufBar_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)578 { 579 RT_NOREF(pDevIns, iReg);902 static VBOXSTRICTRC iommuAmdCmdBufBar_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value) 903 { 904 RT_NOREF(pDevIns, offReg); 580 905 581 906 /* … … 618 943 * Writes the Event Log Base Address Register. 619 944 */ 620 static VBOXSTRICTRC iommuAmdEvtLogBar_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)621 { 622 RT_NOREF(pDevIns, iReg);945 static VBOXSTRICTRC iommuAmdEvtLogBar_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value) 946 { 947 RT_NOREF(pDevIns, offReg); 623 948 624 949 /* … … 662 987 * Writes the Control Register. 663 988 */ 664 static VBOXSTRICTRC iommuAmdCtrl_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)665 { 666 RT_NOREF(pDevIns, iReg);989 static VBOXSTRICTRC iommuAmdCtrl_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value) 990 { 991 RT_NOREF(pDevIns, offReg); 667 992 668 993 /* Mask out all unrecognized bits. */ 669 994 u64Value &= IOMMU_CTRL_VALID_MASK; 670 671 IOMMU_CTRL_T const OldCtrl = iommuAmdGetCtrl(pThis);672 995 IOMMU_CTRL_T NewCtrl; 673 996 NewCtrl.u64 = u64Value; 674 997 675 /* Update the register. */ 676 ASMAtomicWriteU64(&pThis->Ctrl.u64, NewCtrl.u64); 677 678 bool const fNewIommuEn = NewCtrl.n.u1IommuEn; 679 bool const fOldIommuEn = OldCtrl.n.u1IommuEn; 680 681 /* Enable or disable event logging when the bit transitions. */ 682 bool const fOldEvtLogEn = OldCtrl.n.u1EvtLogEn; 683 bool const fNewEvtLogEn = NewCtrl.n.u1EvtLogEn; 684 if ( fOldEvtLogEn != fNewEvtLogEn 685 || fOldIommuEn != fNewIommuEn) 686 { 687 if ( fNewIommuEn 688 && fNewEvtLogEn) 689 { 690 ASMAtomicAndU64(&pThis->Status.u64, ~IOMMU_STATUS_EVT_LOG_OVERFLOW); 691 ASMAtomicOrU64(&pThis->Status.u64, IOMMU_STATUS_EVT_LOG_RUNNING); 692 } 693 else 694 ASMAtomicAndU64(&pThis->Status.u64, ~IOMMU_STATUS_EVT_LOG_RUNNING); 695 } 696 697 /* Enable or disable command buffer processing when the bit transitions. */ 698 bool const fOldCmdBufEn = OldCtrl.n.u1CmdBufEn; 699 bool const fNewCmdBufEn = NewCtrl.n.u1CmdBufEn; 700 if ( fOldCmdBufEn != fNewCmdBufEn 701 || fOldIommuEn != fNewIommuEn) 702 { 703 if ( fNewCmdBufEn 704 && fNewIommuEn) 705 { 706 ASMAtomicOrU64(&pThis->Status.u64, IOMMU_STATUS_CMD_BUF_RUNNING); 707 LogFunc(("Command buffer enabled\n")); 708 709 /* Wake up the command thread to start processing commands. */ 710 iommuAmdCmdThreadWakeUpIfNeeded(pDevIns); 711 } 712 else 713 { 714 ASMAtomicAndU64(&pThis->Status.u64, ~IOMMU_STATUS_CMD_BUF_RUNNING); 715 LogFunc(("Command buffer disabled\n")); 716 } 717 } 718 719 return VINF_SUCCESS; 720 } 721 722 723 /** 724 * Writes to the Excluse Range Base Address Register. 725 */ 726 static VBOXSTRICTRC iommuAmdExclRangeBar_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value) 727 { 728 RT_NOREF(pDevIns, iReg); 998 /* Ensure the device table segments are within limits. */ 999 if (NewCtrl.n.u3DevTabSegEn <= pThis->ExtFeat.n.u2DevTabSegSup) 1000 { 1001 IOMMU_CTRL_T const OldCtrl = iommuAmdGetCtrl(pThis); 1002 1003 /* Update the register. */ 1004 ASMAtomicWriteU64(&pThis->Ctrl.u64, NewCtrl.u64); 1005 1006 bool const fNewIommuEn = NewCtrl.n.u1IommuEn; 1007 bool const fOldIommuEn = OldCtrl.n.u1IommuEn; 1008 1009 /* Enable or disable event logging when the bit transitions. */ 1010 bool const fOldEvtLogEn = OldCtrl.n.u1EvtLogEn; 1011 bool const fNewEvtLogEn = NewCtrl.n.u1EvtLogEn; 1012 if ( fOldEvtLogEn != fNewEvtLogEn 1013 || fOldIommuEn != fNewIommuEn) 1014 { 1015 if ( fNewIommuEn 1016 && fNewEvtLogEn) 1017 { 1018 ASMAtomicAndU64(&pThis->Status.u64, ~IOMMU_STATUS_EVT_LOG_OVERFLOW); 1019 ASMAtomicOrU64(&pThis->Status.u64, IOMMU_STATUS_EVT_LOG_RUNNING); 1020 } 1021 else 1022 ASMAtomicAndU64(&pThis->Status.u64, ~IOMMU_STATUS_EVT_LOG_RUNNING); 1023 } 1024 1025 /* Enable or disable command buffer processing when the bit transitions. */ 1026 bool const fOldCmdBufEn = OldCtrl.n.u1CmdBufEn; 1027 bool const fNewCmdBufEn = NewCtrl.n.u1CmdBufEn; 1028 if ( fOldCmdBufEn != fNewCmdBufEn 1029 || fOldIommuEn != fNewIommuEn) 1030 { 1031 if ( fNewCmdBufEn 1032 && fNewIommuEn) 1033 { 1034 ASMAtomicOrU64(&pThis->Status.u64, IOMMU_STATUS_CMD_BUF_RUNNING); 1035 LogFunc(("Command buffer enabled\n")); 1036 1037 /* Wake up the command thread to start processing commands. */ 1038 iommuAmdCmdThreadWakeUpIfNeeded(pDevIns); 1039 } 1040 else 1041 { 1042 ASMAtomicAndU64(&pThis->Status.u64, ~IOMMU_STATUS_CMD_BUF_RUNNING); 1043 LogFunc(("Command buffer disabled\n")); 1044 } 1045 } 1046 } 1047 else 1048 { 1049 LogFunc(("Invalid number of device table segments enabled, exceeds %#x (%#RX64) -> Ignored!\n", 1050 pThis->ExtFeat.n.u2DevTabSegSup, NewCtrl.u64)); 1051 } 1052 1053 return VINF_SUCCESS; 1054 } 1055 1056 1057 /** 1058 * Writes to the Exclusion Range Base Address Register. 1059 */ 1060 static VBOXSTRICTRC iommuAmdExclRangeBar_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value) 1061 { 1062 RT_NOREF(pDevIns, offReg); 729 1063 pThis->ExclRangeBaseAddr.u64 = u64Value & IOMMU_EXCL_RANGE_BAR_VALID_MASK; 730 1064 return VINF_SUCCESS; … … 733 1067 734 1068 /** 735 * Writes to the Exclus eRange Limit Register.736 */ 737 static VBOXSTRICTRC iommuAmdExclRangeLimit_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)738 { 739 RT_NOREF(pDevIns, iReg);1069 * Writes to the Exclusion Range Limit Register. 1070 */ 1071 static VBOXSTRICTRC iommuAmdExclRangeLimit_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value) 1072 { 1073 RT_NOREF(pDevIns, offReg); 740 1074 u64Value &= IOMMU_EXCL_RANGE_LIMIT_VALID_MASK; 741 1075 u64Value |= UINT64_C(0xfff); … … 748 1082 * Writes the Hardware Event Register (Hi). 749 1083 */ 750 static VBOXSTRICTRC iommuAmdHwEvtHi_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)1084 static VBOXSTRICTRC iommuAmdHwEvtHi_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value) 751 1085 { 752 1086 /** @todo IOMMU: Why the heck is this marked read/write by the AMD IOMMU spec? */ 753 RT_NOREF(pDevIns, iReg);1087 RT_NOREF(pDevIns, offReg); 754 1088 LogFlowFunc(("Writing %#RX64 to hardware event (Hi) register!\n", u64Value)); 755 1089 pThis->HwEvtHi.u64 = u64Value; … … 761 1095 * Writes the Hardware Event Register (Lo). 762 1096 */ 763 static VBOXSTRICTRC iommuAmdHwEvtLo_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)1097 static VBOXSTRICTRC iommuAmdHwEvtLo_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value) 764 1098 { 765 1099 /** @todo IOMMU: Why the heck is this marked read/write by the AMD IOMMU spec? */ 766 RT_NOREF(pDevIns, iReg);1100 RT_NOREF(pDevIns, offReg); 767 1101 LogFlowFunc(("Writing %#RX64 to hardware event (Lo) register!\n", u64Value)); 768 1102 pThis->HwEvtLo = u64Value; … … 774 1108 * Writes the Hardware Event Status Register. 775 1109 */ 776 static VBOXSTRICTRC iommuAmdHwEvtStatus_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)777 { 778 RT_NOREF(pDevIns, iReg);1110 static VBOXSTRICTRC iommuAmdHwEvtStatus_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value) 1111 { 1112 RT_NOREF(pDevIns, offReg); 779 1113 780 1114 /* Mask out all unrecognized bits. */ … … 803 1137 * Writes the Device Table Segment Base Address Register. 804 1138 */ 805 static VBOXSTRICTRC iommuAmdDevTabSegBar_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)1139 static VBOXSTRICTRC iommuAmdDevTabSegBar_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value) 806 1140 { 807 1141 RT_NOREF(pDevIns); 808 1142 809 1143 /* Figure out which segment is being written. */ 810 uint8_t const offSegment = ( iReg - IOMMU_MMIO_OFF_DEV_TAB_SEG_FIRST) >> 3;1144 uint8_t const offSegment = (offReg - IOMMU_MMIO_OFF_DEV_TAB_SEG_FIRST) >> 3; 811 1145 uint8_t const idxSegment = offSegment + 1; 812 1146 Assert(idxSegment < RT_ELEMENTS(pThis->aDevTabBaseAddrs)); … … 832 1166 833 1167 1168 #ifndef IOMMU_NEW_REGISTER_ACCESS 834 1169 /** 835 1170 * Writes the MSI Capability Header Register. 836 1171 */ 837 static VBOXSTRICTRC iommuAmdMsiCapHdr_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)838 { 839 RT_NOREF(pThis, iReg);1172 static VBOXSTRICTRC iommuAmdMsiCapHdr_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value) 1173 { 1174 RT_NOREF(pThis, offReg); 840 1175 PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0]; 841 1176 PDMPCIDEV_ASSERT_VALID(pDevIns, pPciDev); … … 851 1186 * Writes the MSI Address (Lo) Register (32-bit). 852 1187 */ 853 static VBOXSTRICTRC iommuAmdMsiAddrLo_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)854 { 855 RT_NOREF(pThis, iReg);1188 static VBOXSTRICTRC iommuAmdMsiAddrLo_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value) 1189 { 1190 RT_NOREF(pThis, offReg); 856 1191 Assert(!RT_HI_U32(u64Value)); 857 1192 PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0]; … … 865 1200 * Writes the MSI Address (Hi) Register (32-bit). 866 1201 */ 867 static VBOXSTRICTRC iommuAmdMsiAddrHi_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)868 { 869 RT_NOREF(pThis, iReg);1202 static VBOXSTRICTRC iommuAmdMsiAddrHi_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value) 1203 { 1204 RT_NOREF(pThis, offReg); 870 1205 Assert(!RT_HI_U32(u64Value)); 871 1206 PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0]; … … 879 1214 * Writes the MSI Data Register (32-bit). 880 1215 */ 881 static VBOXSTRICTRC iommuAmdMsiData_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)882 { 883 RT_NOREF(pThis, iReg);1216 static VBOXSTRICTRC iommuAmdMsiData_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value) 1217 { 1218 RT_NOREF(pThis, offReg); 884 1219 PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0]; 885 1220 PDMPCIDEV_ASSERT_VALID(pDevIns, pPciDev); … … 887 1222 return VINF_SUCCESS; 888 1223 } 889 890 891 /** 892 * Writes the Command Buffer Head Pointer Register (32-bit). 893 */ 894 static VBOXSTRICTRC iommuAmdCmdBufHeadPtr_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value) 895 { 896 RT_NOREF(pDevIns, iReg); 1224 #else 1225 /** 1226 * Writes the MSI Capability Header Register (32-bit) or the MSI Address (Lo) 1227 * Register (32-bit). 1228 */ 1229 static VBOXSTRICTRC iommuAmdMsiCapHdrOrAddrLo_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value) 1230 { 1231 RT_NOREF(pThis); 1232 PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0]; 1233 PDMPCIDEV_ASSERT_VALID(pDevIns, pPciDev); 1234 if (offReg == IOMMU_MMIO_OFF_MSI_CAP_HDR) 1235 { 1236 /* MsiMultMessEn not supported, so only MsiEn is the writable bit. */ 1237 MSI_CAP_HDR_T MsiCapHdr; 1238 MsiCapHdr.u32 = PDMPciDevGetDWord(pPciDev, IOMMU_PCI_OFF_MSI_CAP_HDR); 1239 MsiCapHdr.n.u1MsiEnable = RT_BOOL(u64Value & IOMMU_MSI_CAP_HDR_MSI_EN_MASK); 1240 PDMPciDevSetDWord(pPciDev, IOMMU_PCI_OFF_MSI_CAP_HDR, MsiCapHdr.u32); 1241 } 1242 else 1243 { 1244 AssertMsg(offReg == IOMMU_MMIO_OFF_MSI_ADDR_LO, ("%#x\n", offReg)); 1245 uint32_t const uMsiAddrLo = u64Value & VBOX_MSI_ADDR_VALID_MASK; 1246 PDMPciDevSetDWord(pPciDev, IOMMU_PCI_OFF_MSI_ADDR_LO, uMsiAddrLo); 1247 } 1248 return VINF_SUCCESS; 1249 } 1250 1251 1252 /** 1253 * Writes the MSI Address (Hi) Register (32-bit) or the MSI data register (32-bit). 1254 */ 1255 static VBOXSTRICTRC iommuAmdMsiAddrHiOrData_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value) 1256 { 1257 RT_NOREF(pThis); 1258 PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0]; 1259 PDMPCIDEV_ASSERT_VALID(pDevIns, pPciDev); 1260 if (offReg == IOMMU_MMIO_OFF_MSI_ADDR_HI) 1261 PDMPciDevSetDWord(pPciDev, IOMMU_PCI_OFF_MSI_ADDR_HI, u64Value); 1262 else 1263 { 1264 AssertMsg(offReg == IOMMU_MMIO_OFF_MSI_DATA, ("%#x\n", offReg)); 1265 uint32_t const uMsiData = u64Value & VBOX_MSI_DATA_VALID_MASK; 1266 PDMPciDevSetDWord(pPciDev, IOMMU_PCI_OFF_MSI_DATA, uMsiData); 1267 } 1268 return VINF_SUCCESS; 1269 } 1270 #endif 1271 1272 1273 /** 1274 * Writes the Command Buffer Head Pointer Register. 1275 */ 1276 static VBOXSTRICTRC iommuAmdCmdBufHeadPtr_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value) 1277 { 1278 RT_NOREF(pDevIns, offReg); 897 1279 898 1280 /* … … 932 1314 933 1315 /** 934 * Writes the Command Buffer Tail Pointer Register (32-bit).935 */ 936 static VBOXSTRICTRC iommuAmdCmdBufTailPtr_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)937 { 938 RT_NOREF(pDevIns, iReg);1316 * Writes the Command Buffer Tail Pointer Register. 1317 */ 1318 static VBOXSTRICTRC iommuAmdCmdBufTailPtr_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value) 1319 { 1320 RT_NOREF(pDevIns, offReg); 939 1321 940 1322 /* … … 973 1355 974 1356 /** 975 * Writes the Event Log Head Pointer Register (32-bit).976 */ 977 static VBOXSTRICTRC iommuAmdEvtLogHeadPtr_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)978 { 979 RT_NOREF(pDevIns, iReg);1357 * Writes the Event Log Head Pointer Register. 1358 */ 1359 static VBOXSTRICTRC iommuAmdEvtLogHeadPtr_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value) 1360 { 1361 RT_NOREF(pDevIns, offReg); 980 1362 981 1363 /* … … 1002 1384 1003 1385 /** 1004 * Writes the Event Log Tail Pointer Register (32-bit).1005 */ 1006 static VBOXSTRICTRC iommuAmdEvtLogTailPtr_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)1007 { 1008 RT_NOREF(pDevIns, iReg);1386 * Writes the Event Log Tail Pointer Register. 1387 */ 1388 static VBOXSTRICTRC iommuAmdEvtLogTailPtr_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value) 1389 { 1390 RT_NOREF(pDevIns, offReg); 1009 1391 NOREF(pThis); 1010 1392 … … 1043 1425 1044 1426 /** 1045 * Writes the Status Register (64-bit).1046 */ 1047 static VBOXSTRICTRC iommuAmdStatus_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)1048 { 1049 RT_NOREF(pDevIns, iReg);1427 * Writes the Status Register. 1428 */ 1429 static VBOXSTRICTRC iommuAmdStatus_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value) 1430 { 1431 RT_NOREF(pDevIns, offReg); 1050 1432 1051 1433 /* Mask out all unrecognized bits. */ … … 1068 1450 } 1069 1451 1070 1071 #if 0 1072 /** 1073 * Table 0: Registers-access table. 1074 */ 1075 static const IOMMUREGACC g_aTable0Regs[] = 1076 { 1077 1452 #ifdef IOMMU_NEW_REGISTER_ACCESS 1453 /** 1454 * Register access table 0. 1455 * The MMIO offset of each entry must be a multiple of 8! 1456 */ 1457 static const IOMMUREGACC g_aRegAccess0[] = 1458 { 1459 /* MMIO off. Register name Read function Write function Reg. size */ 1460 { /* 0x00 */ "DEV_TAB_BAR", iommuAmdDevTabBar_r, iommuAmdDevTabBar_w, 8 }, 1461 { /* 0x08 */ "CMD_BUF_BAR", iommuAmdCmdBufBar_r, iommuAmdCmdBufBar_w, 8 }, 1462 { /* 0x10 */ "EVT_LOG_BAR", iommuAmdEvtLogBar_r, iommuAmdEvtLogBar_w, 8 }, 1463 { /* 0x18 */ "CTRL", iommuAmdCtrl_r, iommuAmdCtrl_w, 8 }, 1464 { /* 0x20 */ "EXCL_BAR", iommuAmdExclRangeBar_r, iommuAmdExclRangeBar_w, 8 }, 1465 { /* 0x28 */ "EXCL_RANGE_LIMIT", iommuAmdExclRangeLimit_r, iommuAmdExclRangeLimit_w, 8 }, 1466 { /* 0x30 */ "EXT_FEAT", iommuAmdExtFeat_r, NULL, 8 }, 1467 { /* 0x38 */ "PPR_LOG_BAR", iommuAmdPprLogBar_r, NULL, 8 }, 1468 { /* 0x40 */ "HW_EVT_HI", iommuAmdHwEvtHi_r, iommuAmdHwEvtHi_w, 8 }, 1469 { /* 0x48 */ "HW_EVT_LO", iommuAmdHwEvtLo_r, iommuAmdHwEvtLo_w, 8 }, 1470 { /* 0x50 */ "HW_EVT_STATUS", iommuAmdHwEvtStatus_r, iommuAmdHwEvtStatus_w, 8 }, 1471 { /* 0x58 */ NULL, NULL, NULL, 0 }, 1472 1473 { /* 0x60 */ "SMI_FLT_0", NULL, NULL, 8 }, 1474 { /* 0x68 */ "SMI_FLT_1", NULL, NULL, 8 }, 1475 { /* 0x70 */ "SMI_FLT_2", NULL, NULL, 8 }, 1476 { /* 0x78 */ "SMI_FLT_3", NULL, NULL, 8 }, 1477 { /* 0x80 */ "SMI_FLT_4", NULL, NULL, 8 }, 1478 { /* 0x88 */ "SMI_FLT_5", NULL, NULL, 8 }, 1479 { /* 0x90 */ "SMI_FLT_6", NULL, NULL, 8 }, 1480 { /* 0x98 */ "SMI_FLT_7", NULL, NULL, 8 }, 1481 { /* 0xa0 */ "SMI_FLT_8", NULL, NULL, 8 }, 1482 { /* 0xa8 */ "SMI_FLT_9", NULL, NULL, 8 }, 1483 { /* 0xb0 */ "SMI_FLT_10", NULL, NULL, 8 }, 1484 { /* 0xb8 */ "SMI_FLT_11", NULL, NULL, 8 }, 1485 { /* 0xc0 */ "SMI_FLT_12", NULL, NULL, 8 }, 1486 { /* 0xc8 */ "SMI_FLT_13", NULL, NULL, 8 }, 1487 { /* 0xd0 */ "SMI_FLT_14", NULL, NULL, 8 }, 1488 { /* 0xd8 */ "SMI_FLT_15", NULL, NULL, 8 }, 1489 1490 { /* 0xe0 */ "GALOG_BAR", iommuAmdGALogBar_r, NULL, 8 }, 1491 { /* 0xe8 */ "GALOG_TAIL_ADDR", NULL, NULL, 8 }, 1492 { /* 0xf0 */ "PPR_LOG_B_BAR", iommuAmdPprLogBBaseAddr_r, NULL, 8 }, 1493 { /* 0xf8 */ "PPR_EVT_B_BAR", iommuAmdEvtLogBBaseAddr_r, NULL, 8 }, 1494 1495 { /* 0x100 */ "DEV_TAB_SEG_1", iommuAmdDevTabSegBar_r, iommuAmdDevTabSegBar_w, 8 }, 1496 { /* 0x108 */ "DEV_TAB_SEG_2", iommuAmdDevTabSegBar_r, iommuAmdDevTabSegBar_w, 8 }, 1497 { /* 0x110 */ "DEV_TAB_SEG_3", iommuAmdDevTabSegBar_r, iommuAmdDevTabSegBar_w, 8 }, 1498 { /* 0x118 */ "DEV_TAB_SEG_4", iommuAmdDevTabSegBar_r, iommuAmdDevTabSegBar_w, 8 }, 1499 { /* 0x120 */ "DEV_TAB_SEG_5", iommuAmdDevTabSegBar_r, iommuAmdDevTabSegBar_w, 8 }, 1500 { /* 0x128 */ "DEV_TAB_SEG_6", iommuAmdDevTabSegBar_r, iommuAmdDevTabSegBar_w, 8 }, 1501 { /* 0x130 */ "DEV_TAB_SEG_7", iommuAmdDevTabSegBar_r, iommuAmdDevTabSegBar_w, 8 }, 1502 1503 { /* 0x138 */ "DEV_SPECIFIC_FEAT", iommuAmdDevSpecificFeat_r, NULL, 8 }, 1504 { /* 0x140 */ "DEV_SPECIFIC_CTRL", iommuAmdDevSpecificCtrl_r, NULL, 8 }, 1505 { /* 0x148 */ "DEV_SPECIFIC_STATUS", iommuAmdDevSpecificStatus_r, NULL, 8 }, 1506 1507 { /* 0x150 */ "MSI_VECTOR_0 or MSI_VECTOR_1", iommuAmdDevMsiVector_r, NULL, 4 }, 1508 { /* 0x158 */ "MSI_CAP_HDR or MSI_ADDR_LO", iommuAmdMsiCapHdrOrAddrLo_r, iommuAmdMsiCapHdrOrAddrLo_w, 4 }, 1509 { /* 0x160 */ "MSI_ADDR_HI or MSI_DATA", iommuAmdMsiAddrHiOrData_r, iommuAmdMsiAddrHiOrData_w, 4 }, 1510 { /* 0x168 */ "MSI_MAPPING_CAP_HDR or PERF_OPT_CTRL", NULL, NULL, 4 }, 1511 1512 { /* 0x170 */ "XT_GEN_INTR_CTRL", NULL, NULL, 8 }, 1513 { /* 0x178 */ "XT_PPR_INTR_CTRL", NULL, NULL, 8 }, 1514 { /* 0x180 */ "XT_GALOG_INT_CTRL", NULL, NULL, 8 }, 1078 1515 }; 1079 1080 /** 1081 * Table 1: Registers-access table. 1082 */ 1083 static const IOMMUREGACC g_aTable1Regs[] = 1084 { 1516 AssertCompile(RT_ELEMENTS(g_aRegAccess0) == (IOMMU_MMIO_OFF_QWORD_TABLE_0_END - IOMMU_MMIO_OFF_QWORD_TABLE_0_START) / 8); 1517 1518 /** 1519 * Register access table 1. 1520 * The MMIO offset of each entry must be a multiple of 8! 1521 */ 1522 static const IOMMUREGACC g_aRegAccess1[] = 1523 { 1524 /* MMIO offset Register name Read function Write function Register size. */ 1525 { /* 0x200 */ "MARC_APER_BAR_0", NULL, NULL, 8 }, 1526 { /* 0x208 */ "MARC_APER_RELOC_0", NULL, NULL, 8 }, 1527 { /* 0x210 */ "MARC_APER_LEN_0", NULL, NULL, 8 }, 1528 { /* 0x218 */ "MARC_APER_BAR_1", NULL, NULL, 8 }, 1529 { /* 0x220 */ "MARC_APER_RELOC_1", NULL, NULL, 8 }, 1530 { /* 0x228 */ "MARC_APER_LEN_1", NULL, NULL, 8 }, 1531 { /* 0x230 */ "MARC_APER_BAR_2", NULL, NULL, 8 }, 1532 { /* 0x238 */ "MARC_APER_RELOC_2", NULL, NULL, 8 }, 1533 { /* 0x240 */ "MARC_APER_LEN_2", NULL, NULL, 8 }, 1534 { /* 0x248 */ "MARC_APER_BAR_3", NULL, NULL, 8 }, 1535 { /* 0x250 */ "MARC_APER_RELOC_3", NULL, NULL, 8 }, 1536 { /* 0x258 */ "MARC_APER_LEN_3", NULL, NULL, 8 } 1085 1537 }; 1538 AssertCompile(RT_ELEMENTS(g_aRegAccess1) == (IOMMU_MMIO_OFF_QWORD_TABLE_1_END - IOMMU_MMIO_OFF_QWORD_TABLE_1_START) / 8); 1539 1540 /** 1541 * Register access table 2. 1542 * The MMIO offset of each entry must be a multiple of 8! 1543 */ 1544 static const IOMMUREGACC g_aRegAccess2[] = 1545 { 1546 /* MMIO offset Register name Read Function Write function Register size (bytes) */ 1547 { /* 0x1ff8 */ "RSVD_REG", NULL, NULL, 8 }, 1548 1549 { /* 0x2000 */ "CMD_BUF_HEAD_PTR", iommuAmdCmdBufHeadPtr_r, iommuAmdCmdBufHeadPtr_w, 8 }, 1550 { /* 0x2008 */ "CMD_BUF_TAIL_PTR", iommuAmdCmdBufTailPtr_r , iommuAmdCmdBufTailPtr_w, 8 }, 1551 { /* 0x2010 */ "EVT_LOG_HEAD_PTR", iommuAmdEvtLogHeadPtr_r, iommuAmdEvtLogHeadPtr_w, 8 }, 1552 { /* 0x2018 */ "EVT_LOG_TAIL_PTR", iommuAmdEvtLogTailPtr_r, iommuAmdEvtLogTailPtr_w, 8 }, 1553 1554 { /* 0x2020 */ "STATUS", iommuAmdStatus_r, iommuAmdStatus_w, 8 }, 1555 { /* 0x2028 */ NULL, NULL, NULL, 0 }, 1556 1557 { /* 0x2030 */ "PPR_LOG_HEAD_PTR", NULL, NULL, 8 }, 1558 { /* 0x2038 */ "PPR_LOG_TAIL_PTR", NULL, NULL, 8 }, 1559 1560 { /* 0x2040 */ "GALOG_HEAD_PTR", NULL, NULL, 8 }, 1561 { /* 0x2048 */ "GALOG_TAIL_PTR", NULL, NULL, 8 }, 1562 1563 { /* 0x2050 */ "PPR_LOG_B_HEAD_PTR", NULL, NULL, 8 }, 1564 { /* 0x2058 */ "PPR_LOG_B_TAIL_PTR", NULL, NULL, 8 }, 1565 1566 { /* 0x2060 */ NULL, NULL, NULL, 0 }, 1567 { /* 0x2068 */ NULL, NULL, NULL, 0 }, 1568 1569 { /* 0x2070 */ "EVT_LOG_B_HEAD_PTR", NULL, NULL, 8 }, 1570 { /* 0x2078 */ "EVT_LOG_B_TAIL_PTR", NULL, NULL, 8 }, 1571 1572 { /* 0x2080 */ "PPR_LOG_AUTO_RESP", NULL, NULL, 8 }, 1573 { /* 0x2088 */ "PPR_LOG_OVERFLOW_EARLY", NULL, NULL, 8 }, 1574 { /* 0x2090 */ "PPR_LOG_B_OVERFLOW_EARLY", NULL, NULL, 8 } 1575 }; 1576 AssertCompile(RT_ELEMENTS(g_aRegAccess2) == (IOMMU_MMIO_OFF_QWORD_TABLE_2_END - IOMMU_MMIO_OFF_QWORD_TABLE_2_START) / 8); 1086 1577 #endif 1087 1578 … … 1100 1591 static VBOXSTRICTRC iommuAmdWriteRegister(PPDMDEVINS pDevIns, uint32_t off, uint8_t cb, uint64_t uValue) 1101 1592 { 1593 /* 1594 * Validate the access in case of IOM bug or incorrect assumption. 1595 */ 1102 1596 Assert(off < IOMMU_MMIO_REGION_SIZE); 1103 Assert (cb == 4 || cb == 8);1104 Assert (!(off & (cb - 1)));1597 AssertMsgReturn(cb == 4 || cb == 8, ("Invalid access size %u\n", cb), VINF_SUCCESS); 1598 AssertMsgReturn(!(off & 3), ("Invalid offset %#x\n", off), VINF_SUCCESS); 1105 1599 1106 1600 Log5Func(("off=%#x cb=%u uValue=%#RX64\n", off, cb, uValue)); 1107 1601 1108 1602 PIOMMU pThis = PDMDEVINS_2_DATA(pDevIns, PIOMMU); 1603 #ifndef IOMMU_NEW_REGISTER_ACCESS 1109 1604 switch (off) 1110 1605 { … … 1183 1678 case IOMMU_MMIO_OFF_RSVD_REG: return iommuAmdIgnore_w(pDevIns, pThis, off, uValue); 1184 1679 1185 case IOMMU_MMIO_ CMD_BUF_HEAD_PTR:return iommuAmdCmdBufHeadPtr_w(pDevIns, pThis, off, uValue);1186 case IOMMU_MMIO_ CMD_BUF_TAIL_PTR:return iommuAmdCmdBufTailPtr_w(pDevIns, pThis, off, uValue);1187 case IOMMU_MMIO_ EVT_LOG_HEAD_PTR:return iommuAmdEvtLogHeadPtr_w(pDevIns, pThis, off, uValue);1188 case IOMMU_MMIO_ EVT_LOG_TAIL_PTR:return iommuAmdEvtLogTailPtr_w(pDevIns, pThis, off, uValue);1680 case IOMMU_MMIO_OFF_CMD_BUF_HEAD_PTR: return iommuAmdCmdBufHeadPtr_w(pDevIns, pThis, off, uValue); 1681 case IOMMU_MMIO_OFF_CMD_BUF_TAIL_PTR: return iommuAmdCmdBufTailPtr_w(pDevIns, pThis, off, uValue); 1682 case IOMMU_MMIO_OFF_EVT_LOG_HEAD_PTR: return iommuAmdEvtLogHeadPtr_w(pDevIns, pThis, off, uValue); 1683 case IOMMU_MMIO_OFF_EVT_LOG_TAIL_PTR: return iommuAmdEvtLogTailPtr_w(pDevIns, pThis, off, uValue); 1189 1684 1190 1685 case IOMMU_MMIO_OFF_STATUS: return iommuAmdStatus_w(pDevIns, pThis, off, uValue); … … 1221 1716 } 1222 1717 } 1718 #else 1719 /* 1720 * Figure out which table the register belongs to and validate its index. 1721 */ 1722 PCIOMMUREGACC pReg; 1723 if (off < IOMMU_MMIO_OFF_QWORD_TABLE_0_END) 1724 { 1725 uint32_t const idxReg = off >> 3; 1726 Assert(idxReg < RT_ELEMENTS(g_aRegAccess0)); 1727 pReg = &g_aRegAccess0[idxReg]; 1728 } 1729 else if ( off < IOMMU_MMIO_OFF_QWORD_TABLE_1_END 1730 && off >= IOMMU_MMIO_OFF_QWORD_TABLE_1_START) 1731 { 1732 uint32_t const idxReg = (off - IOMMU_MMIO_OFF_QWORD_TABLE_1_START) >> 3; 1733 Assert(idxReg < RT_ELEMENTS(g_aRegAccess1)); 1734 pReg = &g_aRegAccess1[idxReg]; 1735 } 1736 else if ( off < IOMMU_MMIO_OFF_QWORD_TABLE_2_END 1737 && off >= IOMMU_MMIO_OFF_QWORD_TABLE_2_START) 1738 { 1739 uint32_t const idxReg = (off - IOMMU_MMIO_OFF_QWORD_TABLE_2_START) >> 3; 1740 Assert(idxReg < RT_ELEMENTS(g_aRegAccess2)); 1741 pReg = &g_aRegAccess2[idxReg]; 1742 } 1743 else 1744 { 1745 LogFunc(("Writing unknown register %u (%#x) with %#RX64 -> Ignored\n", off, off, uValue)); 1746 return VINF_SUCCESS; 1747 } 1748 1749 if (pReg->pfnWrite) 1750 { 1751 /* 1752 * If the write access is aligned and matches the register size, dispatch right away. 1753 * This handles all aligned, 32-bit writes as well. 1754 */ 1755 if ( cb == pReg->cb 1756 && !(off & (cb - 1))) 1757 return pReg->pfnWrite(pDevIns, pThis, off, uValue); 1758 1759 /* 1760 * A 32-bit access for a 64-bit register. 1761 * This is writing a 64-bit register since we took care of 32-bit writes above. 1762 * We shouldn't get smaller sizes because we've specified so with IOM. 1763 */ 1764 Assert(cb == 4); 1765 if (!(off & 7)) 1766 { 1767 /* Lower 32-bits are being written. Merge with higher bits of the register. */ 1768 uint64_t uHi; 1769 if (pReg->pfnRead) 1770 { 1771 VBOXSTRICTRC rcStrict = pReg->pfnRead(pDevIns, pThis, off, &uHi); 1772 if (RT_FAILURE(rcStrict)) 1773 { 1774 LogFunc(("Reading off %#x during split write failed! rc=%Rrc\n -> Ignored", off, VBOXSTRICTRC_VAL(rcStrict))); 1775 return rcStrict; 1776 } 1777 } 1778 else 1779 uHi = 0; 1780 uHi &= UINT64_C(0xffffffff00000000); 1781 uValue |= uHi; 1782 1783 /* Perform the full, 64-bit write. */ 1784 return pReg->pfnWrite(pDevIns, pThis, off, uValue); 1785 } 1786 1787 /* Higher 32-bits are being written. Merge with lower bits of the register. */ 1788 Assert(!(off & 3)); 1789 Assert(off > 4); 1790 uint64_t uLo; 1791 if (pReg->pfnRead) 1792 { 1793 VBOXSTRICTRC rcStrict = pReg->pfnRead(pDevIns, pThis, off - 4, &uLo); 1794 if (RT_FAILURE(rcStrict)) 1795 { 1796 LogFunc(("Reading off %#x during split write failed! rc=%Rrc\n -> Ignored", off, VBOXSTRICTRC_VAL(rcStrict))); 1797 return rcStrict; 1798 } 1799 } 1800 else 1801 uLo = 0; 1802 1803 uLo &= UINT64_C(0x00000000ffffffff); 1804 uValue <<= 32; 1805 uValue |= uLo; 1806 1807 /* Perform the full, 64-bit write. */ 1808 return pReg->pfnWrite(pDevIns, pThis, off - 4, uValue); 1809 } 1810 else 1811 LogFunc(("Writing unknown register %u (%#x) with %#RX64 (cb=%u) -> Ignored\n", off, off, uValue, cb)); 1812 1813 return VINF_SUCCESS; 1814 #endif 1223 1815 } 1224 1816 … … 1354 1946 case IOMMU_MMIO_OFF_RSVD_REG: uReg = pThis->RsvdReg; break; 1355 1947 1356 case IOMMU_MMIO_ CMD_BUF_HEAD_PTR:uReg = pThis->CmdBufHeadPtr.u64; break;1357 case IOMMU_MMIO_ CMD_BUF_TAIL_PTR:uReg = pThis->CmdBufTailPtr.u64; break;1358 case IOMMU_MMIO_ EVT_LOG_HEAD_PTR:uReg = pThis->EvtLogHeadPtr.u64; break;1359 case IOMMU_MMIO_ EVT_LOG_TAIL_PTR:uReg = pThis->EvtLogTailPtr.u64; break;1948 case IOMMU_MMIO_OFF_CMD_BUF_HEAD_PTR: uReg = pThis->CmdBufHeadPtr.u64; break; 1949 case IOMMU_MMIO_OFF_CMD_BUF_TAIL_PTR: uReg = pThis->CmdBufTailPtr.u64; break; 1950 case IOMMU_MMIO_OFF_EVT_LOG_HEAD_PTR: uReg = pThis->EvtLogHeadPtr.u64; break; 1951 case IOMMU_MMIO_OFF_EVT_LOG_TAIL_PTR: uReg = pThis->EvtLogTailPtr.u64; break; 1360 1952 1361 1953 case IOMMU_MMIO_OFF_STATUS: uReg = pThis->Status.u64; break; … … 3422 4014 if (fVerbose) 3423 4015 { 3424 pHlp->pfnPrintf(pHlp, " Base address = % RTbool\n", GALogBar.n.u40Base << X86_PAGE_4K_SHIFT);4016 pHlp->pfnPrintf(pHlp, " Base address = %#RX64\n", GALogBar.n.u40Base << X86_PAGE_4K_SHIFT); 3425 4017 pHlp->pfnPrintf(pHlp, " Length = %u (%u entries, %u bytes)\n", uEncodedLen, 3426 4018 cEntries, cbBuffer); … … 4224 4816 */ 4225 4817 rc = PDMDevHlpMmioCreate(pDevIns, IOMMU_MMIO_REGION_SIZE, pPciDev, 0 /* iPciRegion */, iommuAmdMmioWrite, iommuAmdMmioRead, 4226 NULL /* pvUser */, IOMMMIO_FLAGS_READ_DWORD_QWORD | IOMMMIO_FLAGS_WRITE_DWORD_QWORD_ ZEROED,4818 NULL /* pvUser */, IOMMMIO_FLAGS_READ_DWORD_QWORD | IOMMMIO_FLAGS_WRITE_DWORD_QWORD_READ_MISSING, 4227 4819 "AMD-IOMMU", &pThis->hMmio); 4228 4820 AssertLogRelRCReturn(rc, rc);
Note:
See TracChangeset
for help on using the changeset viewer.