Changeset 80058 in vbox for trunk/src/VBox/Devices/VirtIO
- Timestamp:
- Jul 30, 2019 8:17:49 AM (6 years ago)
- svn:sync-xref-src-repo-rev:
- 132495
- Location:
- trunk/src/VBox/Devices/VirtIO
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/VirtIO/Virtio_1_0.cpp
r79973 r80058 35 35 # define QUEUENAME(s, q) (q->pcszName) 36 36 #endif 37 38 /* These ACCESSOR macros handle the most basic kinds of MMIO accesses to fields 39 * virtio 1.0 spec's virtio_pci_common_cfg avoiding a lot of visual bloat. 40 */ 41 42 /** 43 * If the physical address and access length is within the mapped capability struct 44 * the ptrByType will be set to the mapped capability start. Otherwise ptrByType will be NULL. 45 * 46 * Implied parameters: 47 * GPhysAddr - Physical address accessed (via MMIO callback) 48 * cb - Number of bytes to access 49 * 50 * Actual Parameters: 51 * [IN] pCapStruct - Pointer to MMIO mapped capability struct 52 * [IN] type - Capability struct type 53 * [OUT] result - A pointer of type capType that will be set to a mapped capability 54 * if phys. addr / access len is within it's span. 55 * [OUT] offset - The offset of the physical address into the capability if applicable. 56 */ 57 58 #define MATCH_VIRTIO_CAP_STRUCT(pCapStruct, type, result, offset) \ 59 type *result = NULL; \ 60 if ( GCPhysAddr >= (RTGCPHYS)pCapStruct \ 61 && GCPhysAddr < ((RTGCPHYS)pCapStruct + sizeof(type)) \ 62 && cb <= sizeof(type)) \ 63 { \ 64 offset = GCPhysAddr - (RTGCPHYS)pCapStruct; \ 65 result = (type *)pCapStruct; \ 66 } 67 68 #define LOG_ACCESSOR(member, type) \ 69 LogFunc(("Guest %s 0x%x %s %s\n", fWrite ? "wrote" : "read ", \ 70 *(type *)pv, fWrite ? " to" : "from", #member)); 71 72 #define LOG_INDEXED_ACCESSOR(member, type, idx) \ 73 LogFunc(("Guest %s 0x%x %s %s[%d]\n", fWrite ? "wrote" : "read ", \ 74 *(type *)pv, fWrite ? " to" : "from", #member, idx)); 75 76 #define ACCESSOR(member, type) \ 77 { \ 78 if (fWrite) \ 79 { \ 80 pVirtio->member = *(type *)pv; \ 81 } \ 82 else \ 83 { \ 84 *(type *)pv = pVirtio->member; \ 85 } \ 86 LOG_ACCESSOR(member, type); \ 87 } 88 #define ACCESSOR_WITH_IDX(member, type, idx) \ 89 { \ 90 if (fWrite) \ 91 { \ 92 pVirtio->member[idx] = *(type *)pv; \ 93 } \ 94 else \ 95 { \ 96 *(type *)pv = pVirtio->member[idx]; \ 97 } \ 98 LOG_INDEXED_ACCESSOR(member, type, idx); \ 99 } 100 101 #define ACCESSOR_READONLY(member, type) \ 102 { \ 103 if (fWrite) \ 104 { \ 105 LogFunc(("Guest attempted to write readonly virtio_pci_common_cfg.%s\n", #member)); \ 106 AssertMsgFailed(("bad access\n")); \ 107 } \ 108 else \ 109 { \ 110 *(type *)pv = pVirtio->member; \ 111 LOG_ACCESSOR(member, type); \ 112 } \ 113 } 114 115 #define ACCESSOR_READONLY_WITH_IDX(member, type, idx) \ 116 { \ 117 if (fWrite) \ 118 { \ 119 LogFunc(("Guest attempted to write readonly virtio_pci_common_cfg.%s[%d]\n", #member, idx)); \ 120 AssertMsgFailed(("bad access\n")); \ 121 } \ 122 else \ 123 { \ 124 *(type *)pv = pVirtio->member[idx]; \ 125 LOG_INDEXED_ACCESSOR(member, type, idx); \ 126 } \ 127 } 128 37 129 38 130 #ifdef VBOX_DEVICE_STRUCT_TESTCASE … … 316 408 } 317 409 318 void virtioReset(PVIRTIOSTATE pState) 319 { 320 321 RT_NOREF(pState); 322 /* PK TODO Adapt to VirtIO 1.0 410 int virtioReset(PVIRTIOSTATE pVirtio) 411 { 412 RT_NOREF(pVirtio); 413 /* PK TODO Adapt to VirtIO 1.09 323 414 pState->uGuestFeatures = 0; 324 415 pState->uQueueSelector = 0; … … 329 420 virtQueueReset(&pState->Queues[i]); 330 421 */ 422 virtioNotify(pVirtio); 423 return VINF_SUCCESS; 331 424 } 332 425 … … 374 467 375 468 #ifdef IN_RING3 376 377 /**378 * Gets the pointer to the status LED of a unit.379 *380 * @returns VBox status code.381 * @param pInterface Pointer to the interface structure.382 * @param iLUN The unit which status LED we desire.383 * @param ppLed Where to store the LED pointer.384 * @thread EMT385 */386 static DECLCALLBACK(int) virtioQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed)387 {388 VIRTIOSTATE *pState = IFACE_TO_STATE(pInterface, ILeds);389 int rc = VERR_PDM_LUN_NOT_FOUND;390 391 if (iLUN == 0)392 {393 *ppLed = &pState->led;394 rc = VINF_SUCCESS;395 }396 return rc;397 }398 399 /**400 * Turns on/off the write status LED.401 *402 * @returns VBox status code.403 * @param pState Pointer to the device state structure.404 * @param fOn New LED state.405 */406 void virtioSetWriteLed(PVIRTIOSTATE pState, bool fOn)407 {408 LogFlow(("%s virtioSetWriteLed: %s\n", INSTANCE(pState), fOn ? "on" : "off"));409 if (fOn)410 pState->led.Asserted.s.fWriting = pState->led.Actual.s.fWriting = 1;411 else412 pState->led.Actual.s.fWriting = fOn;413 }414 415 /**416 * Turns on/off the read status LED.417 *418 * @returns VBox status code.419 * @param pState Pointer to the device state structure.420 * @param fOn New LED state.421 */422 void virtioSetReadLed(PVIRTIOSTATE pState, bool fOn)423 {424 LogFlow(("%s virtioSetReadLed: %s\n", INSTANCE(pState), fOn ? "on" : "off"));425 if (fOn)426 pState->led.Asserted.s.fReading = pState->led.Actual.s.fReading = 1;427 else428 pState->led.Actual.s.fReading = fOn;429 }430 469 431 470 … … 575 614 } 576 615 616 void virtioNotify(PVIRTIOSTATE pVirtio) 617 { 618 RT_NOREF(pVirtio); 619 } 620 621 static void virtioResetDevice(PVIRTIOSTATE pVirtio) 622 { 623 RT_NOREF(pVirtio); 624 LogFunc(("")); 625 pVirtio->uDeviceStatus = 0; 626 } 627 628 /** 629 * Handle accesses to Common Configuration capability 630 * 631 * @returns VBox status code 632 * 633 * @param pVirtio Virtio instance state 634 * @param fWrite If write access (otherwise read access) 635 * @param pv Pointer to location to write to or read from 636 * @param cb Number of bytes to read or write 637 */ 638 int virtioCommonCfgAccessed(PVIRTIOSTATE pVirtio, int fWrite, off_t uoff, void const *pv) 639 { 640 int rv = VINF_SUCCESS; 641 if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uDeviceFeature)) 642 { 643 if (fWrite) /* Guest WRITE pCommonCfg->uDeviceFeature */ 644 { 645 AssertMsgFailed(("Guest attempted to write readonly virtio_pci_common_cfg.device_feature\n")); 646 } 647 else /* Guest WRITE pCommonCfg->uDeviceFeature */ 648 { 649 switch(pVirtio->uFeaturesOfferedSelect) 650 { 651 case 0: 652 pVirtio->uFeaturesOffered = *(uint32_t *)pv; 653 LOG_ACCESSOR(uFeaturesOffered, uint32_t); 654 break; 655 case 1: 656 pVirtio->uFeaturesOffered = (uint64_t)(*(uint32_t *)pv) << 32; 657 LOG_ACCESSOR(uFeaturesOffered, uint32_t); 658 break; 659 default: 660 Log(("Guest selected out of range pVirtio->uDeviceFeature (%d), returning 0\n", 661 pVirtio->uFeaturesOfferedSelect)); 662 } 663 } 664 } 665 else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uDriverFeature)) 666 { 667 if (fWrite) /* Guest WRITE pCommonCfg->uDriverFeature */ 668 { 669 switch(pVirtio->uFeaturesOfferedSelect) 670 { 671 case 0: 672 pVirtio->uFeaturesAccepted = *(uint32_t *)pv; 673 LOG_ACCESSOR(uFeaturesAccepted, uint32_t); 674 break; 675 case 1: 676 pVirtio->uFeaturesAccepted = (uint64_t)(*(uint32_t *)pv) << 32; 677 LOG_ACCESSOR(uFeaturesAccepted, uint32_t); 678 break; 679 } 680 } 681 else /* Guest READ pCommonCfg->uDriverFeature */ 682 { 683 switch(pVirtio->uFeaturesOfferedSelect) 684 { 685 case 0: 686 *(uint32_t *)pv = pVirtio->uFeaturesAccepted & 0xffffffff; 687 LOG_ACCESSOR(uFeaturesAccepted, uint32_t); 688 break; 689 case 1: 690 *(uint32_t *)pv = (pVirtio->uFeaturesAccepted >> 32) & 0xffffffff; 691 LOG_ACCESSOR(uFeaturesAccepted, uint32_t); 692 break; 693 } 694 } 695 } 696 else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uNumQueues)) 697 { 698 if (fWrite) 699 { 700 AssertMsgFailed(("Guest attempted to write readonly virtio_pci_common_cfg.num_queues\n")); 701 } 702 else 703 { 704 *(uint16_t *)pv = MAX_QUEUES; 705 Log(("Guest read 0x%x from pVirtio->uNumQueues\n", MAX_QUEUES)); 706 } 707 } 708 else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uDeviceStatus)) 709 { 710 if (fWrite) /* Guest WRITE pCommonCfg->uDeviceStatus */ 711 { 712 pVirtio->uDeviceStatus = *(uint8_t *)pv; 713 LogFunc(("Driver wrote uDeviceStatus:\n")); 714 showDeviceStatus(pVirtio->uDeviceStatus); 715 if (pVirtio->uDeviceStatus == 0) 716 virtioResetDevice(pVirtio); 717 } 718 else /* Guest READ pCommonCfg->uDeviceStatus */ 719 { 720 LogFunc(("Driver read uDeviceStatus:\n")); 721 *(uint32_t *)pv = pVirtio->uDeviceStatus; 722 showDeviceStatus(pVirtio->uDeviceStatus); 723 } 724 } 725 else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uMsixConfig)) 726 { 727 ACCESSOR(uMsixConfig, uint32_t); 728 } 729 else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uDeviceFeatureSelect)) 730 { 731 ACCESSOR(uFeaturesOfferedSelect, uint32_t); 732 } 733 else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uDriverFeatureSelect)) 734 { 735 ACCESSOR(uFeaturesAcceptedSelect, uint32_t); 736 } 737 else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uConfigGeneration)) 738 { 739 ACCESSOR_READONLY(uConfigGeneration, uint8_t); 740 } 741 else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uQueueSelect)) 742 { 743 ACCESSOR(uQueueSelect, uint16_t); 744 } 745 else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uQueueSize)) 746 { 747 ACCESSOR_WITH_IDX(uQueueSize, uint16_t, pVirtio->uQueueSelect); 748 } 749 else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uQueueMsixVector)) 750 { 751 ACCESSOR_WITH_IDX(uQueueMsixVector, uint16_t, pVirtio->uQueueSelect); 752 } 753 else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uQueueEnable)) 754 { 755 ACCESSOR_WITH_IDX(uQueueEnable, uint16_t, pVirtio->uQueueSelect); 756 } 757 else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uQueueNotifyOff)) 758 { 759 ACCESSOR_READONLY_WITH_IDX(uQueueNotifyOff, uint16_t, pVirtio->uQueueSelect); 760 } 761 else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uQueueDesc)) 762 { 763 ACCESSOR_WITH_IDX(uQueueDesc, uint64_t, pVirtio->uQueueSelect); 764 } 765 else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uQueueAvail)) 766 { 767 ACCESSOR_WITH_IDX(uQueueAvail, uint64_t, pVirtio->uQueueSelect); 768 } 769 else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uQueueUsed)) 770 { 771 ACCESSOR_WITH_IDX(uQueueUsed, uint64_t, pVirtio->uQueueSelect); 772 } 773 else 774 { 775 776 AssertMsgFailed(("virtio: Bad common cfg offset \n")); 777 } 778 return rv; 779 } 577 780 578 781 /** … … 587 790 * @param cb Number of bytes read. 588 791 */ 589 PDMBOTHCBDECL(int) virtioPciCapMemRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb) 590 { 591 /* PK New feature! */ 592 792 PDMBOTHCBDECL(int) virtioR3MmioRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb) 793 { 593 794 RT_NOREF(pvUser); 795 PVIRTIOSTATE pVirtio = PDMINS_2_DATA(pDevIns, PVIRTIOSTATE); 594 796 int rc = VINF_SUCCESS; 595 797 596 LogFunc(("Read (MMIO) VirtIO capabilities\n")); 597 PVIRTIOSTATE pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSTATE); 598 599 /* TBD: This should be called only if VIRTIO_PCI_CAP_DEVICE_CFG capability is being accessed */ 600 rc = pThis->pfnVirtioDevCapRead(pDevIns, GCPhysAddr, pv, cb); 798 //#ifdef LOG_ENABLED 799 // LogFlowFunc(("pVirtio=%#p GCPhysAddr=%RGp pv=%#p{%.*Rhxs} cb=%u\n", pVirtio, GCPhysAddr, pv, cb, pv, cb)); 800 //#endif 801 off_t uoff = 0; 802 MATCH_VIRTIO_CAP_STRUCT(pVirtio->pGcPhysCommonCfg, VIRTIO_PCI_COMMON_CFG_T, pCommonCfg, uoff); 803 MATCH_VIRTIO_CAP_STRUCT(pVirtio->pGcPhysIsrCap, VIRTIO_PCI_ISR_CAP_T, pIsrCap, uoff); 804 #if HAVE_VIRTIO_DEVICE_SPECIFIC_CAP 805 MATCH_VIRTIO_CAP_STRUCT(pVirtio->pGcPhysDeviceCap, VIRTIO_PCI_DEVICE_CAP_T, pDeviceCap, uoff); 806 #endif 807 /* Note: The notify capability is handled differently as per VirtIO 1.0 spec 4.1.4.4 */ 808 809 if (pCommonCfg) 810 virtioCommonCfgAccessed(pVirtio, 0 /* fWrite */, uoff, pv); 811 else if (pIsrCap) 812 { 813 *(uint8_t *)pv = pVirtio->fQueueInterrupt | pVirtio->fDeviceConfigInterrupt << 1; 814 LogFunc(("Read 0x%s from pIsrCap\n", *(uint8_t *)pv)); 815 } 816 #if HAVE_VIRTIO_DEVICE_SPECIFIC_CAP 817 else if (pDeviceCap) 818 rc = pThis->pfnVirtioDevCapRead(pDevIns, GCPhysAddr, pv, cb); 819 #endif 820 else 821 AssertMsgFailed(("virtio: Write outside of capabilities region\n")); 822 601 823 return rc; 602 824 } 603 604 825 #if TBD 826 /** 827 * Callback function for reading from the PCI configuration space. 828 * 829 * @returns The register value. 830 * @param pDevIns Pointer to the device instance the PCI device 831 * belongs to. 832 * @param pPciDev Pointer to PCI device. Use pPciDev->pDevIns to get the device instance. 833 * @param uAddress The configuration space register address. [0..4096] 834 * @param cb The register size. [1,2,4] 835 * 836 * @remarks Called with the PDM lock held. The device lock is NOT take because 837 * that is very likely be a lock order violation. 838 */ 839 static DECLCALLBACK(uint32_t) virtioPciConfigRead(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, 840 uint32_t uAddress, unsigned cb) 841 { 842 PVIRTIOSTATE pVirtio = PDMINS_2_DATA(pDevIns, PVIRTIOSTATE); 843 int rc = VINF_SUCCESS; 844 845 LogFunc(("uAddress: %d, uPciConfigDataOffset: %d\n", uAddress, pVirtio->uPciConfigDataOffset)); 846 847 if (uAddress == pVirtio->uPciConfigDataOffset) 848 Log(("Read uPciConfigDataOffset\n")); 849 rc = pVirtio->pfnPciConfigReadOld(pDevIns, pPciDev, uAddress, cb); 850 return rc; 851 852 } 853 854 /** 855 * Callback function for writing to the PCI configuration space. 856 * 857 * @returns VINF_SUCCESS or PDMDevHlpDBGFStop status. 858 * 859 * @param pDevIns Pointer to the device instance the PCI device 860 * belongs to. 861 * @param pPciDev Pointer to PCI device. Use pPciDev->pDevIns to get the device instance. 862 * @param uAddress The configuration space register address. [0..4096] 863 * @param u32Value The value that's being written. The number of bits actually used from 864 * this value is determined by the cb parameter. 865 * @param cb The register size. [1,2,4] 866 * 867 * @remarks Called with the PDM lock held. The device lock is NOT take because 868 * that is very likely be a lock order violation. 869 */ 870 static DECLCALLBACK(VBOXSTRICTRC) virtioPciConfigWrite(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, 871 uint32_t uAddress, uint32_t u32Value, unsigned cb) 872 { 873 PVIRTIOSTATE pVirtio = PDMINS_2_DATA(pDevIns, PVIRTIOSTATE); 874 VBOXSTRICTRC strictRc; 875 876 LogFunc(("uAddress: %d, uPciConfigDataOffset: %d\n", uAddress, pVirtio->uPciConfigDataOffset)); 877 if (uAddress == pVirtio->uPciConfigDataOffset) 878 Log(("Wrote uPciConfigDataOffset\n")); 879 strictRc = pVirtio->pfnPciConfigWriteOld(pDevIns, pPciDev, uAddress, u32Value, cb); 880 return strictRc; 881 } 882 #endif 605 883 /** 606 884 * Memory mapped I/O Handler for PCI Capabilities write operations. … … 614 892 * @param cb Number of bytes to write. 615 893 */ 616 PDMBOTHCBDECL(int) virtioPciCapMemWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb) 617 { 618 619 /* PK New feature! */ 894 PDMBOTHCBDECL(int) virtioR3MmioWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb) 895 { 896 620 897 RT_NOREF(pvUser); 898 PVIRTIOSTATE pVirtio = PDMINS_2_DATA(pDevIns, PVIRTIOSTATE); 621 899 int rc = VINF_SUCCESS; 622 LogFunc(("Write (MMIO) Virtio capabilities\n")); 623 PVIRTIOSTATE pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSTATE); 624 625 /* TBD: This should be called only if VIRTIO_PCI_CAP_DEVICE_CFG capability is being accessed */ 626 rc = pThis->pfnVirtioDevCapWrite(pDevIns, GCPhysAddr, pv,cb); 900 901 #ifdef LOG_ENABLED 902 // LogFunc(("pVirtio=%#p GCPhysAddr=%RGp pv=%#p{%.*Rhxs} cb=%u\n", pVirtio, GCPhysAddr, pv, cb, pv, cb)); 903 #endif 904 off_t uoff = 0; 905 906 MATCH_VIRTIO_CAP_STRUCT(pVirtio->pGcPhysCommonCfg, VIRTIO_PCI_COMMON_CFG_T, pCommonCfg, uoff); 907 MATCH_VIRTIO_CAP_STRUCT(pVirtio->pGcPhysIsrCap, VIRTIO_PCI_ISR_CAP_T, pIsrCap, uoff); 908 #if HAVE_VIRTIO_DEVICE_SPECIFIC_CAP 909 MATCH_VIRTIO_CAP_STRUCT(pVirtio->pGcPhysDeviceCap, VIRTIO_PCI_DEVICE_CAP_T, pDeviceCap, uoff); 910 #endif 911 912 if (pCommonCfg) 913 virtioCommonCfgAccessed(pVirtio, 1 /* fWrite */, uoff, pv); 914 else if (pIsrCap) 915 { 916 pVirtio->fQueueInterrupt = (*(uint8_t *)pv) & 1; 917 pVirtio->fDeviceConfigInterrupt = !!(*((uint8_t *)pv) & 2); 918 Log(("pIsrCap... setting fQueueInterrupt=%d fDeviceConfigInterrupt=%d\n", 919 pVirtio->fQueueInterrupt, pVirtio->fDeviceConfigInterrupt)); 920 } 921 #if HAVE_VIRTIO_DEVICE_SPECIFIC_CAP 922 else if (pDeviceCap) 923 rc = pThis->pfnVirtioDevCapWrite(pDevIns, GCPhysAddr, pv, cb); 924 #endif 925 else 926 AssertMsgFailed(("virtio: Write outside of capabilities region\n")); 627 927 628 928 return rc; 629 929 } 930 630 931 631 932 /** … … 636 937 { 637 938 RT_NOREF3(pPciDev, iRegion, enmType); 638 PVIRTIOSTATE p This= PDMINS_2_DATA(pDevIns, PVIRTIOSTATE);939 PVIRTIOSTATE pVirtio = PDMINS_2_DATA(pDevIns, PVIRTIOSTATE); 639 940 int rc = VINF_SUCCESS; 640 941 641 942 Assert(cb >= 32); 642 643 LogFunc(("virtIO controller PCI Capabilities mapped at GCPhysAddr=%RGp cb=%RGp\n", GCPhysAddress, cb));644 943 645 944 /* We use the assigned size here, because we currently only support page aligned MMIO ranges. */ 646 945 rc = PDMDevHlpMMIORegister(pDevIns, GCPhysAddress, cb, NULL /*pvUser*/, 647 946 IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU, 648 virtio PciCapMemWrite, virtioPciCapMemRead,947 virtioR3MmioWrite, virtioR3MmioRead, 649 948 "virtio-scsi MMIO"); 650 pThis->GCPhysPciCapBase = RT_SUCCESS(rc) ? GCPhysAddress : 0; 949 950 LogFunc(("virtio: PCI Capabilities mapped at GCPhysAddr=%RGp cb=%RGp, region=%d\n", GCPhysAddress, cb, iRegion)); 951 952 if (RT_SUCCESS(rc)) 953 { 954 pVirtio->GCPhysPciCapBase = GCPhysAddress; 955 pVirtio->pGcPhysCommonCfg = (PVIRTIO_PCI_COMMON_CFG_T)(GCPhysAddress + pVirtio->uCommonCfgOffset); 956 pVirtio->pGcPhysNotifyCap = (PVIRTIO_PCI_NOTIFY_CAP_T)(GCPhysAddress + pVirtio->uNotifyCapOffset); 957 pVirtio->pGcPhysIsrCap = (PVIRTIO_PCI_ISR_CAP_T)(GCPhysAddress + pVirtio->uIsrCapOffset); 958 pVirtio->pGcPhysPciCfgCap = (PVIRTIO_PCI_CFG_CAP_T)(GCPhysAddress + pVirtio->uPciCfgCapOffset); 959 #ifdef HAVE_VIRTIO_DEVICE_SPECIFIC_CAP 960 pVirtio->pGcPhysDeviceCap = (PVIRTIO_PCI_DEVICE_CAP_T)(GCPhysAddress + pVirtio->uuDeviceCapOffset); 961 #endif 962 } 651 963 return rc; 652 964 } … … 656 968 * @interface_method_impl{PDMIBASE,pfnQueryInterface} 657 969 */ 658 void *virtioQueryInterface( struct PDMIBASE *pInterface, const char *pszIID)970 void *virtioQueryInterface(PPDMIBASE pInterface, const char *pszIID) 659 971 { 660 972 VIRTIOSTATE *pThis = IFACE_TO_STATE(pInterface, IBase); … … 662 974 663 975 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase); 664 PDMIBASE_RETURN_INTERFACE(pszIID, PDMILEDPORTS, &pThis->ILeds);665 976 return NULL; 666 977 } 667 978 979 /** 980 * Get VirtIO available host-side features 981 * 982 * @returns feature bits selected or 0 if selector out of range. 983 * 984 * @param pState Virtio state 985 * @param uSelect Selects which 32-bit set of feature information to return 986 */ 987 988 static uint64_t virtioGetHostFeatures(PVIRTIOSTATE pVirtio) 989 { 990 return pVirtio->uFeaturesOffered; 991 } 992 993 /** 994 * 995 * Set VirtIO available host-side features 996 * 997 * @returns VBox status code 998 * 999 * @param pState Virtio state 1000 * @param uFeaturesOffered Feature bits (0-63) to set 1001 */ 1002 1003 static int virtioSetHostFeatures(PVIRTIOSTATE pVirtio, uint64_t uFeaturesOffered) 1004 { 1005 pVirtio->uFeaturesOffered = VIRTIO_F_VERSION_1 | uFeaturesOffered; 1006 return VINF_SUCCESS; 1007 } 668 1008 669 1009 /** … … 678 1018 { 679 1019 Log(("%s Destroying PCI instance\n", INSTANCE(pState))); 680 681 1020 return VINF_SUCCESS; 682 1021 } … … 712 1051 * @param devCapWriteCallback Client function to call back to handle device specific capabilities 713 1052 * @param cbDevSpecificCap Size of device specific struct 714 */ 715 int virtioConstruct(PPDMDEVINS pDevIns, PVIRTIOSTATE pVirtio, int iInstance, 716 PVIRTIOPCIPARAMS pPciParams, const char *pcszNameFmt, 717 uint32_t nQueues, uint32_t uVirtioRegion, 1053 * @param uNotifyOffMultiplier See VirtIO 1.0 spec 4.1.4.4 re: virtio_pci_notify_cap 1054 */ 1055 1056 int virtioConstruct(PPDMDEVINS pDevIns, PVIRTIOSTATE pVirtio, int iInstance, PVIRTIOPCIPARAMS pPciParams, 1057 PPVIRTIOCALLBACKS ppVirtioCallbacks, const char *pcszNameFmt, uint32_t nQueues, uint32_t uVirtioRegion, 718 1058 PFNVIRTIODEVCAPREAD devCapReadCallback, PFNVIRTIODEVCAPWRITE devCapWriteCallback, 719 uint16_t cbDevSpecificCap) 720 { 721 RT_NOREF(nQueues); 1059 uint16_t cbDevSpecificCap, uint32_t uNotifyOffMultiplier) 1060 { 1061 pVirtio->nQueues = nQueues; 1062 pVirtio->uNotifyOffMultiplier = uNotifyOffMultiplier; 722 1063 723 1064 /* Init handles and log related stuff. */ 724 1065 RTStrPrintf(pVirtio->szInstance, sizeof(pVirtio->szInstance), pcszNameFmt, iInstance); 725 1066 726 pVirtio->pDevInsR3 = pDevIns; 727 pVirtio->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns); 728 pVirtio->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns); 729 pVirtio->led.u32Magic = PDMLED_MAGIC; 730 pVirtio->ILeds.pfnQueryStatusLed = virtioQueryStatusLed; 1067 VIRTIOCALLBACKS virtioCallbacks; 1068 virtioCallbacks.pfnSetHostFeatures = virtioSetHostFeatures; 1069 virtioCallbacks.pfnGetHostFeatures = virtioGetHostFeatures; 1070 virtioCallbacks.pfnReset = virtioReset; 1071 *ppVirtioCallbacks = &virtioCallbacks; 1072 1073 pVirtio->pDevInsR3 = pDevIns; 1074 pVirtio->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns); 1075 pVirtio->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns); 1076 pVirtio->uDeviceStatus = 0; 731 1077 pVirtio->pfnVirtioDevCapRead = devCapReadCallback; 732 1078 pVirtio->pfnVirtioDevCapWrite = devCapWriteCallback; … … 753 1099 pVirtio->IBase = pDevIns->IBase; 754 1100 755 rc = PDMDevHlpPCIIORegionRegister(pDevIns, uVirtioRegion, 32, PCI_ADDRESS_SPACE_MEM, virtioR3Map); 756 if (RT_FAILURE(rc)) 757 return PDMDEV_SET_ERROR(pDevIns, rc, 758 N_("virtio: cannot register PCI Capabilities address space")); /* can we put params in this error? */ 759 760 /** Build PCI vendor-specific capabilities list for exchanging 761 * VirtIO device capabilities with driver */ 762 1101 /** Construct & map PCI vendor-specific capabilities for virtio host negotiation with guest driver */ 1102 1103 #if 0 && defined(VBOX_WITH_MSI_DEVICES) /* T.B.D. */ 1104 uint8_t fMsiSupport = true; 1105 #else 763 1106 uint8_t fMsiSupport = false; 764 #if 0 && defined(VBOX_WITH_MSI_DEVICES) /* T.B.D. */765 fMsiSupport = true;766 1107 #endif 1108 767 1109 uint8_t uCfgCapOffset = 0x40; 768 /* Capability will be mapped via VirtIO 1.0: struct virtio_pci_common_cfg (VIRTIOCOMMONCFG)*/ 769 PVIRTIOPCICAP pCfg = pVirtio->pCommonCfg = (PVIRTIOPCICAP)&pVirtio->dev.abConfig[uCfgCapOffset]; 1110 PVIRTIO_PCI_NOTIFY_CAP_T pNotifyCap; 1111 PVIRTIO_PCI_CAP_T pCommonCfg, pIsrCap; 1112 #ifdef HAVE_VIRTIO_DEVICE_SPECIFIC_CAP 1113 PVIRTIO_PCI_CAP_T pDeviceCap; 1114 #endif 1115 uint32_t cbVirtioCaps = 0; 1116 1117 /* Capability will be mapped via VirtIO 1.0: struct virtio_pci_cfg_cap (VIRTIO_PCI_CAP_T) */ 1118 pVirtio->pPciCfgCap = (PVIRTIO_PCI_CFG_CAP_T)&pVirtio->dev.abConfig[uCfgCapOffset]; 1119 pVirtio->uPciConfigDataOffset = 0x40 + sizeof(VIRTIO_PCI_CAP_T); 1120 PVIRTIO_PCI_CAP_T pCfg = (PVIRTIO_PCI_CAP_T)pVirtio->pPciCfgCap; 770 1121 pCfg->uCapVndr = VIRTIO_PCI_CAP_ID_VENDOR; 771 pCfg->uCapNext = uCfgCapOffset += sizeof(VIRTIOPCICAP); 1122 pCfg->uCapNext = uCfgCapOffset += sizeof(VIRTIO_PCI_CFG_CAP_T); 1123 pCfg->uCapLen = sizeof(VIRTIO_PCI_CFG_CAP_T); 1124 pCfg->uCfgType = VIRTIO_PCI_CAP_PCI_CFG; 1125 pCfg->uBar = uVirtioRegion; 1126 pCfg->uOffset = pVirtio->uPciCfgCapOffset = 0; 1127 pCfg->uLength = sizeof(VIRTIO_PCI_CFG_CAP_T); 1128 cbVirtioCaps += pCfg->uLength; 1129 1130 /* Capability will be mapped via VirtIO 1.0: struct virtio_pci_common_cfg (VIRTIO_PCI_COMMON_CFG_T)*/ 1131 pCfg = pCommonCfg = (PVIRTIO_PCI_CAP_T)&pVirtio->dev.abConfig[uCfgCapOffset]; 1132 pCfg->uCapVndr = VIRTIO_PCI_CAP_ID_VENDOR; 1133 pCfg->uCapNext = uCfgCapOffset += sizeof(VIRTIO_PCI_CAP_T); 1134 pCfg->uCapLen = sizeof(VIRTIO_PCI_CAP_T); 772 1135 pCfg->uCfgType = VIRTIO_PCI_CAP_COMMON_CFG; 773 1136 pCfg->uBar = uVirtioRegion; 774 pCfg->uOffset = 0; 775 pCfg->uLength = sizeof(VIRTIOPCICAP); 776 777 /* Capability will be mapped via VirtIO 1.0: struct virtio_pci_notify_cap (VIRTIONOTIFYCAP)*/ 778 pCfg = pVirtio->pNotifyCap = (PVIRTIOPCICAP)&pVirtio->dev.abConfig[uCfgCapOffset]; 1137 pCfg->uOffset = pVirtio->uCommonCfgOffset = pVirtio->pPciCfgCap->pciCap.uOffset + sizeof(VIRTIO_PCI_CFG_CAP_T); 1138 pCfg->uLength = sizeof(VIRTIO_PCI_COMMON_CFG_T); 1139 cbVirtioCaps += pCfg->uLength; 1140 1141 /* Capability will be mapped via VirtIO 1.0: struct virtio_pci_notify_cap (VIRTIO_PCI_NOTIFY_CAP_T)*/ 1142 pNotifyCap = (PVIRTIO_PCI_NOTIFY_CAP_T)&pVirtio->dev.abConfig[uCfgCapOffset]; 1143 pCfg = (PVIRTIO_PCI_CAP_T)pNotifyCap; 779 1144 pCfg->uCapVndr = VIRTIO_PCI_CAP_ID_VENDOR; 780 pCfg->uCapNext = uCfgCapOffset += sizeof(VIRTIOPCICAP); 1145 pCfg->uCapNext = uCfgCapOffset += sizeof(VIRTIO_PCI_NOTIFY_CAP_T); 1146 pCfg->uCapLen = sizeof(VIRTIO_PCI_NOTIFY_CAP_T); 781 1147 pCfg->uCfgType = VIRTIO_PCI_CAP_NOTIFY_CFG; 782 1148 pCfg->uBar = uVirtioRegion; 783 pCfg->uOffset = pVirtio->pCommonCfg->uOffset + sizeof(VIRTIOCOMMONCFG); 784 pCfg->uLength = sizeof(VIRTIOPCICAP); 785 786 /* Capability will be mapped via VirtIO 1.0: uint8_t (VIRTIOISRCAP) */ 787 pCfg = pVirtio->pISRCap = (PVIRTIOPCICAP)&pVirtio->dev.abConfig[uCfgCapOffset]; 1149 pCfg->uOffset = pVirtio->uNotifyCapOffset = pCommonCfg->uOffset + sizeof(VIRTIO_PCI_COMMON_CFG_T); 1150 pCfg->uLength = sizeof(VIRTIO_PCI_NOTIFY_CAP_T); 1151 pNotifyCap->uNotifyOffMultiplier = uNotifyOffMultiplier; 1152 cbVirtioCaps += pCfg->uLength; 1153 1154 /* Capability will be mapped via VirtIO 1.0: uint8_t (VIRTIO_PCI_ISR_CAP_T) */ 1155 pCfg = pIsrCap = (PVIRTIO_PCI_CAP_T)&pVirtio->dev.abConfig[uCfgCapOffset]; 788 1156 pCfg->uCapVndr = VIRTIO_PCI_CAP_ID_VENDOR; 789 pCfg->uCapNext = uCfgCapOffset += sizeof(VIRTIOPCICAP); 1157 pCfg->uCapNext = (uint8_t)(fMsiSupport || cbDevSpecificCap ? (uCfgCapOffset += sizeof(VIRTIO_PCI_ISR_CAP_T)) : 0); 1158 pCfg->uCapLen = sizeof(VIRTIO_PCI_CAP_T); 790 1159 pCfg->uCfgType = VIRTIO_PCI_CAP_ISR_CFG; 791 1160 pCfg->uBar = uVirtioRegion; 792 pCfg->uOffset = pVirtio->pNotifyCap->uOffset + sizeof(VIRTIONOTIFYCAP); 793 pCfg->uLength = sizeof(VIRTIOPCICAP); 794 795 /* Capability will be mapped via VirtIO 1.0: struct virtio_pci_cfg_cap (VIRTIOPCICAP) */ 796 pCfg = pVirtio->pPCICfgCap = (PVIRTIOPCICAP)&pVirtio->dev.abConfig[uCfgCapOffset]; 1161 pCfg->uOffset = pVirtio->uIsrCapOffset = pNotifyCap->pciCap.uOffset + sizeof(VIRTIO_PCI_NOTIFY_CAP_T); 1162 pCfg->uLength = sizeof(VIRTIO_PCI_ISR_CAP_T); 1163 cbVirtioCaps += pCfg->uLength; 1164 1165 #ifdef HAVE_VIRTIO_DEVICE_SPECIFIC_CAP 1166 /* Capability will be mapped via VirtIO 1.0: struct virtio_pci_dev_cap (VIRTIODEVCAP)*/ 1167 pCfg = pDeviceCap = (PVIRTIO_PCI_CAP_T)&pVirtio->dev.abConfig[uCfgCapOffset]; 797 1168 pCfg->uCapVndr = VIRTIO_PCI_CAP_ID_VENDOR; 798 pCfg->uCapNext = (uint8_t)(fMsiSupport || cbDevSpecificCap ? (uCfgCapOffset += sizeof(VIRTIOPCICAP)): 0); 799 pCfg->uCfgType = VIRTIO_PCI_CAP_PCI_CFG; 1169 pCfg->uCapNext = (uint8_t)(fMsiSupport ? (uCfgCapOffset += sizeof(VIRTIO_PCI_CAP_T)) : 0); 1170 pCfg->uCapLen = sizeof(VIRTIO_PCI_CAP_T); 1171 pCfg->uCfgType = VIRTIO_PCI_CAP_DEVICE_CFG; 800 1172 pCfg->uBar = uVirtioRegion; 801 pCfg->uOffset = pVirtio->pISRCap->uOffset + sizeof(VIRTIOISRCAP); 802 pCfg->uLength = sizeof(VIRTIOPCICAP); 803 804 if (cbDevSpecificCap) 805 { 806 /* Capability will be mapped via VirtIO 1.0: struct virtio_pci_dev_cap (VIRTIODEVCAP)*/ 807 pCfg = pVirtio->pDeviceCap = (PVIRTIOPCICAP)&pVirtio->dev.abConfig[uCfgCapOffset]; 808 pCfg->uCapVndr = VIRTIO_PCI_CAP_ID_VENDOR; 809 pCfg->uCapNext = (uint8_t)(fMsiSupport ? (uCfgCapOffset += sizeof(VIRTIOPCICAP)) : 0); 810 pCfg->uCfgType = VIRTIO_PCI_CAP_DEVICE_CFG; 811 pCfg->uBar = uVirtioRegion; 812 pCfg->uOffset = pVirtio->pPCICfgCap->uOffset + sizeof(VIRTIOPCICAP); 813 pCfg->uLength = sizeof(VIRTIOPCICAP); 814 } 1173 pCfg->uOffset = uDeviceCapOffset->uOffset + sizeof(VIRTIO_PCI_ISR_CAP_T); 1174 pCfg->uLength = cbDevSpecificCap; 1175 cbVirtioCaps += pCfg->uLength; 1176 #endif 815 1177 816 1178 /* Set offset to first capability and enable PCI dev capabilities */ … … 821 1183 { 822 1184 PDMMSIREG aMsiReg; 823 824 1185 RT_ZERO(aMsiReg); 825 1186 aMsiReg.iMsixCapOffset = uCfgCapOffset; … … 829 1190 rc = PDMDevHlpPCIRegisterMsi(pDevIns, &aMsiReg); /* see MsixR3init() */ 830 1191 if (RT_FAILURE (rc)) 831 {832 1192 /* PK TODO: The following is moot, we need to flag no MSI-X support */ 833 1193 PCIDevSetCapabilityList(&pVirtio->dev, 0x40); 834 } 835 } 836 837 /* Status driver */ 838 PPDMIBASE pUpstreamBase; 839 840 rc = PDMDevHlpDriverAttach(pDevIns, PDM_STATUS_LUN, &pVirtio->IBase, &pUpstreamBase, "Status Port"); 1194 } 1195 /* 1196 PDMDevHlpPCISetConfigCallbacks(pDevIns, &pVirtio->dev, 1197 virtioPciConfigRead, &pVirtio->pfnPciConfigReadOld, 1198 virtioPciConfigWrite, &pVirtio->pfnPciConfigWriteOld); 1199 */ 1200 rc = PDMDevHlpPCIIORegionRegister(pDevIns, uVirtioRegion, cbVirtioCaps, 1201 PCI_ADDRESS_SPACE_MEM, virtioR3Map); 841 1202 if (RT_FAILURE(rc)) 842 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to attach the status LUN"));843 pVirtio->pLedsConnector = PDMIBASE_QUERY_INTERFACE(&pVirtio->IBase, PDMILEDCONNECTORS);1203 return PDMDEV_SET_ERROR(pDevIns, rc, 1204 N_("virtio: cannot register PCI Capabilities address space")); 844 1205 845 1206 return rc; 846 1207 } 847 1208 848 849 850 1209 #endif /* IN_RING3 */ 851 1210 -
trunk/src/VBox/Devices/VirtIO/Virtio_1_0.h
r79973 r80058 34 34 /** @} */ 35 35 36 37 /** Reserved Feature Bits */ 38 #define VIRTIO_F_RING_INDIRECT_DESC RT_BIT_64(28) 39 #define VIRTIO_F_RING_IDX RT_BIT_64(29) 40 #define VIRTIO_F_VERSION_1 RT_BIT_64(32) 41 42 #define MAX_QUEUES 5 /** Maximum number of queues we support */ 43 36 44 /** Mandatory for Virtio PCI device identification, per spec */ 37 45 #define DEVICE_PCI_VENDOR_ID_VIRTIO 0x1AF4 … … 69 77 typedef DECLCALLBACK(uint32_t) FNGETHOSTFEATURES(void *pvState); 70 78 typedef FNGETHOSTFEATURES *PFNGETHOSTFEATURES; 71 72 /** @name VirtIO port I/O callbacks.73 * @{ */74 typedef struct VIRTIOIOCALLBACKS75 {76 DECLCALLBACKMEMBER(uint32_t, pfnGetHostFeatures)(void *pvState);77 DECLCALLBACKMEMBER(uint32_t, pfnGetHostMinimalFeatures)(void *pvState);78 DECLCALLBACKMEMBER(void, pfnSetHostFeatures)(void *pvState, uint32_t fFeatures);79 DECLCALLBACKMEMBER(int, pfnGetConfig)(void *pvState, uint32_t offCfg, uint32_t cb, void *pvData);80 DECLCALLBACKMEMBER(int, pfnSetConfig)(void *pvState, uint32_t offCfg, uint32_t cb, void *pvData);81 DECLCALLBACKMEMBER(int, pfnReset)(void *pvState);82 DECLCALLBACKMEMBER(void, pfnReady)(void *pvState);83 } VIRTIOIOCALLBACKS;84 /** Pointer to a const VirtIO port I/O callback structure. */85 typedef const VIRTIOIOCALLBACKS *PCVIRTIOIOCALLBACKS;86 /** @} */87 79 88 80 … … 140 132 uint32_t uOffset; /** Offset within bar. (L.E.) */ 141 133 uint32_t uLength; /** Length of struct, in bytes. (L.E.) */ 142 } VIRTIO PCICAP, *PVIRTIOPCICAP;134 } VIRTIO_PCI_CAP_T, *PVIRTIO_PCI_CAP_T; 143 135 144 136 typedef struct virtio_pci_common_cfg /* VirtIO 1.0 specification name of this struct */ … … 165 157 uint16_t uQueueMsixVector; /** RW (driver selects MSI-X queue vector) */ 166 158 uint16_t uQueueEnable; /** RW (driver controls usability of queue) */ 167 uint16_t uQueueNotifyOff; /** RO (offset to virtqueue; see spec) */159 uint16_t uQueueNotifyOff; /** RO (offset uto virtqueue; see spec) */ 168 160 uint64_t uQueueDesc; /** RW (driver writes desc table phys addr) */ 169 161 uint64_t uQueueAvail; /** RW (driver writes avail ring phys addr) */ 170 162 uint64_t uQueueUsed; /** RW (driver writes used ring phys addr) */ 171 } VIRTIO COMMONCFG, *PVIRTIOCOMMONCFG;163 } VIRTIO_PCI_COMMON_CFG_T, *PVIRTIO_PCI_COMMON_CFG_T; 172 164 173 165 typedef struct virtio_pci_notify_cap 174 166 { 175 struct virtio_pci_cap cap;167 struct virtio_pci_cap pciCap; 176 168 uint32_t uNotifyOffMultiplier; /* notify_off_multiplier */ 177 } VIRTIO NOTIFYCAP, *PVIRTIONOTIFYCAP;178 179 typedef uint8_t VIRTIO ISRCAP, *PVIRTIOISRCAP;180 181 /* Device-specific configuration (if any) ... T.B.D. (if and when neeed), provide an182 * interface/callback that lets the client of this code manage it, if and when needed.183 * probably just passing in a struct length and a callback from our capabilities184 * region handler */185 typedef struct virtio_pci_dev_cfg 186 { 187 } VIRTIODEVCAP, *PVIRTIODEVCAP; 169 } VIRTIO_PCI_NOTIFY_CAP_T, *PVIRTIO_PCI_NOTIFY_CAP_T; 170 171 typedef uint8_t VIRTIO_PCI_ISR_CAP_T, *PVIRTIO_PCI_ISR_CAP_T; 172 173 /* 174 * If the client of this library has any device-specific capabilities, it must define 175 * and implement this struct and the macro 176 */ 177 #ifdef HAVE_VIRTIO_DEVICE_SPECIFIC_CAP 178 typedef struct virtio_pci_dev_cfg VIRTIO_PCI_DEVICE_CAP_T, *PVIRTIO_PCI_DEVICE_CAP_T; 179 #endif 188 180 189 181 typedef struct virtio_pci_cfg_cap { 190 struct virtio_pci_cap cap;191 uint8_t pci_cfg_data[4]; /* Data for BAR access. */192 } VIRTIO PCICFGCAP, *PVIRTIOPCICFGCAP;182 struct virtio_pci_cap pciCap; 183 uint8_t uPciCfgData[4]; /* Data for BAR access. */ 184 } VIRTIO_PCI_CFG_CAP_T, *PVIRTIO_PCI_CFG_CAP_T; 193 185 194 186 typedef struct virtq_desc /* VirtIO 1.0 specification formal name of this struct */ … … 306 298 /** Status LUN: Base interface. */ 307 299 PDMIBASE IBase; 300 308 301 /** Status LUN: LED port interface. */ 309 PDMILEDPORTS ILeds; 310 /** Status LUN: LED connector (peer). */ 311 R3PTRTYPE(PPDMILEDCONNECTORS) pLedsConnector; 312 313 PPDMDEVINSR3 pDevInsR3; /**< Device instance - R3. */ 314 PPDMDEVINSR0 pDevInsR0; /**< Device instance - R0. */ 315 PPDMDEVINSRC pDevInsRC; /**< Device instance - RC. */ 316 317 /** Base address of PCI capabilities */ 318 RTGCPHYS GCPhysPciCapBase; 319 320 VIRTIOCOMMONCFG pGcPhysVirtioCommonCfg; 321 VIRTIONOTIFYCAP pGcPhysVirtioNotifyCap; 322 VIRTIOISRCAP pGcPhysVirtioIsrCap; 323 VIRTIODEVCAP pGcPhysVirtioDevCap; 324 VIRTIOPCICFGCAP pGcPhysVirtioPciCap; 325 326 /** Callbacks when guest driver reads or writes VirtIO device-specific capabilities(s) */ 327 328 PFNVIRTIODEVCAPWRITE pfnVirtioDevCapWrite; 329 PFNVIRTIODEVCAPREAD pfnVirtioDevCapRead; 330 331 #if HC_ARCH_BITS == 64 332 uint32_t padding2; 333 #endif 334 335 /** Base port of I/O space region. */ 336 RTIOPORT IOPortBase; 302 PDMILEDPORTS ILed; 337 303 338 304 /* Read/write part, protected with critical section. */ … … 340 306 PDMLED led; 341 307 342 uint32_t uGuestFeatures; 343 uint16_t uQueueSelector; /**< An index in aQueues array. */ 344 uint8_t uStatus; /**< Device Status (bits are device-specific). */ 345 uint8_t uISR; /**< Interrupt Status Register. */ 308 309 /** Status LUN: LED connector (peer). */ 310 R3PTRTYPE(PPDMILEDCONNECTORS) pLedsConnector; 311 312 PPDMDEVINSR3 pDevInsR3; /**< Device instance - R3. */ 313 PPDMDEVINSR0 pDevInsR0; /**< Device instance - R0. */ 314 PPDMDEVINSRC pDevInsRC; /**< Device instance - RC. */ 315 316 /** Base address of PCI capabilities */ 317 RTGCPHYS GCPhysPciCapBase; 318 319 320 /** Callbacks when guest driver reads or writes VirtIO device-specific capabilities(s) */ 321 322 PFNVIRTIODEVCAPWRITE pfnVirtioDevCapWrite; 323 PFNVIRTIODEVCAPREAD pfnVirtioDevCapRead; 324 PFNPCICONFIGREAD pfnPciConfigReadOld; 325 PFNPCICONFIGWRITE pfnPciConfigWriteOld; 326 327 uint8_t uPciConfigDataOffset; 328 #if HC_ARCH_BITS == 64 329 uint32_t padding2; 330 #endif 331 332 /** Base port of I/O space region. */ 333 RTIOPORT IOPortBase; 334 335 uint32_t uGuestFeatures; 336 uint16_t uQueueSelector; /** An index in aQueues array. */ 337 uint8_t uStatus; /** Device Status (bits are device-specific). */ 338 uint8_t uISR; /** Interrupt Status Register. */ 346 339 347 340 #if HC_ARCH_BITS != 64 348 uint32_t padding3; 349 #endif 350 351 uint32_t nQueues; /**< Actual number of queues used. */ 352 VQUEUE Queues[VIRTIO_MAX_NQUEUES]; 353 354 PVIRTIOPCICAP pCommonCfg; 355 PVIRTIOPCICAP pNotifyCap; 356 PVIRTIOPCICAP pISRCap; 357 PVIRTIOPCICAP pPCICfgCap; 358 PVIRTIOPCICAP pDeviceCap; 341 uint32_t padding3; 342 #endif 343 344 uint32_t nQueues; /** Actual number of queues used. */ 345 VQUEUE Queues[VIRTIO_MAX_NQUEUES]; 346 347 uint32_t uFeaturesOfferedSelect; /** Select hi/lo 32-bit uFeaturesOffered to r/w */ 348 uint64_t uFeaturesOffered; /** Host features offered */ 349 uint32_t uFeaturesAcceptedSelect; /** Selects hi/lo 32-bit uFeaturesAccepted to r/w*/ 350 uint64_t uFeaturesAccepted; /** Host features accepted by guest */ 351 352 uint32_t uMsixConfig; 353 uint8_t uDeviceStatus; 354 uint8_t uConfigGeneration; 355 uint32_t uNotifyOffMultiplier; /* Multiplier for uQueueNotifyOff[idx] */ 356 357 uint16_t uQueueSelect; 358 uint16_t uQueueSize[MAX_QUEUES]; 359 uint16_t uQueueMsixVector[MAX_QUEUES]; 360 uint16_t uQueueEnable[MAX_QUEUES]; 361 uint16_t uQueueNotifyOff[MAX_QUEUES]; 362 uint64_t uQueueDesc[MAX_QUEUES]; 363 uint64_t uQueueAvail[MAX_QUEUES]; 364 uint64_t uQueueUsed[MAX_QUEUES]; 365 366 uint32_t uNotifyCapOffset; 367 uint32_t uIsrCapOffset; 368 uint32_t uPciCfgCapOffset; 369 uint32_t uDeviceCapOffset; 370 uint32_t uCommonCfgOffset; 371 372 PVIRTIO_PCI_CFG_CAP_T pPciCfgCap; /** Pointer to struct in configuration area */ 373 374 PVIRTIO_PCI_COMMON_CFG_T pGcPhysCommonCfg; /** Pointer to MMIO mapped struct */ 375 PVIRTIO_PCI_NOTIFY_CAP_T pGcPhysNotifyCap; /** Pointer to MMIO mapped struct */ 376 PVIRTIO_PCI_ISR_CAP_T pGcPhysIsrCap; /** Pointer to MMIO mapped struct */ 377 PVIRTIO_PCI_CFG_CAP_T pGcPhysPciCfgCap; /** Pointer to MMIO mapped struct */ 378 #ifdef HAVE_VIRTIO_DEVICE_SPECIFIC_CAP 379 PVIRTIO_PCI_DEVICE_CAP_T pGcPhysDeviceCap; /** Pointer to MMIO mapped struct */ 380 #endif 381 382 bool fDeviceConfigInterrupt; 383 bool fQueueInterrupt; 384 359 385 } VIRTIOSTATE, *PVIRTIOSTATE; 386 387 /** @name VirtIO port I/O callbacks. 388 * @{ */ 389 typedef struct VIRTIOIOCALLBACKS 390 { 391 DECLCALLBACKMEMBER(uint64_t, pfnGetHostFeatures)(PVIRTIOSTATE pVirtio); 392 DECLCALLBACKMEMBER(int, pfnSetHostFeatures)(PVIRTIOSTATE pVirtio, uint64_t uFeaturesOffered); 393 DECLCALLBACKMEMBER(int, pfnReset)(PVIRTIOSTATE pVirtio); 394 /* DECLCALLBACKMEMBER(uint32_t, pfnGetHostMinimalFeatures)(void *pvState); */ 395 /* DECLCALLBACKMEMBER(int, pfnGetConfig)(void *pvState, uint32_t offCfg, uint32_t cb, void *pvData); */ 396 /* DECLCALLBACKMEMBER(int, pfnSetConfig)(void *pvState, uint32_t offCfg, uint32_t cb, void *pvData); */ 397 /* DECLCALLBACKMEMBER(void, pfnReady)(void *pvState); */ 398 } VIRTIOCALLBACKS, *PVIRTIOCALLBACKS, **PPVIRTIOCALLBACKS; 399 /** @} */ 360 400 361 401 void virtioRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta); 362 402 void *virtioQueryInterface(struct PDMIBASE *pInterface, const char *pszIID); 363 403 364 int virtioIOPortIn(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port, 365 uint32_t *pu32, unsigned cb, PCVIRTIOIOCALLBACKS pCallbacks); 366 367 int virtioIOPortOut(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port, 368 uint32_t u32, unsigned cb, PCVIRTIOIOCALLBACKS pCallbacks); 369 370 int virtioConstruct(PPDMDEVINS pDevIns, PVIRTIOSTATE pVirtio, int iInstance, 371 PVIRTIOPCIPARAMS pPciParams, const char *pcszNameFmt, 372 uint32_t nQueues, uint32_t uVirtioRegion, 404 int virtioConstruct(PPDMDEVINS pDevIns, PVIRTIOSTATE pVirtio, int iInstance, PVIRTIOPCIPARAMS pPciParams, 405 PPVIRTIOCALLBACKS ppVirtioCallbacks, const char *pcszNameFmt, uint32_t nQueues, uint32_t uVirtioRegion, 373 406 PFNVIRTIODEVCAPREAD devCapReadCallback, PFNVIRTIODEVCAPWRITE devCapWriteCallback, 374 uint16_t cbDevSpecificCap); 375 376 377 int virtioDestruct( PVIRTIOSTATE pState); 378 void virtioReset( PVIRTIOSTATE pState); 379 int virtioSaveExec( PVIRTIOSTATE pState, PSSMHANDLE pSSM); 380 int virtioLoadExec( PVIRTIOSTATE pState, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass, uint32_t nQueues); 381 void virtioSetReadLed( PVIRTIOSTATE pState, bool fOn); 382 void virtioSetWriteLed( PVIRTIOSTATE pState, bool fOn); 383 int virtioRaiseInterrupt( PVIRTIOSTATE pState, int rcBusy, uint8_t uint8_tIntCause); 384 385 PVQUEUE virtioAddQueue( PVIRTIOSTATE pState, unsigned uSize, PFNVIRTIOQUEUECALLBACK pfnCallback, const char *pcszName); 386 bool virtQueueSkip( PVIRTIOSTATE pState, PVQUEUE pQueue); 387 bool virtQueueGet( PVIRTIOSTATE pState, PVQUEUE pQueue, PVQUEUEELEM pElem, bool fRemove = true); 388 void virtQueuePut( PVIRTIOSTATE pState, PVQUEUE pQueue, PVQUEUEELEM pElem, uint32_t len, uint32_t uReserved = 0); 389 void virtQueueNotify( PVIRTIOSTATE pState, PVQUEUE pQueue); 390 void virtQueueSync( PVIRTIOSTATE pState, PVQUEUE pQueue); 391 void vringSetNotification( PVIRTIOSTATE pState, PVIRTQUEUE pVirtQueue, bool fEnabled); 392 393 394 /* 407 uint16_t cbDevSpecificCap, uint32_t uNotifyOffMultiplier); 408 409 int virtioDestruct(PVIRTIOSTATE pVirtio); 410 int virtioReset(PVIRTIOSTATE pVirtio); 411 int virtioSaveExec(PVIRTIOSTATE pVirtio, PSSMHANDLE pSSM); 412 int virtioLoadExec(PVIRTIOSTATE pVirtio, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass, uint32_t nQueues); 413 void virtioSetReadLed(PVIRTIOSTATE pVirtio, bool fOn); 414 void virtioSetWriteLed(PVIRTIOSTATE pVirtio, bool fOn); 415 int virtioRaiseInterrupt(PVIRTIOSTATE pVirtio, int rcBusy, uint8_t uint8_tIntCause); 416 void virtioNotify(PVIRTIOSTATE pVirtio); 417 418 PVQUEUE virtioAddQueue(PVIRTIOSTATE pVirtio, unsigned uSize, PFNVIRTIOQUEUECALLBACK pfnCallback, const char *pcszName); 419 bool virtQueueSkip(PVIRTIOSTATE pVirtio, PVQUEUE pQueue); 420 bool virtQueueGet(PVIRTIOSTATE pVirtio, PVQUEUE pQueue, PVQUEUEELEM pElem, bool fRemove = true); 421 void virtQueuePut(PVIRTIOSTATE pVirtio, PVQUEUE pQueue, PVQUEUEELEM pElem, uint32_t len, uint32_t uReserved = 0); 422 void virtQueueNotify(PVIRTIOSTATE pVirtio, PVQUEUE pQueue); 423 void virtQueueSync(PVIRTIOSTATE pVirtio, PVQUEUE pQueue); 424 void vringSetNotification( PVIRTIOSTATE pVirtio, PVIRTQUEUE pVirtQueue, bool fEnabled); 425 426 DECLINLINE(void) showDeviceStatus(uint8_t status) 427 { 428 if (status & VIRTIO_STATUS_ACKNOWLEDGE) 429 Log((" ACKNOWLEDGE\n")); 430 if (status & VIRTIO_STATUS_DRIVER) 431 Log((" DRIVER\n")); 432 if (status & VIRTIO_STATUS_DRIVER_OK) 433 Log((" DRIVER_OK\n")); 434 if (status & VIRTIO_STATUS_FEATURES_OK) 435 Log((" FEATURES_OK\n")); 436 if (status & VIRTIO_STATUS_FAILED) 437 Log((" FAILED\n")); 438 if (status & VIRTIO_STATUS_DEVICE_NEEDS_RESET) 439 Log((" ACKNOWLEDGE\n")); 440 if (status == 0) 441 Log((" RESET\n")); 442 Log(("\n")); 443 } 444 445 /* FROM Virtio 1.0 SPEC, NYI 395 446 static inline int virtq_need_event(uint16_t event_idx, uint16_t new_idx, uint16_t old_idx) 396 447 return (uint16_t)(new_idx - event_idx - 1) < (uint16_t)(new_idx - old_idx); … … 435 486 } 436 487 437 DECLINLINE(int) virtioLock(VIRTIOSTATE *pState, int rcBusy)438 {439 int rc = PDMCritSectEnter(&pState->cs, rcBusy);440 return rc;441 }442 443 DECLINLINE(void) virtioUnlock(VIRTIOSTATE *pState)444 {445 PDMCritSectLeave(&pState->cs);446 }447 448 488 #endif /* !VBOX_INCLUDED_SRC_VirtIO_Virtio_1_0_h */
Note:
See TracChangeset
for help on using the changeset viewer.