Changeset 64435 in vbox for trunk/src/VBox
- Timestamp:
- Oct 27, 2016 12:39:50 PM (8 years ago)
- Location:
- trunk/src/VBox/Additions/common/VBoxGuest
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest-solaris.c
r62521 r64435 79 79 static int vgdrvSolarisAddIRQ(dev_info_t *pDip); 80 80 static void vgdrvSolarisRemoveIRQ(dev_info_t *pDip); 81 static uint_t vgdrvSolarisHighLevelISR(caddr_t Arg); 81 82 static uint_t vgdrvSolarisISR(caddr_t Arg); 82 83 … … 178 179 /** Size of the MMIO region. */ 179 180 static off_t g_cbMMIO; 180 /** Pointer to the interrupt handle vector*/181 static ddi_intr_handle_t *g_p Intr;182 /** Number of actually allocated interrupt handles*/183 static size_t g_cIntrAllocated;181 /** Pointer to an array of interrupt handles. */ 182 static ddi_intr_handle_t *g_pahIntrs; 183 /** Handle to the soft interrupt. */ 184 static ddi_softint_handle_t g_hSoftIntr; 184 185 /** The pollhead structure */ 185 186 static pollhead_t g_PollHead; 186 187 /** The IRQ Mutex */ 187 188 static kmutex_t g_IrqMtx; 189 /** The IRQ high-level Mutex. */ 190 static kmutex_t g_HighLevelIrqMtx; 188 191 /** Layered device handle for kernel keep-attached opens */ 189 192 static ldi_handle_t g_LdiHandle = NULL; … … 192 195 /** The Mutex protecting the LDI handle in IDC opens */ 193 196 static kmutex_t g_LdiMtx; 197 /** Whether soft-ints are setup. */ 198 static bool g_fSoftIntRegistered = false; 194 199 195 200 /** … … 353 358 else 354 359 LogRel((DEVICE_NAME "::Attach: VGDrvCommonInitDevExt failed.\n")); 360 355 361 vgdrvSolarisRemoveIRQ(pDip); 356 362 } … … 433 439 static int vgdrvSolarisQuiesce(dev_info_t *pDip) 434 440 { 435 for (int i = 0; i < g_cIntrAllocated; i++) 436 { 437 int rc = ddi_intr_disable(g_pIntr[i]); 438 if (rc != DDI_SUCCESS) 439 return DDI_FAILURE; 440 } 441 int rc = ddi_intr_disable(g_pahIntrs[0]); 442 if (rc != DDI_SUCCESS) 443 return DDI_FAILURE; 441 444 442 445 /** @todo What about HGCM/HGSMI touching guest-memory? */ … … 600 603 # define IOCPARM_LEN(Code) (((Code) >> 16) & IOCPARM_MASK) 601 604 #endif 605 606 607 /** 608 * Converts a VBox status code to a Solaris error code. 609 * 610 * @returns corresponding Solaris errno. 611 * @param rcVBox VirtualBox error code to convert. 612 */ 613 static int vgdrvSolarisConvertToErrno(int rcVBox) 614 { 615 /* RTErrConvertToErrno() below will ring-0 debug assert if we don't do such stuff. */ 616 if (rcVBox == VERR_PERMISSION_DENIED) 617 rcVBox = VERR_ACCESS_DENIED; 618 619 if ( rcVBox > -1000 620 && rcVBox < 1000) 621 return RTErrConvertToErrno(rcVBox); 622 623 switch (rcVBox) 624 { 625 case VERR_HGCM_SERVICE_NOT_FOUND: return ESRCH; 626 case VINF_HGCM_CLIENT_REJECTED: return 0; 627 case VERR_HGCM_INVALID_CMD_ADDRESS: return EFAULT; 628 case VINF_HGCM_ASYNC_EXECUTE: return 0; 629 case VERR_HGCM_INTERNAL: return EPROTO; 630 case VERR_HGCM_INVALID_CLIENT_ID: return EINVAL; 631 case VINF_HGCM_SAVE_STATE: return 0; 632 /* No reason to return this to a guest. */ 633 /* case VERR_HGCM_SERVICE_EXISTS: return EEXIST; */ 634 635 default: 636 { 637 AssertMsgFailed(("Unhandled error code %Rrc\n", rcVBox)); 638 return EINVAL; 639 } 640 } 641 } 602 642 603 643 … … 724 764 */ 725 765 Log(("vgdrvSolarisIOCtl: VGDrvCommonIoCtl failed. Cmd=%#x rc=%d\n", Cmd, rc)); 726 if (rc == VERR_PERMISSION_DENIED) /* RTErrConvertToErrno() below will ring-0 debug assert if we don't do this. */ 727 rc = VERR_ACCESS_DENIED; 728 rc = RTErrConvertToErrno(rc); 766 rc = vgdrvSolarisConvertToErrno(rc); 729 767 } 730 768 *pVal = rc; … … 776 814 LogFlow(("vgdrvSolarisAddIRQ: pDip=%p\n", pDip)); 777 815 778 int IntrType = 0; 779 int rc = ddi_intr_get_supported_types(pDip, &IntrType); 816 /* Get the types of interrupt supported for this hardware. */ 817 int fIntrType = 0; 818 int rc = ddi_intr_get_supported_types(pDip, &fIntrType); 780 819 if (rc == DDI_SUCCESS) 781 820 { 782 /* We won't need to bother about MSIs. */ 783 if (IntrType & DDI_INTR_TYPE_FIXED) 784 { 785 int IntrCount = 0; 786 rc = ddi_intr_get_nintrs(pDip, IntrType, &IntrCount); 821 /* We only support fixed interrupts at this point, not MSIs. */ 822 if (fIntrType & DDI_INTR_TYPE_FIXED) 823 { 824 /* Verify the number of interrupts supported by this device. There can only be one fixed interrupt. */ 825 int cIntrCount = 0; 826 rc = ddi_intr_get_nintrs(pDip, fIntrType, &cIntrCount); 787 827 if ( rc == DDI_SUCCESS 788 && IntrCount > 0)828 && cIntrCount == 1) 789 829 { 790 int IntrAvail = 0; 791 rc = ddi_intr_get_navail(pDip, IntrType, &IntrAvail); 792 if ( rc == DDI_SUCCESS 793 && IntrAvail > 0) 830 /* Allocated kernel memory for the interrupt handle. The allocation size is stored internally. */ 831 g_pahIntrs = RTMemAllocZ(cIntrCount * sizeof(ddi_intr_handle_t)); 832 if (g_pahIntrs) 794 833 { 795 /* Allocated kernel memory for the interrupt handles. The allocation size is stored internally. */ 796 g_pIntr = RTMemAlloc(IntrCount * sizeof(ddi_intr_handle_t)); 797 if (g_pIntr) 834 /* Allocate the interrupt for this device and verify the allocation. */ 835 int cIntrAllocated; 836 rc = ddi_intr_alloc(pDip, g_pahIntrs, fIntrType, 0 /* interrupt number */, cIntrCount, &cIntrAllocated, 837 DDI_INTR_ALLOC_NORMAL); 838 if ( rc == DDI_SUCCESS 839 && cIntrAllocated == 1) 798 840 { 799 int IntrAllocated;800 rc = ddi_intr_alloc(pDip, g_pIntr, IntrType, 0, IntrCount, &IntrAllocated, DDI_INTR_ALLOC_NORMAL);801 if ( rc == DDI_SUCCESS802 && IntrAllocated > 0)841 /* Get the interrupt priority assigned by the system. */ 842 uint_t uIntrPriority; 843 rc = ddi_intr_get_pri(g_pahIntrs[0], &uIntrPriority); 844 if (rc == DDI_SUCCESS) 803 845 { 804 g_cIntrAllocated = IntrAllocated;805 uint_t uIntrPriority;806 rc = ddi_intr_get_pri(g_pIntr[0], &uIntrPriority);807 if ( rc == DDI_SUCCESS)846 /* Check if the interrupt priority is scheduler level or above, if so we need to use a high-level 847 and low-level interrupt handlers with corresponding mutexes. */ 848 cmn_err(CE_NOTE, "vboxguest: uIntrPriority=%d hilevel_pri=%d\n", uIntrPriority, ddi_intr_get_hilevel_pri()); 849 if (uIntrPriority >= ddi_intr_get_hilevel_pri()) 808 850 { 809 /* Initialize the mutex. */ 810 mutex_init(&g_IrqMtx, NULL /* pszDesc */, MUTEX_DRIVER, DDI_INTR_PRI(uIntrPriority)); 811 812 /* Assign interrupt handler functions and enable interrupts. */ 813 for (int i = 0; i < IntrAllocated; i++) 851 /* Initialize the high-level mutex. */ 852 mutex_init(&g_HighLevelIrqMtx, NULL /* pszDesc */, MUTEX_DRIVER, DDI_INTR_PRI(uIntrPriority)); 853 854 /* Assign interrupt handler function to the interrupt handle. */ 855 rc = ddi_intr_add_handler(g_pahIntrs[0], (ddi_intr_handler_t *)&vgdrvSolarisHighLevelISR, 856 NULL /* pvArg1 */, NULL /* pvArg2 */); 857 858 if (rc == DDI_SUCCESS) 814 859 { 815 rc = ddi_intr_add_handler(g_pIntr[i], (ddi_intr_handler_t *)vgdrvSolarisISR, 816 NULL /* pvArg1 */, NULL /* pvArg2 */); 860 /* Add the low-level interrupt handler. */ 861 rc = ddi_intr_add_softint(pDip, &g_hSoftIntr, DDI_INTR_SOFTPRI_MAX, 862 (ddi_intr_handler_t *)&vgdrvSolarisISR, NULL /* pvArg1 */); 817 863 if (rc == DDI_SUCCESS) 818 rc = ddi_intr_enable(g_pIntr[i]);819 if (rc != DDI_SUCCESS)820 864 { 821 /* Changing local IntrAllocated to hold so-far allocated handles for freeing. */ 822 IntrAllocated = i; 823 break; 865 /* Initialize the low-level mutex at the corresponding level. */ 866 mutex_init(&g_IrqMtx, NULL /* pszDesc */, MUTEX_DRIVER, 867 DDI_INTR_PRI(DDI_INTR_SOFTPRI_MAX)); 868 869 g_fSoftIntRegistered = true; 870 /* Enable the high-level interrupt. */ 871 rc = ddi_intr_enable(g_pahIntrs[0]); 872 if (rc == DDI_SUCCESS) 873 return rc; 874 875 LogRel((DEVICE_NAME "::AddIRQ: failed to enable interrupt. rc=%d\n", rc)); 876 mutex_destroy(&g_IrqMtx); 824 877 } 878 else 879 LogRel((DEVICE_NAME "::AddIRQ: failed to add soft interrupt handler. rc=%d\n", rc)); 880 881 ddi_intr_remove_handler(g_pahIntrs[0]); 825 882 } 826 if (rc == DDI_SUCCESS) 827 return rc; 828 829 /* Remove any assigned handlers */ 830 LogRel((DEVICE_NAME ":failed to assign IRQs allocated=%d\n", IntrAllocated)); 831 for (int x = 0; x < IntrAllocated; x++) 832 ddi_intr_remove_handler(g_pIntr[x]); 883 else 884 LogRel((DEVICE_NAME "::AddIRQ: failed to add high-level interrupt handler. rc=%d\n", rc)); 885 886 mutex_destroy(&g_HighLevelIrqMtx); 833 887 } 834 888 else 835 LogRel((DEVICE_NAME "::AddIRQ: failed to get priority of interrupt. rc=%d\n", rc)); 836 837 /* Remove allocated IRQs, too bad we can free only one handle at a time. */ 838 for (int k = 0; k < g_cIntrAllocated; k++) 839 ddi_intr_free(g_pIntr[k]); 840 g_cIntrAllocated = 0; 889 { 890 /* Interrupt handler runs at reschedulable level, initialize the mutex at the given priority. */ 891 mutex_init(&g_IrqMtx, NULL /* pszDesc */, MUTEX_DRIVER, DDI_INTR_PRI(uIntrPriority)); 892 893 /* Assign interrupt handler function to the interrupt handle. */ 894 rc = ddi_intr_add_handler(g_pahIntrs[0], (ddi_intr_handler_t *)vgdrvSolarisISR, 895 NULL /* pvArg1 */, NULL /* pvArg2 */); 896 if (rc == DDI_SUCCESS) 897 { 898 /* Enable the interrupt. */ 899 rc = ddi_intr_enable(g_pahIntrs[0]); 900 if (rc == DDI_SUCCESS) 901 return rc; 902 903 LogRel((DEVICE_NAME "::AddIRQ: failed to enable interrupt. rc=%d\n", rc)); 904 mutex_destroy(&g_IrqMtx); 905 } 906 } 841 907 } 842 908 else 843 LogRel((DEVICE_NAME "::AddIRQ: failed to allocated IRQs. count=%d\n", IntrCount)); 844 RTMemFree(g_pIntr); 909 LogRel((DEVICE_NAME "::AddIRQ: failed to get priority of interrupt. rc=%d\n", rc)); 910 911 Assert(cIntrAllocated == 1); 912 ddi_intr_free(g_pahIntrs[0]); 845 913 } 846 914 else 847 LogRel((DEVICE_NAME "::AddIRQ: failed to allocated IRQs. count=%d\n", IntrCount)); 915 LogRel((DEVICE_NAME "::AddIRQ: failed to allocated IRQs. count=%d\n", cIntrCount)); 916 RTMemFree(g_pahIntrs); 848 917 } 849 918 else 850 LogRel((DEVICE_NAME "::AddIRQ: failed to get or insufficient available IRQs. rc=%d IntrAvail=%d\n", rc, IntrAvail));919 LogRel((DEVICE_NAME "::AddIRQ: failed to allocated IRQs. count=%d\n", cIntrCount)); 851 920 } 852 921 else 853 LogRel((DEVICE_NAME "::AddIRQ: failed to get or insufficient number of IRQs. rc=%d IntrCount=%d\n", rc,IntrCount));922 LogRel((DEVICE_NAME "::AddIRQ: failed to get or insufficient number of IRQs. rc=%d cIntrCount=%d\n", rc, cIntrCount)); 854 923 } 855 924 else 856 LogRel((DEVICE_NAME "::AddIRQ: invalid irq type. IntrType=%#x\n",IntrType));925 LogRel((DEVICE_NAME "::AddIRQ: fixed-type interrupts not supported. IntrType=%#x\n", fIntrType)); 857 926 } 858 927 else 859 LogRel((DEVICE_NAME "::AddIRQ: failed to get supported interrupt types \n"));928 LogRel((DEVICE_NAME "::AddIRQ: failed to get supported interrupt types. rc=%d\n", rc)); 860 929 return rc; 861 930 } … … 871 940 LogFlow(("vgdrvSolarisRemoveIRQ:\n")); 872 941 873 for (int i = 0; i < g_cIntrAllocated; i++) 874 { 875 int rc = ddi_intr_disable(g_pIntr[i]); 942 int rc = ddi_intr_disable(g_pahIntrs[0]); 943 if (rc == DDI_SUCCESS) 944 { 945 rc = ddi_intr_remove_handler(g_pahIntrs[0]); 876 946 if (rc == DDI_SUCCESS) 877 { 878 rc = ddi_intr_remove_handler(g_pIntr[i]); 879 if (rc == DDI_SUCCESS) 880 ddi_intr_free(g_pIntr[i]); 881 } 882 } 883 g_cIntrAllocated = 0; 884 RTMemFree(g_pIntr); 947 ddi_intr_free(g_pahIntrs[0]); 948 } 949 950 if (g_fSoftIntRegistered) 951 { 952 ddi_intr_remove_softint(g_hSoftIntr); 953 mutex_destroy(&g_HighLevelIrqMtx); 954 g_fSoftIntRegistered = false; 955 } 956 885 957 mutex_destroy(&g_IrqMtx); 886 } 887 888 889 /** 890 * Interrupt Service Routine for VMMDev. 958 RTMemFree(g_pahIntrs); 959 } 960 961 962 /** 963 * High-level Interrupt Service Routine for VMMDev. 964 * 965 * This routine simply dispatches a soft-interrupt at an acceptable IPL as 966 * VGDrvCommonISR() cannot be called at a high IPL (scheduler level or higher) 967 * due to pollwakeup() in VGDrvNativeISRMousePollEvent(). 891 968 * 892 969 * @param Arg Private data (unused, will be NULL). 893 970 * @returns DDI_INTR_CLAIMED if it's our interrupt, DDI_INTR_UNCLAIMED if it isn't. 894 971 */ 972 static uint_t vgdrvSolarisHighLevelISR(caddr_t Arg) 973 { 974 bool const fOurIrq = VGDrvCommonIsOurISR(&g_DevExt); 975 if (fOurIrq) 976 { 977 ddi_intr_trigger_softint(g_hSoftIntr, NULL /* Arg */); 978 return DDI_INTR_CLAIMED; 979 } 980 return DDI_INTR_UNCLAIMED; 981 } 982 983 984 /** 985 * Interrupt Service Routine for VMMDev. 986 * 987 * @param Arg Private data (unused, will be NULL). 988 * @returns DDI_INTR_CLAIMED if it's our interrupt, DDI_INTR_UNCLAIMED if it isn't. 989 */ 895 990 static uint_t vgdrvSolarisISR(caddr_t Arg) 896 991 { 897 992 LogFlow(("vgdrvSolarisISR:\n")); 898 993 994 /* The mutex is required to protect against parallel executions (if possible?) and also the 995 mouse notify registeration race between VGDrvNativeSetMouseNotifyCallback() and VGDrvCommonISR(). */ 899 996 mutex_enter(&g_IrqMtx); 900 997 bool fOurIRQ = VGDrvCommonISR(&g_DevExt); … … 905 1002 906 1003 1004 /** 1005 * Poll notifier for mouse poll events. 1006 * 1007 * @param pDevExt Pointer to the device extension. 1008 * 1009 * @remarks This must be called without holding any spinlocks. 1010 */ 907 1011 void VGDrvNativeISRMousePollEvent(PVBOXGUESTDEVEXT pDevExt) 908 1012 { … … 916 1020 917 1021 1022 /** 1023 * Sets the mouse notification callback. 1024 * 1025 * @returns VBox status code. 1026 * @param pDevExt Pointer to the device extension. 1027 * @param pNotify Pointer to the mouse notify struct. 1028 */ 1029 int VGDrvNativeSetMouseNotifyCallback(PVBOXGUESTDEVEXT pDevExt, VBoxGuestMouseSetNotifyCallback *pNotify) 1030 { 1031 /* Take the mutex here so as to not race with VGDrvCommonISR() which invokes the mouse notify callback. */ 1032 mutex_enter(&g_IrqMtx); 1033 pDevExt->MouseNotifyCallback = *pNotify; 1034 mutex_exit(&g_IrqMtx); 1035 return VINF_SUCCESS; 1036 } 1037 1038 918 1039 /* Common code that depend on g_DevExt. */ 919 1040 #include "VBoxGuestIDC-unix.c.h" -
trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp
r63948 r64435 1560 1560 LogFlow(("VBOXGUEST_IOCTL_SET_MOUSE_NOTIFY_CALLBACK: pfnNotify=%p pvUser=%p\n", pNotify->pfnNotify, pNotify->pvUser)); 1561 1561 1562 #ifdef VBOXGUEST_MOUSE_NOTIFY_CAN_PREEMPT 1563 VGDrvNativeSetMouseNotifyCallback(pDevExt, pNotify); 1564 #else 1562 1565 RTSpinlockAcquire(pDevExt->EventSpinlock); 1563 1566 pDevExt->MouseNotifyCallback = *pNotify; 1564 1567 RTSpinlockRelease(pDevExt->EventSpinlock); 1568 #endif 1565 1569 return VINF_SUCCESS; 1566 1570 } … … 3640 3644 3641 3645 /** 3646 * Simply checks whether the IRQ is ours or not, does not do any interrupt 3647 * procesing. 3648 * 3649 * @returns true if it was our interrupt, false if it wasn't. 3650 * @param pDevExt The VBoxGuest device extension. 3651 */ 3652 bool VGDrvCommonIsOurISR(PVBOXGUESTDEVEXT pDevExt) 3653 { 3654 RTSpinlockAcquire(pDevExt->EventSpinlock); 3655 bool const fOurIrq = pDevExt->pVMMDevMemory->V.V1_04.fHaveEvents; 3656 RTSpinlockRelease(pDevExt->EventSpinlock); 3657 3658 return fOurIrq; 3659 } 3660 3661 3662 /** 3642 3663 * Common interrupt service routine. 3643 3664 * … … 3689 3710 fMousePositionChanged = true; 3690 3711 fEvents &= ~VMMDEV_EVENT_MOUSE_POSITION_CHANGED; 3691 #if ndef RT_OS_WINDOWS3712 #if !defined(RT_OS_WINDOWS) && !defined(VBOXGUEST_MOUSE_NOTIFY_CAN_PREEMPT) 3692 3713 if (pDevExt->MouseNotifyCallback.pfnNotify) 3693 3714 pDevExt->MouseNotifyCallback.pfnNotify(pDevExt->MouseNotifyCallback.pvUser); … … 3735 3756 RTSpinlockRelease(pDevExt->EventSpinlock); 3736 3757 3758 /* 3759 * Execute the mouse notification callback here if it cannot be executed while 3760 * holding the interrupt safe spinlock, see @bugref{8639}. 3761 */ 3762 #if defined(VBOXGUEST_MOUSE_NOTIFY_CAN_PREEMPT) 3763 if ( fMousePositionChanged 3764 && pDevExt->MouseNotifyCallback.pfnNotify) 3765 pDevExt->MouseNotifyCallback.pfnNotify(pDevExt->MouseNotifyCallback.pvUser); 3766 #endif 3767 3737 3768 #if defined(VBOXGUEST_USE_DEFERRED_WAKE_UP) && !defined(RT_OS_DARWIN) && !defined(RT_OS_WINDOWS) 3738 3769 /* -
trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuestInternal.h
r62521 r64435 43 43 #endif 44 44 45 /** @def VBOXGUEST_MOUSE_NOTIFY_CAN_PREEMPT 46 * The mouse notification callback can cause preemption and must not be invoked 47 * while holding a high-level spinlock. 48 */ 49 #if defined(RT_OS_SOLARIS) 50 # define VBOXGUEST_MOUSE_NOTIFY_CAN_PREEMPT 51 #endif 45 52 46 53 /** Pointer to the VBoxGuest per session data. */ … … 316 323 int VGDrvCommonInitDevExt(PVBOXGUESTDEVEXT pDevExt, uint16_t IOPortBase, void *pvMMIOBase, uint32_t cbMMIO, 317 324 VBOXOSTYPE enmOSType, uint32_t fEvents); 325 bool VGDrvCommonIsOurISR(PVBOXGUESTDEVEXT pDevExt); 318 326 bool VGDrvCommonISR(PVBOXGUESTDEVEXT pDevExt); 319 327 void VGDrvCommonDeleteDevExt(PVBOXGUESTDEVEXT pDevExt); … … 346 354 #endif 347 355 356 #ifdef VBOXGUEST_MOUSE_NOTIFY_CAN_PREEMPT 357 int VGDrvNativeSetMouseNotifyCallback(PVBOXGUESTDEVEXT pDevExt, VBoxGuestMouseSetNotifyCallback *pNotify); 358 #endif 359 348 360 RT_C_DECLS_END 349 361
Note:
See TracChangeset
for help on using the changeset viewer.