VirtualBox

Changeset 54606 in vbox for trunk/src


Ignore:
Timestamp:
Mar 3, 2015 7:49:35 PM (10 years ago)
Author:
vboxsync
Message:

VBoxGuest: Guest capabilities, mouse status, and event filter cleanups - part 2.

Location:
trunk/src/VBox/Additions/common/VBoxGuest
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest-linux.c

    r53484 r54606  
    967967}
    968968
    969 
    970969/** log and dbg_log parameter getter. */
    971970static int vboxguestLinuxParamLogGrpGet(char *pszBuf, struct kernel_param *pParam)
     
    993992}
    994993
    995 
    996994/** log and dbg_log_flags parameter getter. */
    997995static int vboxguestLinuxParamLogFlagsGet(char *pszBuf, struct kernel_param *pParam)
     
    10191017}
    10201018
    1021 
    10221019/** log and dbg_log_dest parameter getter. */
    10231020static int vboxguestLinuxParamLogDstGet(char *pszBuf, struct kernel_param *pParam)
     
    10291026    return strlen(pszBuf);
    10301027}
     1028
     1029
     1030/** r3_log_to_host parameter setter. */
     1031static int vboxguestLinuxParamR3LogToHostSet(const char *pszValue, struct kernel_param *pParam)
     1032{
     1033    if (    pszValue == NULL
     1034        || *pszValue == '\0'
     1035        || *pszValue == 'n'
     1036        || *pszValue == 'N'
     1037        || *pszValue == 'y'
     1038        || *pszValue == 'y'
     1039        || *pszValue == 'd'
     1040        || *pszValue == 'D'
     1041        || !strcmp(pszValue, "off")
     1042       )
     1043        g_DevExt.fLoggingEnabled = false;
     1044    else
     1045        g_DevExt.fLoggingEnabled = true;
     1046    return 0;
     1047}
     1048
     1049/** r3_log_to_host parameter getter. */
     1050static int vboxguestLinuxParamR3LogToHostGet(char *pszBuf, struct kernel_param *pParam)
     1051{
     1052    strcpy(pszBuf, g_DevExt.fLoggingEnabled ? "enabled" : "disabled");
     1053    return strlen(pszBuf);
     1054}
     1055
    10311056
    10321057/*
     
    10411066module_param_call(dbg_log_dest,   vboxguestLinuxParamLogDstSet,   vboxguestLinuxParamLogDstGet,   NULL, 0664);
    10421067# endif
     1068module_param_call(r3_log_to_host, vboxguestLinuxParamR3LogToHostSet, vboxguestLinuxParamR3LogToHostGet, NULL, 0664);
    10431069
    10441070#endif /* 2.6.0 and later */
  • trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp

    r54601 r54606  
    9090#endif
    9191static int VBoxGuestCommonIOCtl_CancelAllWaitEvents(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession);
    92 static int      vboxGuestUpdateHostFlags(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, unsigned fFlags);
     92static void     vbgdBitUsageTrackerClear(PVBOXGUESTBITUSAGETRACER pTracker);
    9393static uint32_t vbgdGetAllowedEventMaskForSession(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession);
    94 static int      vbgdUpdateCapabilitiesOnHost(PVBOXGUESTDEVEXT pDevExt);
     94static int      vbgdResetEventFilterOnHost(PVBOXGUESTDEVEXT pDevExt, uint32_t fFixedEvents);
     95static int      vbgdResetMouseStatusOnHost(PVBOXGUESTDEVEXT pDevExt);
     96static int      vbgdResetCapabilitiesOnHost(PVBOXGUESTDEVEXT pDevExt);
     97static int      vbgdSetSessionEventFilter(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession,
     98                                          uint32_t fOrMask, uint32_t fNotMask, bool fSessionTermination);
     99static int      vbgdSetSessionMouseStatus(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession,
     100                                          uint32_t fOrMask, uint32_t fNotMask, bool fSessionTermination);
     101static int      vbgdSetSessionCapabilities(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession,
     102                                           uint32_t fOrMask, uint32_t fNoMask, bool fSessionTermination);
    95103static int      vbgdAcquireSessionCapabilities(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, uint32_t fOrMask,
    96104                                               uint32_t fNotMask, VBOXGUESTCAPSACQUIRE_FLAGS enmFlags, bool fSessionTermination);
    97 static int      vbgdSetSessionCapabilities(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, uint32_t fOrMask, uint32_t fNoMask);
    98105static int      vbgdDispatchEventsLocked(PVBOXGUESTDEVEXT pDevExt, uint32_t fEvents);
    99106
     
    852859    pDevExt->IOPortBase = IOPortBase;
    853860    pDevExt->pVMMDevMemory = NULL;
    854     pDevExt->fFixedEvents = fFixedEvents;
    855861    pDevExt->hGuestMappings = NIL_RTR0MEMOBJ;
    856862    pDevExt->EventSpinlock = NIL_RTSPINLOCK;
     
    882888    pDevExt->pReqGuestHeartbeat = NULL;
    883889
     890    pDevExt->fFixedEvents = fFixedEvents;
     891    vbgdBitUsageTrackerClear(&pDevExt->EventFilterTracker);
     892    pDevExt->fEventFilterHost = UINT32_MAX;  /* forces a report */
     893
     894    vbgdBitUsageTrackerClear(&pDevExt->MouseStatusTracker);
     895    pDevExt->fMouseStatusHost = UINT32_MAX;  /* forces a report */
     896
     897    pDevExt->u32AcquireModeGuestCaps = 0;
     898    pDevExt->u32SetModeGuestCaps = 0;
     899    pDevExt->u32GuestCapsAcquired = 0;
     900    vbgdBitUsageTrackerClear(&pDevExt->SetGuestCapsTracker);
     901    pDevExt->fGuestCapsHost = UINT32_MAX; /* forces a report */
     902
    884903    /*
    885904     * If there is an MMIO region validate the version and size.
     
    902921    }
    903922
    904     pDevExt->u32AcquireModeGuestCaps = 0;
    905     pDevExt->u32SetModeGuestCaps = 0;
    906     pDevExt->u32GuestCapsAcquired = 0;
    907     RT_ZERO(pDevExt->acGuestCapsSet);
    908     pDevExt->fGuestCapsHost = UINT32_MAX; /* forces a report */
    909 
    910923    /*
    911924     * Create the wait and session spinlocks as well as the ballooning mutex.
     
    949962            {
    950963                /*
    951                  * Set the fixed event and disable the guest graphics capability
    952                  * by default. The guest specific graphics driver will re-enable
    953                  * the graphics capability if and when appropriate.
     964                 * Set the fixed event and make sure guest capabilities are cleared.
    954965                 */
    955                 rc = vboxGuestUpdateHostFlags(pDevExt, NULL, HostFlags_FilterMask);
     966                rc = vbgdResetEventFilterOnHost(pDevExt, pDevExt->fFixedEvents);
    956967                if (RT_SUCCESS(rc))
    957968                {
    958                     rc = vbgdUpdateCapabilitiesOnHost(pDevExt);
     969                    rc = vbgdResetCapabilitiesOnHost(pDevExt);
    959970                    if (RT_SUCCESS(rc))
    960971                    {
     972                        /*
     973                         * Initialize stuff which may fail without requiring the driver init to fail.
     974                         */
    961975                        vboxGuestInitFixateGuestMappings(pDevExt);
    962976                        vbgdHeartbeatInit(pDevExt);
    963977
     978                        /*
     979                         * Done!
     980                         */
    964981                        rc = VBoxGuestReportDriverStatus(true /* Driver is active */);
    965982                        if (RT_FAILURE(rc))
     
    10551072    /* Update the host flags (mouse status etc) not to reflect this session. */
    10561073    pDevExt->fFixedEvents = 0;
    1057     vboxGuestUpdateHostFlags(pDevExt, NULL, HostFlags_All);
     1074    vbgdResetEventFilterOnHost(pDevExt, 0 /*fFixedEvents*/);
     1075    vbgdResetCapabilitiesOnHost(pDevExt);
     1076    vbgdResetMouseStatusOnHost(pDevExt);
     1077
    10581078    vboxGuestCloseMemBalloon(pDevExt, (PVBOXGUESTSESSION)NULL);
    10591079
     
    11781198    vbgdAcquireSessionCapabilities(pDevExt, pSession, 0, UINT32_MAX, VBOXGUESTCAPSACQUIRE_FLAGS_NONE,
    11791199                                   true /*fSessionTermination*/);
    1180     vbgdSetSessionCapabilities(pDevExt, pSession, 0 /*fOrMask*/, UINT32_MAX /*fNotMask*/);
     1200    vbgdSetSessionCapabilities(pDevExt, pSession, 0 /*fOrMask*/, UINT32_MAX /*fNotMask*/, true /*fSessionTermination*/);
     1201    vbgdSetSessionEventFilter(pDevExt, pSession, 0 /*fOrMask*/, UINT32_MAX /*fNotMask*/, true /*fSessionTermination*/);
     1202    vbgdSetSessionMouseStatus(pDevExt, pSession, 0 /*fOrMask*/, UINT32_MAX /*fNotMask*/, true /*fSessionTermination*/);
    11811203
    11821204    VBoxGuestCommonIOCtl_CancelAllWaitEvents(pDevExt, pSession);
     
    12001222    vboxGuestCloseMemBalloon(pDevExt, pSession);
    12011223    RTMemFree(pSession);
    1202 
    1203     /* Update the host flags (mouse status etc) not to reflect this session. */
    1204     vboxGuestUpdateHostFlags(pDevExt, NULL,
    1205                                HostFlags_All
    1206 #ifdef RT_OS_WINDOWS
    1207                              & ~HostFlags_MouseStatus
    1208 #endif
    1209                              );
    12101224}
    12111225
     
    18941908
    18951909
    1896 static int VBoxGuestCommonIOCtl_CtlFilterMask(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession,
    1897                                               VBoxGuestFilterMaskInfo *pInfo)
    1898 {
    1899     int rc;
    1900 
    1901     if ((pInfo->u32OrMask | pInfo->u32NotMask) & ~VMMDEV_EVENT_VALID_EVENT_MASK)
    1902         return VERR_INVALID_PARAMETER;
    1903     RTSpinlockAcquire(pDevExt->SessionSpinlock);
    1904     pSession->fFilterMask |= pInfo->u32OrMask;
    1905     pSession->fFilterMask &= ~pInfo->u32NotMask;
    1906     RTSpinlockRelease(pDevExt->SessionSpinlock);
    1907     rc = vboxGuestUpdateHostFlags(pDevExt, pSession, HostFlags_FilterMask);
    1908     return rc;
    1909 }
    1910 
    1911 
    1912 /**
    1913  * Sets the mouse status features for this session and updates them
    1914  * globally.
    1915  *
    1916  * @returns VBox status code.
    1917  *
    1918  * @param   pDevExt             The device extention.
    1919  * @param   pSession            The session.
    1920  * @param   fFeatures           New bitmap of enabled features.
    1921  */
    1922 static int vboxGuestCommonIOCtl_SetMouseStatus(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, uint32_t fFeatures)
    1923 {
    1924     int rc;
    1925 
    1926     if (fFeatures & ~VMMDEV_MOUSE_GUEST_MASK)
    1927         return VERR_INVALID_PARAMETER;
    1928     /* Since this is more of a negative feature we invert it to get the real
    1929      * feature (when the guest does not need the host cursor). */
    1930     fFeatures ^= VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR;
    1931     RTSpinlockAcquire(pDevExt->SessionSpinlock);
    1932     pSession->fMouseStatus = fFeatures;
    1933     RTSpinlockRelease(pDevExt->SessionSpinlock);
    1934     rc = vboxGuestUpdateHostFlags(pDevExt, pSession, HostFlags_MouseStatus);
    1935     return rc;
    1936 }
    1937 
    19381910#ifdef VBOX_WITH_HGCM
    19391911
     
    24062378    NOREF(pch);
    24072379    NOREF(cbData);
     2380RTAssertMsg2Weak("\nVBoxGuestCommonIOCtl_Log: cbData=%#x\n", cbData);
    24082381    if (pDevExt->fLoggingEnabled)
    24092382        RTLogBackdoorPrintf("%.*s", cbData, pch);
     
    24232396
    24242397/**
    2425  * Sets the interrupt filter mask during initialization and termination.
    2426  *
    2427  * This will ASSUME that we're the ones in carge over the mask, so
    2428  * we'll simply clear all bits we don't set.
    2429  *
    2430  * @returns VBox status code (ignored).
    2431  * @param   fMask       The new mask.
    2432  */
    2433 static int vboxGuestSetFilterMask(VMMDevCtlGuestFilterMask *pReq, uint32_t fMask)
     2398 * Clears a bit usage tracker (init time).
     2399 *
     2400 * @param   pTracker            The tracker to clear.
     2401 */
     2402static void vbgdBitUsageTrackerClear(PVBOXGUESTBITUSAGETRACER pTracker)
     2403{
     2404    uint32_t iBit;
     2405    AssertCompile(sizeof(pTracker->acPerBitUsage) == 32 * sizeof(uint32_t));
     2406
     2407    for (iBit = 0; iBit < 32; iBit++)
     2408        pTracker->acPerBitUsage[iBit] = 0;
     2409    pTracker->fMask = 0;
     2410}
     2411
     2412
     2413#ifdef VBOX_STRICT
     2414/**
     2415 * Checks that pTracker->fMask is correct and that the usage values are within
     2416 * the valid range.
     2417 *
     2418 * @param   pTracker            The tracker.
     2419 * @param   cMax                Max valid usage value.
     2420 * @param   pszWhat             Identifies the tracker in assertions.
     2421 */
     2422static void vbgdBitUsageTrackerCheckMask(PCVBOXGUESTBITUSAGETRACER pTracker, uint32_t cMax, const char *pszWhat)
     2423{
     2424    uint32_t fMask = 0;
     2425    uint32_t iBit;
     2426    AssertCompile(sizeof(pTracker->acPerBitUsage) == 32 * sizeof(uint32_t));
     2427
     2428    for (iBit = 0; iBit < 32; iBit++)
     2429        if (pTracker->acPerBitUsage[iBit])
     2430        {
     2431            fMask |= RT_BIT_32(iBit);
     2432            AssertMsg(pTracker->acPerBitUsage[iBit] <= cMax,
     2433                      ("%s: acPerBitUsage[%u]=%#x cMax=%#x\n", pszWhat, iBit, pTracker->acPerBitUsage[iBit], cMax));
     2434        }
     2435
     2436    AssertMsg(fMask == pTracker->fMask, ("%s: %#x vs %#x\n", pszWhat, fMask, pTracker->fMask));
     2437}
     2438#endif
     2439
     2440
     2441/**
     2442 * Applies a change to the bit usage tracker.
     2443 *
     2444 *
     2445 * @returns true if the mask changed, false if not.
     2446 * @param   pTracker            The bit usage tracker.
     2447 * @param   fChanged            The bits to change.
     2448 * @param   fPrevious           The previous value of the bits.
     2449 * @param   cMax                The max valid usage value for assertions.
     2450 * @param   pszWhat             Identifies the tracker in assertions.
     2451 */
     2452static bool vbgdBitUsageTrackerChange(PVBOXGUESTBITUSAGETRACER pTracker, uint32_t fChanged, uint32_t fPrevious,
     2453                                     uint32_t cMax, const char *pszWhat)
     2454{
     2455    bool        fGlobalChange = false;
     2456    uint32_t    iBit;
     2457    AssertCompile(sizeof(pTracker->acPerBitUsage) == 32 * sizeof(uint32_t));
     2458
     2459    for (iBit = ASMBitFirstSetU32(fChanged) - 1; iBit < 32; iBit++)
     2460    {
     2461        uint32_t const fBitMask = RT_BIT_32(iBit);
     2462        if (fBitMask & fChanged)
     2463        {
     2464            if (fChanged & fPrevious)
     2465            {
     2466                pTracker->acPerBitUsage[iBit] -= 1;
     2467                AssertMsg(pTracker->acPerBitUsage[iBit] <= cMax,
     2468                          ("%s: acPerBitUsage[%u]=%#x cMax=%#x\n", pszWhat, iBit, pTracker->acPerBitUsage[iBit], cMax));
     2469                if (pTracker->acPerBitUsage[iBit] == 0)
     2470                {
     2471                    fGlobalChange = true;
     2472                    pTracker->fMask &= ~fBitMask;
     2473                }
     2474            }
     2475            else
     2476            {
     2477                pTracker->acPerBitUsage[iBit] += 1;
     2478                AssertMsg(pTracker->acPerBitUsage[iBit] > 0 && pTracker->acPerBitUsage[iBit] <= cMax,
     2479                          ("pTracker->acPerBitUsage[%u]=%#x cMax=%#x\n", pszWhat, iBit, pTracker->acPerBitUsage[iBit], cMax));
     2480                if (pTracker->acPerBitUsage[iBit] == 1)
     2481                {
     2482                    fGlobalChange = true;
     2483                    pTracker->fMask |= fBitMask;
     2484                }
     2485            }
     2486            fChanged &= ~fBitMask;
     2487            if (!fChanged)
     2488                break;
     2489        }
     2490    }
     2491
     2492#ifdef VBOX_STRICT
     2493    vbgdBitUsageTrackerCheckMask(pTracker, cMax, pszWhat);
     2494#endif
     2495    NOREF(pszWhat); NOREF(cMax);
     2496    return fGlobalChange;
     2497}
     2498
     2499
     2500/**
     2501 * Init and termination worker for resetting the (host) event filter on the host
     2502 *
     2503 * @returns VBox status code.
     2504 * @param   pDevExt         The device extension.
     2505 * @param   fFixedEvents    Fixed events (init time).
     2506 */
     2507static int vbgdResetEventFilterOnHost(PVBOXGUESTDEVEXT pDevExt, uint32_t fFixedEvents)
     2508{
     2509    VMMDevCtlGuestFilterMask *pReq;
     2510    int rc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, sizeof(*pReq), VMMDevReq_CtlGuestFilterMask);
     2511    if (RT_SUCCESS(rc))
     2512    {
     2513        pReq->u32NotMask = UINT32_MAX & ~fFixedEvents;
     2514        pReq->u32OrMask  = fFixedEvents;
     2515        rc = VbglGRPerform(&pReq->header);
     2516        if (RT_FAILURE(rc))
     2517            LogRelFunc(("failed with rc=%Rrc\n", rc));
     2518        VbglGRFree(&pReq->header);
     2519    }
     2520    return rc;
     2521}
     2522
     2523
     2524/**
     2525 * Changes the event filter mask for the given session.
     2526 *
     2527 * This is called in response to VBOXGUEST_IOCTL_CTL_FILTER_MASK as well as to
     2528 * do session cleanup.
     2529 *
     2530 * @returns VBox status code.
     2531 * @param   pDevExt             The device extension.
     2532 * @param   pSession            The session.
     2533 * @param   fOrMask             The events to add.
     2534 * @param   fNotMask            The events to remove.
     2535 * @param   fSessionTermination Set if we're called by the session cleanup code.
     2536 *                              This tweaks the error handling so we perform
     2537 *                              proper session cleanup even if the host
     2538 *                              misbehaves.
     2539 *
     2540 * @remarks Takes the session spinlock.
     2541 */
     2542static int vbgdSetSessionEventFilter(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession,
     2543                                     uint32_t fOrMask, uint32_t fNotMask, bool fSessionTermination)
     2544{
     2545    VMMDevCtlGuestFilterMask   *pReq;
     2546    uint32_t                    fChanged;
     2547    uint32_t                    fPrevious;
     2548    int                         rc;
     2549
     2550    /*
     2551     * Preallocate a request buffer so we can do all in one go without leaving the spinlock.
     2552     */
     2553    rc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, sizeof(*pReq), VMMDevReq_CtlGuestFilterMask);
     2554    if (RT_SUCCESS(rc))
     2555    { /* nothing */ }
     2556    else if (!fSessionTermination)
     2557    {
     2558        LogRel(("vbgdSetSessionFilterMask: VbglGRAlloc failure: %Rrc\n", rc));
     2559        return rc;
     2560    }
     2561    else
     2562        pReq = NULL; /* Ignore failure, we must do session cleanup. */
     2563
     2564
     2565    RTSpinlockAcquire(pDevExt->SessionSpinlock);
     2566
     2567    /*
     2568     * Apply the changes to the session mask.
     2569     */
     2570    fPrevious = pSession->fEventFilter;
     2571    pSession->fEventFilter |= fOrMask;
     2572    pSession->fEventFilter &= fNotMask;
     2573
     2574    /*
     2575     * If anything actually changed, update the global usage counters.
     2576     */
     2577    fChanged = fPrevious ^ pSession->fEventFilter;
     2578    if (fChanged)
     2579    {
     2580        bool fGlobalChange = vbgdBitUsageTrackerChange(&pDevExt->EventFilterTracker, fChanged, fPrevious,
     2581                                                       pDevExt->cSessions, "EventFilterTracker");
     2582
     2583        /*
     2584         * If there are global changes, update the event filter on the host.
     2585         */
     2586        if (fGlobalChange || pDevExt->fEventFilterHost == UINT32_MAX)
     2587        {
     2588            Assert(pReq || fSessionTermination);
     2589            if (pReq)
     2590            {
     2591                pReq->u32OrMask = pDevExt->fFixedEvents | pDevExt->EventFilterTracker.fMask;
     2592                if (pReq->u32OrMask == pDevExt->fEventFilterHost)
     2593                    rc = VINF_SUCCESS;
     2594                else
     2595                {
     2596                    pDevExt->fEventFilterHost = pReq->u32OrMask;
     2597                    pReq->u32NotMask = ~pReq->u32OrMask;
     2598                    rc = VbglGRPerform(&pReq->header);
     2599                    if (RT_FAILURE(rc))
     2600                    {
     2601                        /*
     2602                         * Failed, roll back (unless it's session termination time).
     2603                         */
     2604                        pDevExt->fEventFilterHost = UINT32_MAX;
     2605                        if (!fSessionTermination)
     2606                        {
     2607                            vbgdBitUsageTrackerChange(&pDevExt->EventFilterTracker, fChanged, pSession->fEventFilter,
     2608                                                      pDevExt->cSessions, "EventFilterTracker");
     2609                            pSession->fEventFilter = fPrevious;
     2610                        }
     2611                    }
     2612                }
     2613            }
     2614            else
     2615                rc = VINF_SUCCESS;
     2616        }
     2617    }
     2618
     2619    RTSpinlockRelease(pDevExt->SessionSpinlock);
     2620    if (pReq)
     2621        VbglGRFree(&pReq->header);
     2622    return rc;
     2623}
     2624
     2625
     2626/**
     2627 * Handle VBOXGUEST_IOCTL_CTL_FILTER_MASK.
     2628 *
     2629 * @returns VBox status code.
     2630 *
     2631 * @param   pDevExt             The device extension.
     2632 * @param   pSession            The session.
     2633 * @param   pInfo               The request.
     2634 */
     2635static int VBoxGuestCommonIOCtl_CtlFilterMask(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession,
     2636                                              VBoxGuestFilterMaskInfo *pInfo)
     2637{
     2638    LogFlow(("VBoxGuestCommonIOCtl: CTL_FILTER_MASK or=%#x not=%#x\n", pInfo->u32OrMask, pInfo->u32NotMask));
     2639
     2640    if ((pInfo->u32OrMask | pInfo->u32NotMask) & ~VMMDEV_EVENT_VALID_EVENT_MASK)
     2641    {
     2642        Log(("VBoxGuestCommonIOCtl: CTL_FILTER_MASK or=%#x not=%#x: Invalid masks!\n", pInfo->u32OrMask, pInfo->u32NotMask));
     2643        return VERR_INVALID_PARAMETER;
     2644    }
     2645
     2646    return vbgdSetSessionEventFilter(pDevExt, pSession, pInfo->u32OrMask, pInfo->u32NotMask, false /*fSessionTermination*/);
     2647}
     2648
     2649
     2650/**
     2651 * Init and termination worker for set mouse feature status to zero on the host.
     2652 *
     2653 * @returns VBox status code.
     2654 * @param   pDevExt         The device extension.
     2655 */
     2656static int vbgdResetMouseStatusOnHost(PVBOXGUESTDEVEXT pDevExt)
     2657{
     2658    VMMDevReqMouseStatus *pReq;
     2659    int rc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, sizeof(*pReq), VMMDevReq_SetMouseStatus);
     2660    if (RT_SUCCESS(rc))
     2661    {
     2662        pReq->mouseFeatures = 0;
     2663        pReq->pointerXPos   = 0;
     2664        pReq->pointerYPos   = 0;
     2665        rc = VbglGRPerform(&pReq->header);
     2666        if (RT_FAILURE(rc))
     2667            LogRelFunc(("failed with rc=%Rrc\n", rc));
     2668        VbglGRFree(&pReq->header);
     2669    }
     2670    return rc;
     2671}
     2672
     2673
     2674/**
     2675 * Changes the mouse status mask for the given session.
     2676 *
     2677 * This is called in response to VBOXGUEST_IOCTL_SET_MOUSE_STATUS as well as to
     2678 * do session cleanup.
     2679 *
     2680 * @returns VBox status code.
     2681 * @param   pDevExt             The device extension.
     2682 * @param   pSession            The session.
     2683 * @param   fOrMask             The status flags to add.
     2684 * @param   fNotMask            The status flags to remove.
     2685 * @param   fSessionTermination Set if we're called by the session cleanup code.
     2686 *                              This tweaks the error handling so we perform
     2687 *                              proper session cleanup even if the host
     2688 *                              misbehaves.
     2689 *
     2690 * @remarks Takes the session spinlock.
     2691 */
     2692static int vbgdSetSessionMouseStatus(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession,
     2693                                     uint32_t fOrMask, uint32_t fNotMask, bool fSessionTermination)
     2694{
     2695    VMMDevReqMouseStatus   *pReq;
     2696    uint32_t                fChanged;
     2697    uint32_t                fPrevious;
     2698    int                     rc;
     2699
     2700    /*
     2701     * Preallocate a request buffer so we can do all in one go without leaving the spinlock.
     2702     */
     2703    rc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, sizeof(*pReq), VMMDevReq_SetMouseStatus);
     2704    if (RT_SUCCESS(rc))
     2705    { /* nothing */ }
     2706    else if (!fSessionTermination)
     2707    {
     2708        LogRel(("vbgdSetSessionMouseStatus: VbglGRAlloc failure: %Rrc\n", rc));
     2709        return rc;
     2710    }
     2711    else
     2712        pReq = NULL; /* Ignore failure, we must do session cleanup. */
     2713
     2714
     2715    RTSpinlockAcquire(pDevExt->SessionSpinlock);
     2716
     2717    /*
     2718     * Apply the changes to the session mask.
     2719     */
     2720    fPrevious = pSession->fMouseStatus;
     2721    pSession->fMouseStatus |= fOrMask;
     2722    pSession->fMouseStatus &= fNotMask;
     2723
     2724    /*
     2725     * If anything actually changed, update the global usage counters.
     2726     */
     2727    fChanged = fPrevious ^ pSession->fMouseStatus;
     2728    if (fChanged)
     2729    {
     2730        bool fGlobalChange = vbgdBitUsageTrackerChange(&pDevExt->MouseStatusTracker, fChanged, fPrevious,
     2731                                                       pDevExt->cSessions, "MouseStatusTracker");
     2732
     2733        /*
     2734         * If there are global changes, update the event filter on the host.
     2735         */
     2736        if (fGlobalChange || pDevExt->fMouseStatusHost == UINT32_MAX)
     2737        {
     2738            Assert(pReq || fSessionTermination);
     2739            if (pReq)
     2740            {
     2741                /* Since VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR is inverted in the session
     2742                 * capabilities we invert it again here before sending it to the host. */
     2743                pReq->mouseFeatures = pDevExt->MouseStatusTracker.fMask ^ VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR;
     2744                if (pReq->mouseFeatures == pDevExt->fMouseStatusHost)
     2745                    rc = VINF_SUCCESS;
     2746                else
     2747                {
     2748                    pDevExt->fMouseStatusHost = pReq->mouseFeatures;
     2749                    pReq->pointerXPos = 0;
     2750                    pReq->pointerYPos = 0;
     2751                    rc = VbglGRPerform(&pReq->header);
     2752                    if (RT_FAILURE(rc))
     2753                    {
     2754                        /*
     2755                         * Failed, roll back (unless it's session termination time).
     2756                         */
     2757                        pDevExt->fMouseStatusHost = UINT32_MAX;
     2758                        if (!fSessionTermination)
     2759                        {
     2760                            vbgdBitUsageTrackerChange(&pDevExt->MouseStatusTracker, fChanged, pSession->fMouseStatus,
     2761                                                      pDevExt->cSessions, "MouseStatusTracker");
     2762                            pSession->fMouseStatus = fPrevious;
     2763                        }
     2764                    }
     2765                }
     2766            }
     2767            else
     2768                rc = VINF_SUCCESS;
     2769        }
     2770    }
     2771
     2772    RTSpinlockRelease(pDevExt->SessionSpinlock);
     2773    if (pReq)
     2774        VbglGRFree(&pReq->header);
     2775    return rc;
     2776}
     2777
     2778
     2779/**
     2780 * Sets the mouse status features for this session and updates them globally.
     2781 *
     2782 * @returns VBox status code.
     2783 *
     2784 * @param   pDevExt             The device extention.
     2785 * @param   pSession            The session.
     2786 * @param   fFeatures           New bitmap of enabled features.
     2787 */
     2788static int vboxGuestCommonIOCtl_SetMouseStatus(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, uint32_t fFeatures)
    24342789{
    24352790    int rc;
    2436 
    2437     pReq->u32OrMask = fMask;
    2438     pReq->u32NotMask = ~fMask;
    2439     rc = VbglGRPerform(&pReq->header);
    2440     if (RT_FAILURE(rc))
    2441         LogRel(("vboxGuestSetFilterMask: failed with rc=%Rrc\n", rc));
    2442     return rc;
    2443 }
    2444 
    2445 
    2446 /**
    2447  * Sets the mouse status to the host.
    2448  *
    2449  * This will ASSUME that we're the ones in charge of the mask, so
    2450  * we'll simply clear all bits we don't set.
    2451  *
    2452  * @returns VBox status code.
    2453  * @param   fMask       The new mask.
    2454  */
    2455 static int vboxGuestSetMouseStatus(VMMDevReqMouseStatus *pReq, uint32_t fMask)
    2456 {
    2457     int rc;
    2458 
    2459     pReq->mouseFeatures = fMask;
    2460     pReq->pointerXPos   = 0;
    2461     pReq->pointerYPos   = 0;
    2462     rc = VbglGRPerform(&pReq->header);
    2463     if (RT_FAILURE(rc))
    2464         LogRelFunc(("failed with rc=%Rrc\n", rc));
    2465     return rc;
    2466 }
    2467 
    2468 
    2469 static int vboxGuestGetHostFlagsFromSessions(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession,
    2470                                              uint32_t *pfFilterMask, uint32_t *pfMouseStatus)
    2471 {
    2472     PVBOXGUESTSESSION pIterator;
    2473     uint32_t fFilterMask = 0;
    2474     uint32_t fMouseStatus = 0;
    2475     unsigned cSessions = 0;
    2476     int rc = VINF_SUCCESS;
    2477 
    2478 /** @todo r=bird: Please just do the global bit counting thing.  This code
    2479  * gives me the [performances] creeps.  */
    2480     RTListForEach(&pDevExt->SessionList, pIterator, VBOXGUESTSESSION, ListNode)
    2481     {
    2482         fFilterMask   |= pIterator->fFilterMask;
    2483         fMouseStatus  |= pIterator->fMouseStatus;
    2484         ++cSessions;
    2485     }
    2486     if (!cSessions)
    2487         if (fFilterMask | fMouseStatus)
    2488             rc = VERR_INTERNAL_ERROR;
    2489     if (cSessions == 1 && pSession)
    2490         if (   fFilterMask   != pSession->fFilterMask
    2491             || fMouseStatus  != pSession->fMouseStatus)
    2492             rc = VERR_INTERNAL_ERROR;
    2493     if (cSessions > 1 && pSession)
    2494         if (   ~fFilterMask   & pSession->fFilterMask
    2495             || ~fMouseStatus  & pSession->fMouseStatus)
    2496             rc = VERR_INTERNAL_ERROR;
    2497     *pfFilterMask = fFilterMask;
    2498     *pfMouseStatus = fMouseStatus;
    2499     return rc;
    2500 }
    2501 
    2502 
    2503 /**
    2504  * Calls the host and set the filter mask, capabilities and/or mouse status.
    2505  *
    2506  * Check which host flags in a given category are being asserted by some guest
    2507  * session and assert exactly those on the host which are being asserted by one
    2508  * or more sessions.  pCallingSession is purely for sanity checking and can be
    2509  * NULL.
    2510  *
    2511  * @note Takes the session spin-lock.
    2512  */
    2513 static int vboxGuestUpdateHostFlags(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, unsigned fFlags)
    2514 {
    2515     int rc;
    2516     VMMDevCtlGuestFilterMask    *pFilterReq = NULL;
    2517     VMMDevReqMouseStatus        *pStatusReq = NULL;
    2518     uint32_t                     fFilterMask = 0;
    2519     uint32_t                     fMouseStatus = 0;
    2520 
    2521     rc = VbglGRAlloc((VMMDevRequestHeader **)&pFilterReq, sizeof(*pFilterReq),
    2522                      VMMDevReq_CtlGuestFilterMask);
    2523     if (RT_SUCCESS(rc))
    2524         rc = VbglGRAlloc((VMMDevRequestHeader **)&pStatusReq,
    2525                          sizeof(*pStatusReq), VMMDevReq_SetMouseStatus);
    2526     if (RT_SUCCESS(rc))
    2527     {
    2528         RTSpinlockAcquire(pDevExt->SessionSpinlock);
    2529         rc = vboxGuestGetHostFlagsFromSessions(pDevExt, pSession, &fFilterMask, &fMouseStatus);
    2530         if (RT_SUCCESS(rc))
    2531         {
    2532             fFilterMask |= pDevExt->fFixedEvents;
    2533             /* Since VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR is inverted in the session
    2534              * capabilities we invert it again before sending it to the host. */
    2535             fMouseStatus ^= VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR;
    2536             if (fFlags & HostFlags_FilterMask)
    2537                 vboxGuestSetFilterMask(pFilterReq, fFilterMask);
    2538             if (fFlags & HostFlags_MouseStatus)
    2539                 vboxGuestSetMouseStatus(pStatusReq, fMouseStatus);
    2540         }
    2541         RTSpinlockRelease(pDevExt->SessionSpinlock);
    2542     }
    2543     if (pFilterReq)
    2544         VbglGRFree(&pFilterReq->header);
    2545     if (pStatusReq)
    2546         VbglGRFree(&pStatusReq->header);
    2547 
    2548     return rc;
    2549 }
    2550 
    2551 
    2552 /**
    2553  * Return the mask of VMM device events that this session is allowed to see.
     2791    LogFlow(("VBoxGuestCommonIOCtl: CTL_FILTER_MASK features=%#x\n", fFeatures));
     2792
     2793    if (fFeatures & ~VMMDEV_MOUSE_GUEST_MASK)
     2794        return VERR_INVALID_PARAMETER;
     2795
     2796    /* Since this is more of a negative feature we invert it to get the real
     2797     * feature (when the guest does not need the host cursor). */
     2798    fFeatures ^= VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR;
     2799
     2800    return vbgdSetSessionMouseStatus(pDevExt, pSession, fFeatures, ~fFeatures, false /*fSessionTermination*/);
     2801}
     2802
     2803
     2804/**
     2805 * Return the mask of VMM device events that this session is allowed to see (wrt
     2806 * to "acquire" mode guest capabilities).
    25542807 *
    25552808 * The events associated with guest capabilities in "acquire" mode will be
     
    26002853
    26012854/**
     2855 * Init and termination worker for set guest capabilities to zero on the host.
     2856 *
     2857 * @returns VBox status code.
     2858 * @param   pDevExt         The device extension.
     2859 */
     2860static int vbgdResetCapabilitiesOnHost(PVBOXGUESTDEVEXT pDevExt)
     2861{
     2862    VMMDevReqGuestCapabilities2 *pReq;
     2863    int rc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, sizeof(*pReq), VMMDevReq_SetGuestCapabilities);
     2864    if (RT_SUCCESS(rc))
     2865    {
     2866        pReq->u32NotMask = UINT32_MAX;
     2867        pReq->u32OrMask  = 0;
     2868        rc = VbglGRPerform(&pReq->header);
     2869
     2870        if (RT_FAILURE(rc))
     2871            LogRelFunc(("failed with rc=%Rrc\n", rc));
     2872        VbglGRFree(&pReq->header);
     2873    }
     2874    return rc;
     2875}
     2876
     2877
     2878/**
    26022879 * Sets the guest capabilities to the host while holding the lock.
    26032880 *
     
    26132890    uint32_t iBit;
    26142891
    2615     pReq->u32OrMask = pDevExt->u32GuestCapsAcquired;
    2616     for (iBit = 0; iBit < 32; iBit++)
    2617         if (pDevExt->acGuestCapsSet[iBit] > 0)
    2618             pReq->u32OrMask |= RT_BIT_32(iBit);
    2619 
     2892    pReq->u32OrMask = pDevExt->u32GuestCapsAcquired | pDevExt->SetGuestCapsTracker.fMask;
    26202893    if (pReq->u32OrMask == pDevExt->fGuestCapsHost)
    26212894        rc = VINF_SUCCESS;
     
    26342907
    26352908/**
    2636  * Sets the guest capabilities to the host.
    2637  *
    2638  * This will ASSUME that we're the ones in charge of the mask, so
    2639  * we'll simply clear all bits we don't set.
    2640  *
    2641  * @returns VBox status code.
    2642  * @param   fMask       The new mask.
    2643  */
    2644 static int vbgdUpdateCapabilitiesOnHost(PVBOXGUESTDEVEXT pDevExt)
    2645 {
    2646     VMMDevReqGuestCapabilities2 *pReq;
    2647     int rc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, sizeof(*pReq), VMMDevReq_SetGuestCapabilities);
    2648     if (RT_SUCCESS(rc))
    2649     {
    2650         RTSpinlockAcquire(pDevExt->SessionSpinlock);
    2651 
    2652         rc = vbgdUpdateCapabilitiesOnHostWithReqAndLock(pDevExt, pReq);
    2653 
    2654         RTSpinlockRelease(pDevExt->SessionSpinlock);
    2655 
    2656         if (RT_FAILURE(rc))
    2657             LogRelFunc(("failed with rc=%Rrc\n", rc));
    2658         VbglGRFree(&pReq->header);
    2659     }
    2660     return rc;
    2661 }
    2662 
    2663 
    2664 /**
    2665  * Switch a set of capabilities into "acuquire" mode and (maybe) acquire them
    2666  * for the given session.
     2909 * Switch a set of capabilities into "acquire" mode and (maybe) acquire them for
     2910 * the given session.
    26672911 *
    26682912 * This is called in response to VBOXGUEST_IOCTL_GUEST_CAPS_ACQUIRE as well as
     
    27192963        return VERR_INVALID_PARAMETER;
    27202964    }
     2965    Assert(!fOrMask || !fSessionTermination);
    27212966
    27222967    /* The fNotMask no need to have all values valid, invalid ones will simply be ignored. */
     
    27302975    {
    27312976        rc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, sizeof(*pReq), VMMDevReq_SetGuestCapabilities);
    2732         if (RT_FAILURE(rc))
     2977        if (RT_SUCCESS(rc))
     2978        { /* do nothing */ }
     2979        else if (!fSessionTermination)
    27332980        {
    27342981            LogRel(("vbgdAcquireSessionCapabilities: pSession=%p fOrMask=%#x fNotMask=%#x enmFlags=%#x: VbglGRAlloc failure: %Rrc\n",
     
    27362983            return rc;
    27372984        }
     2985        else
     2986            pReq = NULL; /* Ignore failure, we must do session cleanup. */
    27382987    }
    27392988
     
    27422991     *
    27432992     * Note! We currently ignore anyone which may already have "set" the capabilities
    2744      *       in fOrMask.  This is simple, but perhaps not the best idea?
     2993     *       in fOrMask.  Perhaps not the best way to handle it, but it's simple...
    27452994     */
    27462995    RTSpinlockAcquire(pDevExt->EventSpinlock);
     
    27723021        return VINF_SUCCESS;
    27733022    }
    2774     Assert(pReq);
     3023    Assert(pReq || fSessionTermination);
    27753024
    27763025    /*
     
    28033052         * If something changes (which is very likely), tell the host.
    28043053         */
    2805         if (fSessionAddedCaps || fSessionRemovedCaps)
    2806         {
    2807             rc = vbgdUpdateCapabilitiesOnHostWithReqAndLock(pDevExt, pReq);
    2808             if (RT_FAILURE(rc))
     3054        if (fSessionAddedCaps || fSessionRemovedCaps || pDevExt->fGuestCapsHost == UINT32_MAX)
     3055        {
     3056            Assert(pReq || fSessionTermination);
     3057            if (pReq)
    28093058            {
    2810                 /*
    2811                  * Failed, roll back.  Except, don't roll back session cleanups.
    2812                  */
    2813                 if (fSessionAddedCaps)
     3059                rc = vbgdUpdateCapabilitiesOnHostWithReqAndLock(pDevExt, pReq);
     3060                if (RT_FAILURE(rc) && !fSessionTermination)
    28143061                {
    2815                     pSession->u32AquiredGuestCaps &= ~fSessionAddedCaps;
    2816                     pDevExt->u32GuestCapsAcquired &= ~fSessionAddedCaps;
     3062                    /* Failed, roll back. */
     3063                    if (fSessionAddedCaps)
     3064                    {
     3065                        pSession->u32AquiredGuestCaps &= ~fSessionAddedCaps;
     3066                        pDevExt->u32GuestCapsAcquired &= ~fSessionAddedCaps;
     3067                    }
     3068                    if (fSessionRemovedCaps)
     3069                    {
     3070                        pSession->u32AquiredGuestCaps |= fSessionRemovedCaps;
     3071                        pDevExt->u32GuestCapsAcquired |= fSessionRemovedCaps;
     3072                    }
     3073
     3074                    RTSpinlockRelease(pDevExt->EventSpinlock);
     3075                    LogRel(("vbgdAcquireSessionCapabilities: VBoxGuestSetGuestCapabilities failed: rc=%Rrc\n", rc));
     3076                    VbglGRFree(&pReq->header);
     3077                    return rc;
    28173078                }
    2818                 if (fSessionRemovedCaps && !fSessionTermination)
    2819                 {
    2820                     pSession->u32AquiredGuestCaps |= fSessionRemovedCaps;
    2821                     pDevExt->u32GuestCapsAcquired |= fSessionRemovedCaps;
    2822                 }
    2823 
    2824                 RTSpinlockRelease(pDevExt->EventSpinlock);
    2825                 LogRel(("vbgdAcquireSessionCapabilities: VBoxGuestSetGuestCapabilities failed: rc=%Rrc\n", rc));
    2826                 VbglGRFree(&pReq->header);
    2827                 return rc;
    28283079            }
    28293080        }
    2830 
    28313081    }
    28323082    else
     
    28403090
    28413091    RTSpinlockRelease(pDevExt->EventSpinlock);
    2842     VbglGRFree(&pReq->header);
     3092    if (pReq)
     3093        VbglGRFree(&pReq->header);
    28433094
    28443095    /*
     
    29053156 * @param   fOrMask             The capabilities to add.
    29063157 * @param   fNotMask            The capabilities to remove.
     3158 * @param   fSessionTermination Set if we're called by the session cleanup code.
     3159 *                              This tweaks the error handling so we perform
     3160 *                              proper session cleanup even if the host
     3161 *                              misbehaves.
    29073162 *
    29083163 * @remarks Takes the session spinlock.
    29093164 */
    2910 static int vbgdSetSessionCapabilities(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, uint32_t fOrMask, uint32_t fNotMask)
    2911 {
    2912     int rc;
     3165static int vbgdSetSessionCapabilities(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession,
     3166                                      uint32_t fOrMask, uint32_t fNotMask, bool fSessionTermination)
     3167{
     3168    /*
     3169     * Preallocate a request buffer so we can do all in one go without leaving the spinlock.
     3170     */
     3171    VMMDevReqGuestCapabilities2 *pReq;
     3172    int rc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, sizeof(*pReq), VMMDevReq_SetGuestCapabilities);
     3173    if (RT_SUCCESS(rc))
     3174    { /* nothing */ }
     3175    else if (!fSessionTermination)
     3176    {
     3177        LogRel(("vbgdSetSessionCapabilities: VbglGRAlloc failure: %Rrc\n", rc));
     3178        return rc;
     3179    }
     3180    else
     3181        pReq = NULL; /* Ignore failure, we must do session cleanup. */
     3182
     3183
    29133184    RTSpinlockAcquire(pDevExt->SessionSpinlock);
    29143185
     
    29353206        if (fChanged)
    29363207        {
    2937             bool        fGlobalChange = false;
    2938             uint32_t    iBit;
    2939             for (iBit = ASMBitFirstSetU32(fChanged) - 1; iBit < 32; iBit++)
    2940                 if (RT_BIT_32(iBit) & fChanged)
     3208            bool fGlobalChange = vbgdBitUsageTrackerChange(&pDevExt->SetGuestCapsTracker, fChanged, fPrevious,
     3209                                                           pDevExt->cSessions, "SetGuestCapsTracker");
     3210
     3211            /*
     3212             * If there are global changes, update the capabilities on the host.
     3213             */
     3214            if (fGlobalChange || pDevExt->fGuestCapsHost == UINT32_MAX)
     3215            {
     3216                Assert(pReq || fSessionTermination);
     3217                if (pReq)
    29413218                {
    2942                     if (fChanged & fPrevious)
     3219                    rc = vbgdUpdateCapabilitiesOnHostWithReqAndLock(pDevExt, pReq);
     3220
     3221                    /* On failure, roll back (unless it's session termination time). */
     3222                    if (RT_FAILURE(rc) && !fSessionTermination)
    29433223                    {
    2944                         pDevExt->acGuestCapsSet[iBit] -= 1;
    2945                         AssertMsg(pDevExt->acGuestCapsSet[iBit] <= pDevExt->cSessions,
    2946                                   ("pDevExt->acGuestCaps[%u]=%#x cSessions=%#x\n",
    2947                                    iBit, pDevExt->acGuestCapsSet[iBit], pDevExt->cSessions));
    2948                         fGlobalChange |= pDevExt->acGuestCapsSet[iBit] == 0;
     3224                        vbgdBitUsageTrackerChange(&pDevExt->SetGuestCapsTracker, fChanged, pSession->fCapabilities,
     3225                                                  pDevExt->cSessions, "SetGuestCapsTracker");
     3226                        pSession->fCapabilities = fPrevious;
    29493227                    }
    2950                     else
    2951                     {
    2952                         pDevExt->acGuestCapsSet[iBit] += 1;
    2953                         AssertMsg(pDevExt->acGuestCapsSet[iBit] > 0 && pDevExt->acGuestCapsSet[iBit] <= pDevExt->cSessions,
    2954                                   ("pDevExt->acGuestCaps[%u]=%#x cSessions=%#x\n",
    2955                                    iBit, pDevExt->acGuestCapsSet[iBit], pDevExt->cSessions));
    2956                         fGlobalChange |= pDevExt->acGuestCapsSet[iBit] == 1;
    2957                     }
    2958                     fChanged &= ~RT_BIT_32(iBit);
    2959                     if (!fChanged)
    2960                         break;
    29613228                }
    2962 
    2963             /*
    2964              * If there were global changes, update the capabilities on the host.
    2965              */
    2966             if (fGlobalChange)
    2967             {
    2968                 RTSpinlockRelease(pDevExt->SessionSpinlock);
    2969 
    2970                 return vbgdUpdateCapabilitiesOnHost(pDevExt);
    29713229            }
    29723230        }
    2973         rc = VINF_SUCCESS;
    29743231    }
    29753232#ifndef VBOXGUEST_DISREGARD_ACQUIRE_MODE_GUEST_CAPS
     
    29793236
    29803237    RTSpinlockRelease(pDevExt->SessionSpinlock);
     3238    if (pReq)
     3239        VbglGRFree(&pReq->header);
    29813240    return rc;
    29823241}
     
    29993258
    30003259    if (!((pInfo->u32OrMask | pInfo->u32NotMask) & ~VMMDEV_GUEST_CAPABILITIES_MASK))
    3001         rc = vbgdSetSessionCapabilities(pDevExt, pSession, pInfo->u32OrMask, pInfo->u32NotMask);
     3260        rc = vbgdSetSessionCapabilities(pDevExt, pSession, pInfo->u32OrMask, pInfo->u32NotMask, false /*fSessionTermination*/);
    30023261    else
    30033262        rc = VERR_INVALID_PARAMETER;
  • trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuestInternal.h

    r54601 r54606  
    109109typedef VBOXGUESTMEMBALLOON *PVBOXGUESTMEMBALLOON;
    110110
     111
     112/**
     113 * Per bit usage tracker for a uint32_t mask.
     114 *
     115 * Used for optimal handling of guest properties, mouse status and event filter.
     116 */
     117typedef struct VBOXGUESTBITUSAGETRACER
     118{
     119    /** Per bit usage counters. */
     120    uint32_t        acPerBitUsage[32];
     121    /** The current mask according to acPerBitUsage. */
     122    uint32_t        fMask;
     123} VBOXGUESTBITUSAGETRACER;
     124/** Pointer to a per bit usage tracker.  */
     125typedef VBOXGUESTBITUSAGETRACER *PVBOXGUESTBITUSAGETRACER;
     126/** Pointer to a const per bit usage tracker.  */
     127typedef VBOXGUESTBITUSAGETRACER const *PCVBOXGUESTBITUSAGETRACER;
     128
     129
    111130/**
    112131 * VBox guest device (data) extension.
     
    118137    /** Pointer to the mapping of the VMMDev adapter memory. */
    119138    VMMDevMemory volatile      *pVMMDevMemory;
    120     /** Events we won't permit anyone to filter out. */
    121     uint32_t                    fFixedEvents;
    122139    /** The memory object reserving space for the guest mappings. */
    123140    RTR0MEMOBJ                  hGuestMappings;
     
    173190    VBoxGuestMouseSetNotifyCallback MouseNotifyCallback;
    174191
    175     /** @name Guest Capabilities.
     192    /** @name Host Event Filtering
     193     * @{ */
     194    /** Events we won't permit anyone to filter out. */
     195    uint32_t                    fFixedEvents;
     196    /** Usage counters for the host events. (Fixed events are not included.) */
     197    VBOXGUESTBITUSAGETRACER     EventFilterTracker;
     198    /** The event filter last reported to the host (UINT32_MAX on failure). */
     199    uint32_t                    fEventFilterHost;
     200    /** @} */
     201
     202    /** @name Mouse Status
     203     * @{ */
     204    /** Usage counters for the mouse statuses (VMMDEV_MOUSE_XXX). */
     205    VBOXGUESTBITUSAGETRACER     MouseStatusTracker;
     206    /** The mouse status last reported to the host (UINT32_MAX on failure). */
     207    uint32_t                    fMouseStatusHost;
     208    /** @} */
     209
     210    /** @name Guest Capabilities
    176211     * @{ */
    177212    /** Guest capabilities which have been set to "acquire" mode.  This means
     
    190225    /** Usage counters for guest capabilities in "set" mode. Indexed by
    191226     *  capability bit number, one count per session using a capability. */
    192     uint32_t                    acGuestCapsSet[32];
    193     /** The set guest capabilities reported to the host. */
     227    VBOXGUESTBITUSAGETRACER     SetGuestCapsTracker;
     228    /** The guest capabilities last reported to the host (UINT32_MAX on failure). */
    194229    uint32_t                    fGuestCapsHost;
    195230    /** @} */
     
    241276     * Used to implement polling.  */
    242277    uint32_t volatile           u32MousePosChangedSeq;
    243     /** VMMDev events requested.  An event type requested in any guest session
    244      * will be added to the host filter.
    245      * Use under the VBOXGUESTDEVEXT#SessionSpinlock lock. */
    246     uint32_t                    fFilterMask;
     278    /** Host events requested by the session.
     279     * An event type requested in any guest session will be added to the host
     280     * filter.  Protected by VBOXGUESTDEVEXT::SessionSpinlock. */
     281    uint32_t                    fEventFilter;
    247282    /** Guest capabilities held in "acquired" by this session.
    248283     * Protected by VBOXGUESTDEVEXT::SessionSpinlock, but is unfortunately read
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette