VBoxDev.cpp revision aad14fb630be24973e77f45b777b714d68d348ae
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * VBox Guest/VMM/host communication:
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Virtual communication device
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Copyright (C) 2006-2007 innotek GmbH
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * available from http://www.virtualbox.org. This file is free software;
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * you can redistribute it and/or modify it under the terms of the GNU
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * General Public License as published by the Free Software Foundation,
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * distribution. VirtualBox OSE is distributed in the hope that it will
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * be useful, but WITHOUT ANY WARRANTY of any kind.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * If you received this file as part of a commercial VirtualBox
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * distribution, then only the terms of your commercial VirtualBox
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * license agreement apply instead of the previous paragraph.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync/* #define LOG_ENABLED */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync#define PCIDEV_2_VMMDEVSTATE(pPciDev) ( (VMMDevState *)(pPciDev) )
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync#define VMMDEVSTATE_2_DEVINS(pVMMDevState) ( (pVMMDevState)->pDevIns )
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync ((RT_HIWORD ((s)->guestInfo.additionsVersion) == 1) && \
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync (RT_LOWORD ((s)->guestInfo.additionsVersion) == 3))
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync#define VBOX_GUEST_ADDITIONS_VERSION_OK(additionsVersion) \
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync (RT_HIWORD(additionsVersion) == RT_HIWORD(VMMDEV_VERSION) \
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync && RT_LOWORD(additionsVersion) <= RT_LOWORD(VMMDEV_VERSION))
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync#define VBOX_GUEST_ADDITIONS_VERSION_OLD(additionsVersion) \
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync ((RT_HIWORD(additionsVersion) < RT_HIWORD(VMMDEV_VERSION) \
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync || ((RT_HIWORD(additionsVersion) == RT_HIWORD(VMMDEV_VERSION) \
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync && RT_LOWORD(additionsVersion) <= RT_LOWORD(VMMDEV_VERSION))
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync#define VBOX_GUEST_ADDITIONS_VERSION_TOO_OLD(additionsVersion) \
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync (RT_HIWORD(additionsVersion) < RT_HIWORD(VMMDEV_VERSION))
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync#define VBOX_GUEST_ADDITIONS_VERSION_NEW(additionsVersion) \
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync ((RT_HIWORD(additionsVersion) > RT_HIWORD(VMMDEV_VERSION) \
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync || ((RT_HIWORD(additionsVersion) == RT_HIWORD(VMMDEV_VERSION) \
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync && RT_LOWORD(additionsVersion) > RT_LOWORD(VMMDEV_VERSION))
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync/* Whenever host wants to inform guest about something
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * an IRQ notification will be raised.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * VMMDev PDM interface will contain the guest notification method.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * There is a 32 bit event mask which will be read
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * by guest on an interrupt. A non zero bit in the mask
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * means that the specific event occured and requires
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * processing on guest side.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * After reading the event mask guest must issue a
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * generic request AcknowlegdeEvents.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * IRQ line is set to 1 (request) if there are unprocessed
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * events, that is the event mask is not zero.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * After receiving an interrupt and checking event mask,
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * the guest must process events using the event specific
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * mechanism.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * That is if mouse capabilities were changed,
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * guest will use VMMDev_GetMouseStatus generic request.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Event mask is only a set of flags indicating that guest
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * must proceed with a procedure.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Unsupported events are therefore ignored.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * The guest additions must inform host which events they
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * want to receive, to avoid unnecessary IRQ processing.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * By default no events are signalled to guest.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * This seems to be fast method. It requires
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * only one context switch for an event processing.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncstatic void vmmdevSetIRQ_Legacy_EMT (VMMDevState *pVMMDevState)
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync Log(("vmmdevSetIRQ: IRQ is not generated, guest has not yet reported to us.\n"));
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* Filter unsupported events */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync & pVMMDevState->pVMMDevRAMHC->V.V1_03.u32GuestEventMask;
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync "pVMMDevState->u32HostEventFlags = 0x%08X, "
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync "pVMMDevState->pVMMDevRAMHC->u32GuestEventMask = 0x%08X\n",
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync pVMMDevState->pVMMDevRAMHC->V.V1_03.u32GuestEventMask));
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* Move event flags to VMMDev RAM */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync pVMMDevState->pVMMDevRAMHC->V.V1_03.u32HostEvents = u32EventFlags;
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* Clear host flags which will be delivered to guest. */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync Log(("vmmdevSetIRQ: pVMMDevState->u32HostEventFlags = 0x%08X\n",
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* Set IRQ level for pin 0 */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /** @todo make IRQ pin configurable, at least a symbolic constant */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync PPDMDEVINS pDevIns = VMMDEVSTATE_2_DEVINS(pVMMDevState);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncstatic void vmmdevMaybeSetIRQ_EMT (VMMDevState *pVMMDevState)
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync PPDMDEVINS pDevIns = VMMDEVSTATE_2_DEVINS (pVMMDevState);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync Log(("vmmdevMaybeSetIRQ_EMT: u32HostEventFlags = 0x%08X, u32GuestFilterMask = 0x%08X.\n",
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync pVMMDevState->u32HostEventFlags, pVMMDevState->u32GuestFilterMask));
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync#endif /* DEBUG_sunlover */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync if (pVMMDevState->u32HostEventFlags & pVMMDevState->u32GuestFilterMask)
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync pVMMDevState->pVMMDevRAMHC->V.V1_04.fHaveEvents = true;
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync#endif /* DEBUG_sunlover */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncstatic void vmmdevNotifyGuest_EMT (VMMDevState *pVMMDevState, uint32_t u32EventMask)
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync Log(("VMMDevNotifyGuest_EMT: u32EventMask = 0x%08X.\n", u32EventMask));
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync#endif /* DEBUG_sunlover */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync if (VBOX_GUEST_ADDITIONS_VERSION_1_03 (pVMMDevState))
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync Log(("VMMDevNotifyGuest_EMT: Old additions detected.\n"));
25747178cb66800d8386c20b8ffd87f78f24f4e5vboxsync#endif /* DEBUG_sunlover */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync Log(("VMMDevNotifyGuest_EMT: New additions detected.\n"));
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync#endif /* DEBUG_sunlover */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync Log(("vmmdevNotifyGuest_EMT: IRQ is not generated, guest has not yet reported to us.\n"));
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync (pVMMDevState->u32HostEventFlags & pVMMDevState->u32GuestFilterMask) != 0;
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync Log(("VMMDevNotifyGuest_EMT: fHadEvents = %d, u32HostEventFlags = 0x%08X, u32GuestFilterMask = 0x%08X.\n",
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync fHadEvents, pVMMDevState->u32HostEventFlags, pVMMDevState->u32GuestFilterMask));
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync#endif /* DEBUG_sunlover */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncstatic void vmmdevCtlGuestFilterMask_EMT (VMMDevState *pVMMDevState,
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync (pVMMDevState->u32HostEventFlags & pVMMDevState->u32GuestFilterMask) != 0;
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync Log(("vmmdevCtlGuestFilterMask_EMT: u32OrMask = 0x%08X, u32NotMask = 0x%08X, fHadEvents = %d.\n", u32OrMask, u32NotMask, fHadEvents));
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync pVMMDevState->u32NewGuestFilterMask = pVMMDevState->u32GuestFilterMask;
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync pVMMDevState->u32NewGuestFilterMask &= ~u32NotMask;
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncvoid VMMDevCtlSetGuestFilterMask (VMMDevState *pVMMDevState,
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync PPDMDEVINS pDevIns = VMMDEVSTATE_2_DEVINS(pVMMDevState);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync Log(("VMMDevCtlSetGuestFilterMask: u32OrMask = 0x%08X, u32NotMask = 0x%08X.\n", u32OrMask, u32NotMask));
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync vmmdevCtlGuestFilterMask_EMT (pVMMDevState, u32OrMask, u32NotMask);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync rc = VMR3ReqCallVoid (pVM, &pReq, RT_INDEFINITE_WAIT,
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncvoid VMMDevNotifyGuest (VMMDevState *pVMMDevState, uint32_t u32EventMask)
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync PPDMDEVINS pDevIns = VMMDEVSTATE_2_DEVINS(pVMMDevState);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync Log(("VMMDevNotifyGuest: u32EventMask = 0x%08X.\n", u32EventMask));
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync#endif /* DEBUG_sunlover */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync rc = VMR3ReqCallVoid (pVM, &pReq, RT_INDEFINITE_WAIT,
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Port I/O Handler for OUT operations.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @returns VBox status code.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param pDevIns The device instance.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param pvUser User argument - ignored.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param uPort Port number used for the IN operation.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param u32 The value to output.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param cb The value size in bytes.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncstatic DECLCALLBACK(int) vmmdevBackdoorLog(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync VMMDevState *pData = PDMINS2DATA(pDevIns, VMMDevState *);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync if (!pData->fBackdoorLogDisabled && cb == 1 && Port == RTLOG_DEBUG_PORT)
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* The raw version. */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync default: Log2(("vmmdev: %c (%02x)\n", u32, u32)); break;
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* The readable, buffered version. */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Port I/O Handler for OUT operations.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @returns VBox status code.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param pDevIns The device instance.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param pvUser User argument - ignored.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param uPort Port number used for the IN operation.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param u32 The value to output.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param cb The value size in bytes.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncstatic DECLCALLBACK(int) vmmdevTimesyncBackdoorWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync VMMDevState *pData = PDMINS2DATA(pDevIns, VMMDevState *);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Port I/O Handler for backdoor timesync IN operations.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @returns VBox status code.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param pDevIns The device instance.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param pvUser User argument - ignored.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param uPort Port number used for the IN operation.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param pu32 Where to store the result.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param cb Number of bytes read.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncstatic DECLCALLBACK(int) vmmdevTimesyncBackdoorRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync VMMDevState *pData = PDMINS2DATA(pDevIns, VMMDevState *);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync *pu32 = (uint32_t)(pData->hostTime & (uint64_t)0xFFFFFFFF);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync pData->hostTime = RTTimeSpecGetMilli(PDMDevHlpUTCNow(pDevIns, &now));
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync#endif /* TIMESYNC_BACKDOOR */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Port I/O Handler for the generic request interface
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @see FNIOMIOPORTOUT for details.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncstatic DECLCALLBACK(int) vmmdevRequestHandler(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * The caller has passed the guest context physical address
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * of the request structure. Get the corresponding host virtual
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync rc = PDMDevHlpPhys2HCVirt(pDevIns, (RTGCPHYS)u32, 0, (PRTHCPTR)&requestHeader);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync AssertMsgFailed(("VMMDev could not convert guest physical address to host virtual! rc = %Vrc\n", rc));
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* the structure size must be greater or equal to the header size */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync if (requestHeader->size < sizeof(VMMDevRequestHeader))
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync Log(("VMMDev request header size too small! size = %d\n", requestHeader->size));
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* check the version of the header structure */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync if (requestHeader->version != VMMDEV_REQUEST_HEADER_VERSION)
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync Log(("VMMDev: guest header version (0x%08X) differs from ours (0x%08X)\n", requestHeader->version, VMMDEV_REQUEST_HEADER_VERSION));
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync Log2(("VMMDev request issued: %d\n", requestHeader->requestType));
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync if (requestHeader->requestType != VMMDevReq_ReportGuestInfo
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync Log(("VMMDev: guest has not yet reported to us. Refusing operation.\n"));
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* which request was sent? */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Guest wants to give up a timeslice
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* just return to EMT telling it that we want to halt */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Guest is reporting its information
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync if (requestHeader->size < sizeof(VMMDevReportGuestInfo))
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync AssertMsgFailed(("VMMDev guest information structure has invalid size!\n"));
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync VMMDevReportGuestInfo *guestInfo = (VMMDevReportGuestInfo*)requestHeader;
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync if (memcmp (&pData->guestInfo, &guestInfo->guestInfo, sizeof (guestInfo->guestInfo)) != 0)
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* make a copy of supplied information */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* Check additions version */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync pData->fu32AdditionsOk = VBOX_GUEST_ADDITIONS_VERSION_OK(pData->guestInfo.additionsVersion);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync LogRel(("Guest Additions information report: additionsVersion = 0x%08X osType = 0x%08X\n",
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync pData->pDrv->pfnUpdateGuestVersion(pData->pDrv, &pData->guestInfo);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* Report guest capabilities */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync if (requestHeader->size != sizeof(VMMDevReqGuestCapabilities))
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync AssertMsgFailed(("VMMDev guest caps structure has invalid size!\n"));
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync VMMDevReqGuestCapabilities *guestCaps = (VMMDevReqGuestCapabilities*)requestHeader;
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* make a copy of supplied information */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync LogRel(("Guest Additions capability report: (0x%x) "
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync "VMMDEV_GUEST_SUPPORTS_SEAMLESS: %s "
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync "VMMDEV_GUEST_SUPPORTS_GUEST_HOST_WINDOW_MAPPING: %s\n",
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync guestCaps->caps & VMMDEV_GUEST_SUPPORTS_SEAMLESS ? "yes" : "no",
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync guestCaps->caps & VMMDEV_GUEST_SUPPORTS_GUEST_HOST_WINDOW_MAPPING ? "yes" : "no"));
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync pData->pDrv->pfnUpdateGuestCapabilities(pData->pDrv, guestCaps->caps);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Retrieve mouse information
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync if (requestHeader->size != sizeof(VMMDevReqMouseStatus))
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync AssertMsgFailed(("VMMDev mouse status structure has invalid size!\n"));
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync VMMDevReqMouseStatus *mouseStatus = (VMMDevReqMouseStatus*)requestHeader;
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync if (pData->mouseCapabilities & VMMDEV_MOUSEHOSTWANTSABS)
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync mouseStatus->mouseFeatures |= VBOXGUEST_MOUSE_HOST_CAN_ABSOLUTE;
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync if (pData->mouseCapabilities & VMMDEV_MOUSEGUESTWANTSABS)
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync mouseStatus->mouseFeatures |= VBOXGUEST_MOUSE_GUEST_CAN_ABSOLUTE;
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync if (pData->mouseCapabilities & VMMDEV_MOUSEHOSTCANNOTHWPOINTER)
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync mouseStatus->mouseFeatures |= VBOXGUEST_MOUSE_HOST_CANNOT_HWPOINTER;
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync Log(("returning mouse status: features = %d, absX = %d, absY = %d\n", mouseStatus->mouseFeatures,
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync mouseStatus->pointerXPos, mouseStatus->pointerYPos));
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Set mouse information
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync if (requestHeader->size != sizeof(VMMDevReqMouseStatus))
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync AssertMsgFailed(("VMMDev mouse status structure has invalid size %d (%#x) version=%d!\n",
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync requestHeader->size, requestHeader->size, requestHeader->size, requestHeader->version));
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync bool bCapsChanged = false;
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync VMMDevReqMouseStatus *mouseStatus = (VMMDevReqMouseStatus*)requestHeader;
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* check if the guest wants absolute coordinates */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync if (mouseStatus->mouseFeatures & VBOXGUEST_MOUSE_GUEST_CAN_ABSOLUTE)
25747178cb66800d8386c20b8ffd87f78f24f4e5vboxsync /* set the capability flag and the changed flag if it's actually a change */
25747178cb66800d8386c20b8ffd87f78f24f4e5vboxsync if (!(pData->mouseCapabilities & VMMDEV_MOUSEGUESTWANTSABS))
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync pData->mouseCapabilities |= VMMDEV_MOUSEGUESTWANTSABS;
25747178cb66800d8386c20b8ffd87f78f24f4e5vboxsync LogRel(("Guest requests mouse pointer integration\n"));
25747178cb66800d8386c20b8ffd87f78f24f4e5vboxsync if (pData->mouseCapabilities & VMMDEV_MOUSEGUESTWANTSABS)
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync pData->mouseCapabilities &= ~VMMDEV_MOUSEGUESTWANTSABS;
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync LogRel(("Guest disables mouse pointer integration\n"));
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync if (mouseStatus->mouseFeatures & VBOXGUEST_MOUSE_GUEST_NEEDS_HOST_CURSOR)
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync pData->mouseCapabilities |= VMMDEV_MOUSEGUESTNEEDSHOSTCUR;
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync pData->mouseCapabilities &= ~VMMDEV_MOUSEGUESTNEEDSHOSTCUR;
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Notify connector if something has changed
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync Log(("VMMDevReq_SetMouseStatus: capabilities changed (%x), informing connector\n", pData->mouseCapabilities));
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync pData->pDrv->pfnUpdateMouseCapabilities(pData->pDrv, pData->mouseCapabilities);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Set a new mouse pointer shape
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync if (requestHeader->size < sizeof(VMMDevReqMousePointer))
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync AssertMsg(requestHeader->size == 0x10028 && requestHeader->version == 10000, /* don't bitch about legacy!!! */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync ("VMMDev mouse shape structure has invalid size %d (%#x) version=%d!\n",
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync requestHeader->size, requestHeader->size, requestHeader->size, requestHeader->version));
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync VMMDevReqMousePointer *pointerShape = (VMMDevReqMousePointer*)requestHeader;
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync bool fVisible = (pointerShape->fFlags & VBOX_MOUSE_POINTER_VISIBLE) != 0;
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync bool fAlpha = (pointerShape->fFlags & VBOX_MOUSE_POINTER_ALPHA) != 0;
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync bool fShape = (pointerShape->fFlags & VBOX_MOUSE_POINTER_SHAPE) != 0;
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync Log(("VMMDevReq_SetPointerShape: visible: %d, alpha: %d, shape = %d, width: %d, height: %d\n",
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync fVisible, fAlpha, fShape, pointerShape->width, pointerShape->height));
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* forward call to driver */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Query the system time from the host
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync if (requestHeader->size != sizeof(VMMDevReqHostTime))
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync AssertMsgFailed(("VMMDev host time structure has invalid size!\n"));
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync VMMDevReqHostTime *hostTimeReq = (VMMDevReqHostTime*)requestHeader;
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync hostTimeReq->time = RTTimeSpecGetMilli(PDMDevHlpUTCNow(pDevIns, &now));
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Query information about the hypervisor
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync if (requestHeader->size != sizeof(VMMDevReqHypervisorInfo))
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync AssertMsgFailed(("VMMDev hypervisor info structure has invalid size!\n"));
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync VMMDevReqHypervisorInfo *hypervisorInfo = (VMMDevReqHypervisorInfo*)requestHeader;
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync requestHeader->rc = PGMR3MappingsSize(pVM, &hypervisorSize);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync hypervisorInfo->hypervisorSize = (uint32_t)hypervisorSize;
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync Assert(hypervisorInfo->hypervisorSize == hypervisorSize);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Set hypervisor information
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync if (requestHeader->size != sizeof(VMMDevReqHypervisorInfo))
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync AssertMsgFailed(("VMMDev hypervisor info structure has invalid size!\n"));
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync VMMDevReqHypervisorInfo *hypervisorInfo = (VMMDevReqHypervisorInfo*)requestHeader;
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* only if the client has queried the size before! */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync requestHeader->rc = PGMR3MappingsSize(pVM, &mappingsSize);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync if (VBOX_SUCCESS(requestHeader->rc) && (hypervisorInfo->hypervisorSize == mappingsSize))
case VMMDevReq_SetPowerStatus:
case VMMDevPowerState_Pause:
pData->displayChangeRequest.xres, pData->displayChangeRequest.yres, pData->displayChangeRequest.bpp));
pData->displayChangeRequest.xres, pData->displayChangeRequest.yres, pData->displayChangeRequest.bpp, pData->displayChangeRequest.display));
VMMDevVideoModeSupportedRequest *videoModeSupportedRequest = (VMMDevVideoModeSupportedRequest*)requestHeader;
VMMDevGetHeightReductionRequest *heightReductionRequest = (VMMDevGetHeightReductionRequest*)requestHeader;
#ifdef VBOX_HGCM
case VMMDevReq_HGCMConnect:
case VMMDevReq_HGCMDisconnect:
case VMMDevReq_HGCMCall:
Log(("VMMDevReq_VideoAccelEnable guest ring buffer size %d, should be %d!!!\n", ptr->cbRingBuffer, VBVA_RING_BUFFER_SIZE));
#ifdef DEBUG
case VMMDevReq_LogString:
return rcRet;
static DECLCALLBACK(int) vmmdevIORAMRegionMap(PPCIDEVICE pPciDev, /*unsigned*/ int iRegion, RTGCPHYS GCPhysAddress, uint32_t cb, PCIADDRESSSPACE enmType)
int rc;
LogFlow(("vmmdevR3IORAMRegionMap: iRegion=%d GCPhysAddress=%VGp cb=%#x enmType=%d\n", iRegion, GCPhysAddress, cb, enmType));
return VINF_SUCCESS;
AssertReleaseMsgFailed(("Failed to relocate VMMDev RAM from %VGp to %VGp! rc=%Vra\n", pData->GCPhysVMMDevRAM, GCPhysAddress, rc));
rc = MMR3PhysRegister(pVM, pData->pVMMDevRAMHC, GCPhysAddress, VMMDEV_RAM_SIZE, MM_RAM_FLAGS_MMIO2, "VBoxDev");
return VINF_SUCCESS;
return rc;
return VERR_INTERNAL_ERROR;
static DECLCALLBACK(int) vmmdevIOPortRegionMap(PPCIDEVICE pPciDev, /*unsigned*/ int iRegion, RTGCPHYS GCPhysAddress, uint32_t cb, PCIADDRESSSPACE enmType)
AssertMsg(RT_ALIGN(GCPhysAddress, 8) == GCPhysAddress, ("Expected 8 byte alignment. GCPhysAddress=%#x\n", GCPhysAddress));
return rc;
static DECLCALLBACK(void *) vmmdevPortQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface)
switch (enmInterface)
case PDMINTERFACE_BASE:
case PDMINTERFACE_VMMDEV_PORT:
#ifdef VBOX_HGCM
case PDMINTERFACE_HGCM_PORT:
return NULL;
#define IVMMDEVPORT_2_VMMDEVSTATE(pInterface) ( (VMMDevState*)((uintptr_t)pInterface - RT_OFFSETOF(VMMDevState, Port)) )
static DECLCALLBACK(int) vmmdevQueryAbsoluteMouse(PPDMIVMMDEVPORT pInterface, uint32_t *pAbsX, uint32_t *pAbsY)
if (pAbsX)
if (pAbsY)
return VINF_SUCCESS;
static DECLCALLBACK(int) vmmdevSetAbsoluteMouse(PPDMIVMMDEVPORT pInterface, uint32_t absX, uint32_t absY)
return VINF_SUCCESS;
static DECLCALLBACK(int) vmmdevQueryMouseCapabilities(PPDMIVMMDEVPORT pInterface, uint32_t *pCapabilities)
if (!pCapabilities)
return VERR_INVALID_PARAMETER;
return VINF_SUCCESS;
static DECLCALLBACK(int) vmmdevSetMouseCapabilities(PPDMIVMMDEVPORT pInterface, uint32_t capabilities)
if (bCapsChanged)
return VINF_SUCCESS;
static DECLCALLBACK(int) vmmdevRequestDisplayChange(PPDMIVMMDEVPORT pInterface, uint32_t xres, uint32_t yres, uint32_t bpp, uint32_t display)
fSameResolution = false;
#ifdef DEBUG_sunlover
Log(("vmmdevRequestDisplayChange: same=%d. new: xres=%d, yres=%d, bpp=%d, display=%d. old: xres=%d, yres=%d, bpp=%d, display=%d.\n",
fSameResolution, xres, yres, bpp, display, pData->lastReadDisplayChangeRequest.xres, pData->lastReadDisplayChangeRequest.yres, pData->lastReadDisplayChangeRequest.bpp, pData->lastReadDisplayChangeRequest.display));
if (!fSameResolution)
return VINF_SUCCESS;
if (!fSameMode)
return VINF_SUCCESS;
return VERR_INVALID_PARAMETER;
return VINF_SUCCESS;
if (pData)
#define IHGCMPORT_2_VMMDEVSTATE(pInterface) ( (VMMDevState*)((uintptr_t)pInterface - RT_OFFSETOF(VMMDevState, HGCMPort)) )
#ifdef VBOX_HGCM
return VINF_SUCCESS;
static DECLCALLBACK(int) vmmdevLoadState(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle, uint32_t u32Version)
#ifdef VBOX_HGCM
Log(("vmmdevLoadState: capabilities changed (%x), informing connector\n", pData->mouseCapabilities));
pData->pDrv->pfnVideoAccelEnable (pData->pDrv, !!pData->u32VideoAccelEnabled, &pData->pVMMDevRAMHC->vbvaMemory);
return VINF_SUCCESS;
#ifdef VBOX_HGCM
return VINF_SUCCESS;
int rc;
rc = PDMDevHlpIOPortRegister(pDevIns, RTLOG_DEBUG_PORT, 1, NULL, vmmdevBackdoorLog, NULL, NULL, NULL, "VMMDev backdoor logging");
#ifdef TIMESYNC_BACKDOOR
rc = PDMDevHlpIOPortRegister(pDevIns, 0x505, 1, NULL, vmmdevTimesyncBackdoorWrite, vmmdevTimesyncBackdoorRead, NULL, NULL, "VMMDev timesync backdoor");
return rc;
Log(("!!WARNING!!: pData->dev.devfn=%d (ignore if testcase or no started by Main)\n", pData->dev.devfn));
return rc;
rc = PDMDevHlpPCIIORegionRegister(pDevIns, 1, VMMDEV_RAM_SIZE, PCI_ADDRESS_SPACE_MEM, vmmdevIORAMRegionMap);
return rc;
#ifdef VBOX_HGCM
pData->pDrv = (PPDMIVMMDEVCONNECTOR)pData->pDrvBase->pfnQueryInterface(pData->pDrvBase, PDMINTERFACE_VMMDEV_CONNECTOR);
AssertMsgFailedReturn(("LUN #0 doesn't have a VMMDev connector interface!\n"), VERR_PDM_MISSING_INTERFACE);
#ifdef VBOX_HGCM
pData->pHGCMDrv = (PPDMIHGCMCONNECTOR)pData->pDrvBase->pfnQueryInterface(pData->pDrvBase, PDMINTERFACE_HGCM_CONNECTOR);
Log(("%s/%d: warning: no driver attached to LUN #0!\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
#ifdef VBOX_HGCM
return rc;
sizeof(VMMDevState),
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,