1
/* $Id: VBoxDev.cpp $ */
3
* VMMDev - Guest <-> VMM/Host communication device.
7
* Copyright (C) 2006-2007 Sun Microsystems, Inc.
9
* This file is part of VirtualBox Open Source Edition (OSE), as
10
* available from http://www.virtualbox.org. This file is free software;
11
* you can redistribute it and/or modify it under the terms of the GNU
12
* General Public License (GPL) as published by the Free Software
13
* Foundation, in version 2 as it comes in the "COPYING" file of the
14
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18
* Clara, CA 95054 USA or visit http://www.sun.com if you need
19
* additional information or have any questions.
23
/*******************************************************************************
25
*******************************************************************************/
26
/* #define LOG_ENABLED */
27
/* Enable dev_vmm Log3 statements to get IRQ-related logging. */
29
#define LOG_GROUP LOG_GROUP_DEV_VMM
30
#include <VBox/VBoxDev.h>
31
#include <VBox/VBoxGuest.h>
33
#include <VBox/param.h>
37
#include <VBox/vm.h> /* for VM_IS_EMT */
39
#include <iprt/assert.h>
40
#include <iprt/string.h>
41
#include <iprt/time.h>
43
# include <iprt/mem.h>
46
#include "VMMDevState.h"
48
# include "VMMDevHGCM.h"
52
/*******************************************************************************
53
* Defined Constants And Macros *
54
*******************************************************************************/
55
#define PCIDEV_2_VMMDEVSTATE(pPciDev) ( (VMMDevState *)(pPciDev) )
56
#define VMMDEVSTATE_2_DEVINS(pVMMDevState) ( (pVMMDevState)->pDevIns )
58
#define VBOX_GUEST_ADDITIONS_VERSION_1_03(s) \
59
((RT_HIWORD ((s)->guestInfo.additionsVersion) == 1) && \
60
(RT_LOWORD ((s)->guestInfo.additionsVersion) == 3))
62
#define VBOX_GUEST_ADDITIONS_VERSION_OK(additionsVersion) \
63
(RT_HIWORD(additionsVersion) == RT_HIWORD(VMMDEV_VERSION) \
64
&& RT_LOWORD(additionsVersion) <= RT_LOWORD(VMMDEV_VERSION))
66
#define VBOX_GUEST_ADDITIONS_VERSION_OLD(additionsVersion) \
67
((RT_HIWORD(additionsVersion) < RT_HIWORD(VMMDEV_VERSION) \
68
|| ((RT_HIWORD(additionsVersion) == RT_HIWORD(VMMDEV_VERSION) \
69
&& RT_LOWORD(additionsVersion) <= RT_LOWORD(VMMDEV_VERSION))
71
#define VBOX_GUEST_ADDITIONS_VERSION_TOO_OLD(additionsVersion) \
72
(RT_HIWORD(additionsVersion) < RT_HIWORD(VMMDEV_VERSION))
74
#define VBOX_GUEST_ADDITIONS_VERSION_NEW(additionsVersion) \
75
((RT_HIWORD(additionsVersion) > RT_HIWORD(VMMDEV_VERSION) \
76
|| ((RT_HIWORD(additionsVersion) == RT_HIWORD(VMMDEV_VERSION) \
77
&& RT_LOWORD(additionsVersion) > RT_LOWORD(VMMDEV_VERSION))
79
#ifndef VBOX_DEVICE_STRUCT_TESTCASE
81
/* Whenever host wants to inform guest about something
82
* an IRQ notification will be raised.
84
* VMMDev PDM interface will contain the guest notification method.
86
* There is a 32 bit event mask which will be read
87
* by guest on an interrupt. A non zero bit in the mask
88
* means that the specific event occurred and requires
89
* processing on guest side.
91
* After reading the event mask guest must issue a
92
* generic request AcknowlegdeEvents.
94
* IRQ line is set to 1 (request) if there are unprocessed
95
* events, that is the event mask is not zero.
97
* After receiving an interrupt and checking event mask,
98
* the guest must process events using the event specific
101
* That is if mouse capabilities were changed,
102
* guest will use VMMDev_GetMouseStatus generic request.
104
* Event mask is only a set of flags indicating that guest
105
* must proceed with a procedure.
107
* Unsupported events are therefore ignored.
108
* The guest additions must inform host which events they
109
* want to receive, to avoid unnecessary IRQ processing.
110
* By default no events are signalled to guest.
112
* This seems to be fast method. It requires
113
* only one context switch for an event processing.
117
static void vmmdevSetIRQ_Legacy_EMT (VMMDevState *pVMMDevState)
119
if (!pVMMDevState->fu32AdditionsOk)
121
Log(("vmmdevSetIRQ: IRQ is not generated, guest has not yet reported to us.\n"));
125
uint32_t u32IRQLevel = 0;
127
/* Filter unsupported events */
128
uint32_t u32EventFlags =
129
pVMMDevState->u32HostEventFlags
130
& pVMMDevState->pVMMDevRAMR3->V.V1_03.u32GuestEventMask;
132
Log(("vmmdevSetIRQ: u32EventFlags = 0x%08X, "
133
"pVMMDevState->u32HostEventFlags = 0x%08X, "
134
"pVMMDevState->pVMMDevRAMR3->u32GuestEventMask = 0x%08X\n",
136
pVMMDevState->u32HostEventFlags,
137
pVMMDevState->pVMMDevRAMR3->V.V1_03.u32GuestEventMask));
139
/* Move event flags to VMMDev RAM */
140
pVMMDevState->pVMMDevRAMR3->V.V1_03.u32HostEvents = u32EventFlags;
144
/* Clear host flags which will be delivered to guest. */
145
pVMMDevState->u32HostEventFlags &= ~u32EventFlags;
146
Log(("vmmdevSetIRQ: pVMMDevState->u32HostEventFlags = 0x%08X\n",
147
pVMMDevState->u32HostEventFlags));
151
/* Set IRQ level for pin 0 */
152
/** @todo make IRQ pin configurable, at least a symbolic constant */
153
PPDMDEVINS pDevIns = VMMDEVSTATE_2_DEVINS(pVMMDevState);
154
PDMDevHlpPCISetIrqNoWait(pDevIns, 0, u32IRQLevel);
155
Log(("vmmdevSetIRQ: IRQ set %d\n", u32IRQLevel));
158
static void vmmdevMaybeSetIRQ_EMT (VMMDevState *pVMMDevState)
160
PPDMDEVINS pDevIns = VMMDEVSTATE_2_DEVINS (pVMMDevState);
162
Log3(("vmmdevMaybeSetIRQ_EMT: u32HostEventFlags = 0x%08X, u32GuestFilterMask = 0x%08X.\n",
163
pVMMDevState->u32HostEventFlags, pVMMDevState->u32GuestFilterMask));
165
if (pVMMDevState->u32HostEventFlags & pVMMDevState->u32GuestFilterMask)
167
pVMMDevState->pVMMDevRAMR3->V.V1_04.fHaveEvents = true;
168
PDMDevHlpPCISetIrqNoWait (pDevIns, 0, 1);
169
Log3(("vmmdevMaybeSetIRQ_EMT: IRQ set.\n"));
173
static void vmmdevNotifyGuest_EMT (VMMDevState *pVMMDevState, uint32_t u32EventMask)
175
Log3(("VMMDevNotifyGuest_EMT: u32EventMask = 0x%08X.\n", u32EventMask));
177
if (VBOX_GUEST_ADDITIONS_VERSION_1_03 (pVMMDevState))
179
Log3(("VMMDevNotifyGuest_EMT: Old additions detected.\n"));
181
pVMMDevState->u32HostEventFlags |= u32EventMask;
182
vmmdevSetIRQ_Legacy_EMT (pVMMDevState);
186
Log3(("VMMDevNotifyGuest_EMT: New additions detected.\n"));
188
if (!pVMMDevState->fu32AdditionsOk)
190
pVMMDevState->u32HostEventFlags |= u32EventMask;
191
Log(("vmmdevNotifyGuest_EMT: IRQ is not generated, guest has not yet reported to us.\n"));
195
const bool fHadEvents =
196
(pVMMDevState->u32HostEventFlags & pVMMDevState->u32GuestFilterMask) != 0;
198
Log3(("VMMDevNotifyGuest_EMT: fHadEvents = %d, u32HostEventFlags = 0x%08X, u32GuestFilterMask = 0x%08X.\n",
199
fHadEvents, pVMMDevState->u32HostEventFlags, pVMMDevState->u32GuestFilterMask));
201
pVMMDevState->u32HostEventFlags |= u32EventMask;
204
vmmdevMaybeSetIRQ_EMT (pVMMDevState);
208
static void vmmdevCtlGuestFilterMask_EMT (VMMDevState *pVMMDevState,
212
const bool fHadEvents =
213
(pVMMDevState->u32HostEventFlags & pVMMDevState->u32GuestFilterMask) != 0;
215
Log(("vmmdevCtlGuestFilterMask_EMT: u32OrMask = 0x%08X, u32NotMask = 0x%08X, fHadEvents = %d.\n", u32OrMask, u32NotMask, fHadEvents));
218
if (!pVMMDevState->fNewGuestFilterMask)
219
pVMMDevState->u32NewGuestFilterMask = pVMMDevState->u32GuestFilterMask;
221
pVMMDevState->u32NewGuestFilterMask |= u32OrMask;
222
pVMMDevState->u32NewGuestFilterMask &= ~u32NotMask;
223
pVMMDevState->fNewGuestFilterMask = true;
227
pVMMDevState->u32GuestFilterMask |= u32OrMask;
228
pVMMDevState->u32GuestFilterMask &= ~u32NotMask;
229
vmmdevMaybeSetIRQ_EMT (pVMMDevState);
233
void VMMDevCtlSetGuestFilterMask (VMMDevState *pVMMDevState,
237
PPDMDEVINS pDevIns = VMMDEVSTATE_2_DEVINS(pVMMDevState);
238
PVM pVM = PDMDevHlpGetVM(pDevIns);
240
Log(("VMMDevCtlSetGuestFilterMask: u32OrMask = 0x%08X, u32NotMask = 0x%08X.\n", u32OrMask, u32NotMask));
244
vmmdevCtlGuestFilterMask_EMT (pVMMDevState, u32OrMask, u32NotMask);
251
rc = VMR3ReqCallVoid (pVM, VMCPUID_ANY, &pReq, RT_INDEFINITE_WAIT,
252
(PFNRT) vmmdevCtlGuestFilterMask_EMT,
253
3, pVMMDevState, u32OrMask, u32NotMask);
254
AssertReleaseRC (rc);
259
void VMMDevNotifyGuest (VMMDevState *pVMMDevState, uint32_t u32EventMask)
261
PPDMDEVINS pDevIns = VMMDEVSTATE_2_DEVINS(pVMMDevState);
262
PVM pVM = PDMDevHlpGetVM(pDevIns);
265
Log3(("VMMDevNotifyGuest: u32EventMask = 0x%08X.\n", u32EventMask));
268
* Drop notifications if the VM is not running yet/anymore.
270
if (PDMDevHlpVMState(pDevIns) != VMSTATE_RUNNING)
273
/* No need to wait for the completion of this request. It is a notification
274
* about something, which has already happened.
276
rc = VMR3ReqCallEx(pVM, VMCPUID_ANY, NULL, 0, VMREQFLAGS_NO_WAIT | VMREQFLAGS_VOID,
277
(PFNRT) vmmdevNotifyGuest_EMT,
278
2, pVMMDevState, u32EventMask);
283
* Port I/O Handler for OUT operations.
285
* @returns VBox status code.
287
* @param pDevIns The device instance.
288
* @param pvUser User argument - ignored.
289
* @param uPort Port number used for the IN operation.
290
* @param u32 The value to output.
291
* @param cb The value size in bytes.
293
static DECLCALLBACK(int) vmmdevBackdoorLog(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
295
VMMDevState *pThis = PDMINS_2_DATA(pDevIns, VMMDevState *);
297
if (!pThis->fBackdoorLogDisabled && cb == 1 && Port == RTLOG_DEBUG_PORT)
300
/* The raw version. */
303
case '\r': LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_2, LOG_GROUP_DEV_VMM_BACKDOOR, ("vmmdev: <return>\n")); break;
304
case '\n': LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_2, LOG_GROUP_DEV_VMM_BACKDOOR, ("vmmdev: <newline>\n")); break;
305
case '\t': LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_2, LOG_GROUP_DEV_VMM_BACKDOOR, ("vmmdev: <tab>\n")); break;
306
default: LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_2, LOG_GROUP_DEV_VMM_BACKDOOR, ("vmmdev: %c (%02x)\n", u32, u32)); break;
309
/* The readable, buffered version. */
310
if (u32 == '\n' || u32 == '\r')
312
pThis->szMsg[pThis->iMsg] = '\0';
314
LogRelIt(LOG_REL_INSTANCE, RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP_DEV_VMM_BACKDOOR, ("Guest Log: %s\n", pThis->szMsg));
319
if (pThis->iMsg >= sizeof(pThis->szMsg)-1)
321
pThis->szMsg[pThis->iMsg] = '\0';
322
LogRelIt(LOG_REL_INSTANCE, RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP_DEV_VMM_BACKDOOR, ("Guest Log: %s\n", pThis->szMsg));
325
pThis->szMsg[pThis->iMsg] = (char )u32;
326
pThis->szMsg[++pThis->iMsg] = '\0';
332
#ifdef TIMESYNC_BACKDOOR
334
* Port I/O Handler for OUT operations.
336
* @returns VBox status code.
338
* @param pDevIns The device instance.
339
* @param pvUser User argument - ignored.
340
* @param uPort Port number used for the IN operation.
341
* @param u32 The value to output.
342
* @param cb The value size in bytes.
344
static DECLCALLBACK(int) vmmdevTimesyncBackdoorWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
349
VMMDevState *pThis = PDMINS_2_DATA(pDevIns, VMMDevState *);
353
pThis->fTimesyncBackdoorLo = false;
356
pThis->fTimesyncBackdoorLo = true;
365
* Port I/O Handler for backdoor timesync IN operations.
367
* @returns VBox status code.
369
* @param pDevIns The device instance.
370
* @param pvUser User argument - ignored.
371
* @param uPort Port number used for the IN operation.
372
* @param pu32 Where to store the result.
373
* @param cb Number of bytes read.
375
static DECLCALLBACK(int) vmmdevTimesyncBackdoorRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
381
VMMDevState *pThis = PDMINS_2_DATA(pDevIns, VMMDevState *);
384
if (pThis->fTimesyncBackdoorLo)
385
*pu32 = (uint32_t)pThis->hostTime;
388
pThis->hostTime = RTTimeSpecGetMilli(PDMDevHlpUTCNow(pDevIns, &now));
389
*pu32 = (uint32_t)(pThis->hostTime >> 32);
394
rc = VERR_IOM_IOPORT_UNUSED;
397
#endif /* TIMESYNC_BACKDOOR */
400
* Port I/O Handler for the generic request interface
401
* @see FNIOMIOPORTOUT for details.
403
* @todo Too long, suggest doing the request copying here and moving the
404
* switch into a different function (or better case -> functions), and
407
static DECLCALLBACK(int) vmmdevRequestHandler(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
409
VMMDevState *pThis = (VMMDevState*)pvUser;
410
int rcRet = VINF_SUCCESS;
411
PDMCritSectEnter(&pThis->CritSect, VERR_SEM_BUSY);
414
* The caller has passed the guest context physical address
415
* of the request structure. Copy the request packet.
417
VMMDevRequestHeader requestHeader = {0};
418
VMMDevRequestHeader *pRequestHeader = NULL;
420
PDMDevHlpPhysRead(pDevIns, (RTGCPHYS)u32, &requestHeader, sizeof(requestHeader));
422
/* the structure size must be greater or equal to the header size */
423
if (requestHeader.size < sizeof(VMMDevRequestHeader))
425
Log(("VMMDev request header size too small! size = %d\n", requestHeader.size));
426
rcRet = VINF_SUCCESS;
427
goto end; /** @todo shouldn't (/ no need to) write back.*/
430
/* check the version of the header structure */
431
if (requestHeader.version != VMMDEV_REQUEST_HEADER_VERSION)
433
Log(("VMMDev: guest header version (0x%08X) differs from ours (0x%08X)\n", requestHeader.version, VMMDEV_REQUEST_HEADER_VERSION));
434
rcRet = VINF_SUCCESS;
435
goto end; /** @todo shouldn't (/ no need to) write back.*/
438
Log2(("VMMDev request issued: %d\n", requestHeader.requestType));
440
if ( requestHeader.requestType != VMMDevReq_ReportGuestInfo
441
&& !pThis->fu32AdditionsOk)
443
Log(("VMMDev: guest has not yet reported to us. Refusing operation.\n"));
444
requestHeader.rc = VERR_NOT_SUPPORTED;
445
rcRet = VINF_SUCCESS;
449
/* Check upper limit */
450
if (requestHeader.size > VMMDEV_MAX_VMMDEVREQ_SIZE)
452
LogRel(("VMMDev: request packet too big (%x). Refusing operation.\n", requestHeader.size));
453
requestHeader.rc = VERR_NOT_SUPPORTED;
454
rcRet = VINF_SUCCESS;
458
/* Read the entire request packet */
459
pRequestHeader = (VMMDevRequestHeader *)RTMemAlloc(requestHeader.size);
462
Log(("VMMDev: RTMemAlloc failed!\n"));
463
rcRet = VINF_SUCCESS;
464
requestHeader.rc = VERR_NO_MEMORY;
467
PDMDevHlpPhysRead(pDevIns, (RTGCPHYS)u32, pRequestHeader, requestHeader.size);
469
/* which request was sent? */
470
switch (pRequestHeader->requestType)
473
* Guest wants to give up a timeslice
477
/* just return to EMT telling it that we want to halt */
478
rcRet = VINF_EM_HALT;
483
* Guest is reporting its information
485
case VMMDevReq_ReportGuestInfo:
487
if (pRequestHeader->size < sizeof(VMMDevReportGuestInfo))
489
AssertMsgFailed(("VMMDev guest information structure has invalid size!\n"));
490
pRequestHeader->rc = VERR_INVALID_PARAMETER;
494
VMMDevReportGuestInfo *guestInfo = (VMMDevReportGuestInfo*)pRequestHeader;
496
if (memcmp (&pThis->guestInfo, &guestInfo->guestInfo, sizeof (guestInfo->guestInfo)) != 0)
498
/* make a copy of supplied information */
499
pThis->guestInfo = guestInfo->guestInfo;
501
/* Check additions version */
502
pThis->fu32AdditionsOk = VBOX_GUEST_ADDITIONS_VERSION_OK(pThis->guestInfo.additionsVersion);
504
LogRel(("Guest Additions information report: additionsVersion = 0x%08X osType = 0x%08X\n",
505
pThis->guestInfo.additionsVersion,
506
pThis->guestInfo.osType));
507
pThis->pDrv->pfnUpdateGuestVersion(pThis->pDrv, &pThis->guestInfo);
510
if (pThis->fu32AdditionsOk)
512
pRequestHeader->rc = VINF_SUCCESS;
516
pRequestHeader->rc = VERR_VERSION_MISMATCH;
522
/* Report guest capabilities */
523
case VMMDevReq_ReportGuestCapabilities:
525
if (pRequestHeader->size != sizeof(VMMDevReqGuestCapabilities))
527
AssertMsgFailed(("VMMDev guest caps structure has invalid size!\n"));
528
pRequestHeader->rc = VERR_INVALID_PARAMETER;
532
VMMDevReqGuestCapabilities *guestCaps = (VMMDevReqGuestCapabilities*)pRequestHeader;
534
/* Enable this automatically for guests using the old
535
request to report their capabilities. */
536
/** @todo change this when we next bump the interface version */
537
guestCaps->caps |= VMMDEV_GUEST_SUPPORTS_GRAPHICS;
538
if (pThis->guestCaps != guestCaps->caps)
540
/* make a copy of supplied information */
541
pThis->guestCaps = guestCaps->caps;
543
LogRel(("Guest Additions capability report: (0x%x) "
545
"hostWindowMapping: %s, "
548
guestCaps->caps & VMMDEV_GUEST_SUPPORTS_SEAMLESS ? "yes" : "no",
549
guestCaps->caps & VMMDEV_GUEST_SUPPORTS_GUEST_HOST_WINDOW_MAPPING ? "yes" : "no",
550
guestCaps->caps & VMMDEV_GUEST_SUPPORTS_GRAPHICS ? "yes" : "no"));
552
pThis->pDrv->pfnUpdateGuestCapabilities(pThis->pDrv, guestCaps->caps);
554
pRequestHeader->rc = VINF_SUCCESS;
559
/* Change guest capabilities */
560
case VMMDevReq_SetGuestCapabilities:
562
if (pRequestHeader->size != sizeof(VMMDevReqGuestCapabilities2))
564
AssertMsgFailed(("VMMDev guest caps structure has invalid size!\n"));
565
pRequestHeader->rc = VERR_INVALID_PARAMETER;
569
VMMDevReqGuestCapabilities2 *guestCaps = (VMMDevReqGuestCapabilities2*)pRequestHeader;
571
pThis->guestCaps |= guestCaps->u32OrMask;
572
pThis->guestCaps &= ~guestCaps->u32NotMask;
574
LogRel(("Guest Additions capability report: (0x%x) "
576
"hostWindowMapping: %s, "
579
pThis->guestCaps & VMMDEV_GUEST_SUPPORTS_SEAMLESS ? "yes" : "no",
580
pThis->guestCaps & VMMDEV_GUEST_SUPPORTS_GUEST_HOST_WINDOW_MAPPING ? "yes" : "no",
581
pThis->guestCaps & VMMDEV_GUEST_SUPPORTS_GRAPHICS ? "yes" : "no"));
583
pThis->pDrv->pfnUpdateGuestCapabilities(pThis->pDrv, pThis->guestCaps);
584
pRequestHeader->rc = VINF_SUCCESS;
590
* Retrieve mouse information
592
case VMMDevReq_GetMouseStatus:
594
if (pRequestHeader->size != sizeof(VMMDevReqMouseStatus))
596
AssertMsgFailed(("VMMDev mouse status structure has invalid size!\n"));
597
pRequestHeader->rc = VERR_INVALID_PARAMETER;
601
VMMDevReqMouseStatus *mouseStatus = (VMMDevReqMouseStatus*)pRequestHeader;
602
mouseStatus->mouseFeatures = 0;
603
if (pThis->mouseCapabilities & VMMDEV_MOUSEHOSTWANTSABS)
605
mouseStatus->mouseFeatures |= VBOXGUEST_MOUSE_HOST_CAN_ABSOLUTE;
607
if (pThis->mouseCapabilities & VMMDEV_MOUSEGUESTWANTSABS)
609
mouseStatus->mouseFeatures |= VBOXGUEST_MOUSE_GUEST_CAN_ABSOLUTE;
611
if (pThis->mouseCapabilities & VMMDEV_MOUSEHOSTCANNOTHWPOINTER)
613
mouseStatus->mouseFeatures |= VBOXGUEST_MOUSE_HOST_CANNOT_HWPOINTER;
615
mouseStatus->pointerXPos = pThis->mouseXAbs;
616
mouseStatus->pointerYPos = pThis->mouseYAbs;
617
Log2(("returning mouse status: features = %d, absX = %d, absY = %d\n", mouseStatus->mouseFeatures,
618
mouseStatus->pointerXPos, mouseStatus->pointerYPos));
619
pRequestHeader->rc = VINF_SUCCESS;
625
* Set mouse information
627
case VMMDevReq_SetMouseStatus:
629
if (pRequestHeader->size != sizeof(VMMDevReqMouseStatus))
631
AssertMsgFailed(("VMMDev mouse status structure has invalid size %d (%#x) version=%d!\n",
632
pRequestHeader->size, pRequestHeader->size, pRequestHeader->size, pRequestHeader->version));
633
pRequestHeader->rc = VERR_INVALID_PARAMETER;
637
bool bCapsChanged = false;
639
VMMDevReqMouseStatus *mouseStatus = (VMMDevReqMouseStatus*)pRequestHeader;
641
/* check if the guest wants absolute coordinates */
642
if (mouseStatus->mouseFeatures & VBOXGUEST_MOUSE_GUEST_CAN_ABSOLUTE)
644
/* set the capability flag and the changed flag if it's actually a change */
645
if (!(pThis->mouseCapabilities & VMMDEV_MOUSEGUESTWANTSABS))
647
pThis->mouseCapabilities |= VMMDEV_MOUSEGUESTWANTSABS;
649
LogRel(("Guest requests mouse pointer integration\n"));
653
if (pThis->mouseCapabilities & VMMDEV_MOUSEGUESTWANTSABS)
655
pThis->mouseCapabilities &= ~VMMDEV_MOUSEGUESTWANTSABS;
657
LogRel(("Guest disables mouse pointer integration\n"));
660
if (mouseStatus->mouseFeatures & VBOXGUEST_MOUSE_GUEST_NEEDS_HOST_CURSOR)
661
pThis->mouseCapabilities |= VMMDEV_MOUSEGUESTNEEDSHOSTCUR;
663
pThis->mouseCapabilities &= ~VMMDEV_MOUSEGUESTNEEDSHOSTCUR;
664
if (mouseStatus->mouseFeatures & VBOXGUEST_MOUSE_GUEST_USES_VMMDEV)
665
pThis->mouseCapabilities |= VMMDEV_MOUSEGUESTUSESVMMDEV;
667
pThis->mouseCapabilities &= ~VMMDEV_MOUSEGUESTUSESVMMDEV;
670
* Notify connector if something has changed
674
Log(("VMMDevReq_SetMouseStatus: capabilities changed (%x), informing connector\n", pThis->mouseCapabilities));
675
pThis->pDrv->pfnUpdateMouseCapabilities(pThis->pDrv, pThis->mouseCapabilities);
677
pRequestHeader->rc = VINF_SUCCESS;
684
* Set a new mouse pointer shape
686
case VMMDevReq_SetPointerShape:
688
if (pRequestHeader->size < sizeof(VMMDevReqMousePointer))
690
AssertMsg(pRequestHeader->size == 0x10028 && pRequestHeader->version == 10000, /* don't bitch about legacy!!! */
691
("VMMDev mouse shape structure has invalid size %d (%#x) version=%d!\n",
692
pRequestHeader->size, pRequestHeader->size, pRequestHeader->size, pRequestHeader->version));
693
pRequestHeader->rc = VERR_INVALID_PARAMETER;
697
VMMDevReqMousePointer *pointerShape = (VMMDevReqMousePointer*)pRequestHeader;
699
bool fVisible = (pointerShape->fFlags & VBOX_MOUSE_POINTER_VISIBLE) != 0;
700
bool fAlpha = (pointerShape->fFlags & VBOX_MOUSE_POINTER_ALPHA) != 0;
701
bool fShape = (pointerShape->fFlags & VBOX_MOUSE_POINTER_SHAPE) != 0;
703
Log(("VMMDevReq_SetPointerShape: visible: %d, alpha: %d, shape = %d, width: %d, height: %d\n",
704
fVisible, fAlpha, fShape, pointerShape->width, pointerShape->height));
706
if (pRequestHeader->size == sizeof(VMMDevReqMousePointer))
708
/* The guest did not provide the shape actually. */
712
/* forward call to driver */
715
pThis->pDrv->pfnUpdatePointerShape(pThis->pDrv,
718
pointerShape->xHot, pointerShape->yHot,
719
pointerShape->width, pointerShape->height,
720
pointerShape->pointerData);
724
pThis->pDrv->pfnUpdatePointerShape(pThis->pDrv,
731
pThis->fHostCursorRequested = fVisible;
732
pRequestHeader->rc = VINF_SUCCESS;
738
* Query the system time from the host
740
case VMMDevReq_GetHostTime:
742
if (pRequestHeader->size != sizeof(VMMDevReqHostTime))
744
AssertMsgFailed(("VMMDev host time structure has invalid size!\n"));
745
pRequestHeader->rc = VERR_INVALID_PARAMETER;
747
else if (RT_UNLIKELY(pThis->fGetHostTimeDisabled))
748
pRequestHeader->rc = VERR_NOT_SUPPORTED;
751
VMMDevReqHostTime *hostTimeReq = (VMMDevReqHostTime*)pRequestHeader;
753
hostTimeReq->time = RTTimeSpecGetMilli(PDMDevHlpUTCNow(pDevIns, &now));
754
pRequestHeader->rc = VINF_SUCCESS;
760
* Query information about the hypervisor
762
case VMMDevReq_GetHypervisorInfo:
764
if (pRequestHeader->size != sizeof(VMMDevReqHypervisorInfo))
766
AssertMsgFailed(("VMMDev hypervisor info structure has invalid size!\n"));
767
pRequestHeader->rc = VERR_INVALID_PARAMETER;
771
VMMDevReqHypervisorInfo *hypervisorInfo = (VMMDevReqHypervisorInfo*)pRequestHeader;
772
PVM pVM = PDMDevHlpGetVM(pDevIns);
773
pRequestHeader->rc = PGMR3MappingsSize(pVM, &hypervisorInfo->hypervisorSize);
779
* Set hypervisor information
781
case VMMDevReq_SetHypervisorInfo:
783
if (pRequestHeader->size != sizeof(VMMDevReqHypervisorInfo))
785
AssertMsgFailed(("VMMDev hypervisor info structure has invalid size!\n"));
786
pRequestHeader->rc = VERR_INVALID_PARAMETER;
790
VMMDevReqHypervisorInfo *hypervisorInfo = (VMMDevReqHypervisorInfo*)pRequestHeader;
791
PVM pVM = PDMDevHlpGetVM(pDevIns);
792
if (hypervisorInfo->hypervisorStart == 0)
793
pRequestHeader->rc = PGMR3MappingsUnfix(pVM);
796
/* only if the client has queried the size before! */
797
uint32_t mappingsSize;
798
pRequestHeader->rc = PGMR3MappingsSize(pVM, &mappingsSize);
799
if (RT_SUCCESS(pRequestHeader->rc) && hypervisorInfo->hypervisorSize == mappingsSize)
801
/* new reservation */
802
pRequestHeader->rc = PGMR3MappingsFix(pVM, hypervisorInfo->hypervisorStart,
803
hypervisorInfo->hypervisorSize);
804
LogRel(("Guest reported fixed hypervisor window at 0x%p (size = 0x%x, rc = %Rrc)\n",
805
(uintptr_t)hypervisorInfo->hypervisorStart,
806
hypervisorInfo->hypervisorSize,
807
pRequestHeader->rc));
814
case VMMDevReq_RegisterPatchMemory:
816
if (pRequestHeader->size != sizeof(VMMDevReqPatchMemory))
818
AssertMsgFailed(("VMMDevReq_RegisterPatchMemory structure has invalid size!\n"));
819
pRequestHeader->rc = VERR_INVALID_PARAMETER;
823
VMMDevReqPatchMemory *pPatchRequest = (VMMDevReqPatchMemory*)pRequestHeader;
825
pRequestHeader->rc = VMMR3RegisterPatchMemory(PDMDevHlpGetVM(pDevIns), pPatchRequest->pPatchMem, pPatchRequest->cbPatchMem);
830
case VMMDevReq_DeregisterPatchMemory:
832
if (pRequestHeader->size != sizeof(VMMDevReqPatchMemory))
834
AssertMsgFailed(("VMMDevReq_DeregisterPatchMemory structure has invalid size!\n"));
835
pRequestHeader->rc = VERR_INVALID_PARAMETER;
839
VMMDevReqPatchMemory *pPatchRequest = (VMMDevReqPatchMemory*)pRequestHeader;
841
pRequestHeader->rc = VMMR3DeregisterPatchMemory(PDMDevHlpGetVM(pDevIns), pPatchRequest->pPatchMem, pPatchRequest->cbPatchMem);
847
* Set the system power status
849
case VMMDevReq_SetPowerStatus:
851
if (pRequestHeader->size != sizeof(VMMDevPowerStateRequest))
853
AssertMsgFailed(("VMMDev power state request structure has invalid size!\n"));
854
pRequestHeader->rc = VERR_INVALID_PARAMETER;
858
VMMDevPowerStateRequest *powerStateRequest = (VMMDevPowerStateRequest*)pRequestHeader;
859
switch(powerStateRequest->powerState)
861
case VMMDevPowerState_Pause:
863
LogRel(("Guest requests the VM to be suspended (paused)\n"));
864
pRequestHeader->rc = rcRet = PDMDevHlpVMSuspend(pDevIns);
868
case VMMDevPowerState_PowerOff:
870
LogRel(("Guest requests the VM to be turned off\n"));
871
pRequestHeader->rc = rcRet = PDMDevHlpVMPowerOff(pDevIns);
875
case VMMDevPowerState_SaveState:
877
/** @todo no API for that yet */
878
pRequestHeader->rc = VERR_NOT_IMPLEMENTED;
883
AssertMsgFailed(("VMMDev invalid power state request: %d\n", powerStateRequest->powerState));
884
pRequestHeader->rc = VERR_INVALID_PARAMETER;
892
* Get display change request
894
case VMMDevReq_GetDisplayChangeRequest:
896
if (pRequestHeader->size != sizeof(VMMDevDisplayChangeRequest))
898
/* Assert only if the size also not equal to a previous version size to prevent
899
* assertion with old additions.
901
AssertMsg(pRequestHeader->size == sizeof(VMMDevDisplayChangeRequest) - sizeof (uint32_t),
902
("VMMDev display change request structure has invalid size!\n"));
903
pRequestHeader->rc = VERR_INVALID_PARAMETER;
907
VMMDevDisplayChangeRequest *displayChangeRequest = (VMMDevDisplayChangeRequest*)pRequestHeader;
909
if (displayChangeRequest->eventAck == VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST)
911
/* Remember which resolution the client has queried, subsequent reads
912
* will return the same values. */
913
pThis->lastReadDisplayChangeRequest = pThis->displayChangeRequest;
914
pThis->fGuestSentChangeEventAck = true;
917
if (pThis->fGuestSentChangeEventAck)
919
displayChangeRequest->xres = pThis->lastReadDisplayChangeRequest.xres;
920
displayChangeRequest->yres = pThis->lastReadDisplayChangeRequest.yres;
921
displayChangeRequest->bpp = pThis->lastReadDisplayChangeRequest.bpp;
925
displayChangeRequest->xres = pThis->displayChangeRequest.xres;
926
displayChangeRequest->yres = pThis->displayChangeRequest.yres;
927
displayChangeRequest->bpp = pThis->displayChangeRequest.bpp;
929
Log(("VMMDev: returning display change request xres = %d, yres = %d, bpp = %d\n",
930
displayChangeRequest->xres, displayChangeRequest->yres, displayChangeRequest->bpp));
932
pRequestHeader->rc = VINF_SUCCESS;
937
case VMMDevReq_GetDisplayChangeRequest2:
939
if (pRequestHeader->size != sizeof(VMMDevDisplayChangeRequest2))
941
pRequestHeader->rc = VERR_INVALID_PARAMETER;
945
VMMDevDisplayChangeRequest2 *displayChangeRequest = (VMMDevDisplayChangeRequest2*)pRequestHeader;
947
if (displayChangeRequest->eventAck == VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST)
949
/* Remember which resolution the client has queried, subsequent reads
950
* will return the same values. */
951
pThis->lastReadDisplayChangeRequest = pThis->displayChangeRequest;
952
pThis->fGuestSentChangeEventAck = true;
955
if (pThis->fGuestSentChangeEventAck)
957
displayChangeRequest->xres = pThis->lastReadDisplayChangeRequest.xres;
958
displayChangeRequest->yres = pThis->lastReadDisplayChangeRequest.yres;
959
displayChangeRequest->bpp = pThis->lastReadDisplayChangeRequest.bpp;
960
displayChangeRequest->display = pThis->lastReadDisplayChangeRequest.display;
964
displayChangeRequest->xres = pThis->displayChangeRequest.xres;
965
displayChangeRequest->yres = pThis->displayChangeRequest.yres;
966
displayChangeRequest->bpp = pThis->displayChangeRequest.bpp;
967
displayChangeRequest->display = pThis->displayChangeRequest.display;
969
Log(("VMMDev: returning display change request xres = %d, yres = %d, bpp = %d at %d\n",
970
displayChangeRequest->xres, displayChangeRequest->yres, displayChangeRequest->bpp, displayChangeRequest->display));
972
pRequestHeader->rc = VINF_SUCCESS;
978
* Query whether the given video mode is supported
980
case VMMDevReq_VideoModeSupported:
982
if (pRequestHeader->size != sizeof(VMMDevVideoModeSupportedRequest))
984
AssertMsgFailed(("VMMDev video mode supported request structure has invalid size!\n"));
985
pRequestHeader->rc = VERR_INVALID_PARAMETER;
989
VMMDevVideoModeSupportedRequest *videoModeSupportedRequest = (VMMDevVideoModeSupportedRequest*)pRequestHeader;
990
/* forward the call */
991
pRequestHeader->rc = pThis->pDrv->pfnVideoModeSupported(pThis->pDrv,
992
videoModeSupportedRequest->width,
993
videoModeSupportedRequest->height,
994
videoModeSupportedRequest->bpp,
995
&videoModeSupportedRequest->fSupported);
1001
* Query the height reduction in pixels
1003
case VMMDevReq_GetHeightReduction:
1005
if (pRequestHeader->size != sizeof(VMMDevGetHeightReductionRequest))
1007
AssertMsgFailed(("VMMDev height reduction request structure has invalid size!\n"));
1008
pRequestHeader->rc = VERR_INVALID_PARAMETER;
1012
VMMDevGetHeightReductionRequest *heightReductionRequest = (VMMDevGetHeightReductionRequest*)pRequestHeader;
1013
/* forward the call */
1014
pRequestHeader->rc = pThis->pDrv->pfnGetHeightReduction(pThis->pDrv,
1015
&heightReductionRequest->heightReduction);
1021
* Acknowledge VMMDev events
1023
case VMMDevReq_AcknowledgeEvents:
1025
if (pRequestHeader->size != sizeof(VMMDevEvents))
1027
AssertMsgFailed(("VMMDevReq_AcknowledgeEvents structure has invalid size!\n"));
1028
pRequestHeader->rc = VERR_INVALID_PARAMETER;
1032
if (VBOX_GUEST_ADDITIONS_VERSION_1_03 (pThis))
1034
vmmdevSetIRQ_Legacy_EMT (pThis);
1038
VMMDevEvents *pAckRequest;
1040
if (pThis->fNewGuestFilterMask)
1042
pThis->fNewGuestFilterMask = false;
1043
pThis->u32GuestFilterMask = pThis->u32NewGuestFilterMask;
1046
pAckRequest = (VMMDevEvents *)pRequestHeader;
1047
pAckRequest->events =
1048
pThis->u32HostEventFlags & pThis->u32GuestFilterMask;
1050
pThis->u32HostEventFlags &= ~pThis->u32GuestFilterMask;
1051
pThis->pVMMDevRAMR3->V.V1_04.fHaveEvents = false;
1052
PDMDevHlpPCISetIrqNoWait (pThis->pDevIns, 0, 0);
1054
pRequestHeader->rc = VINF_SUCCESS;
1060
* Change guest filter mask
1062
case VMMDevReq_CtlGuestFilterMask:
1064
if (pRequestHeader->size != sizeof(VMMDevCtlGuestFilterMask))
1066
AssertMsgFailed(("VMMDevReq_AcknowledgeEvents structure has invalid size!\n"));
1067
pRequestHeader->rc = VERR_INVALID_PARAMETER;
1071
VMMDevCtlGuestFilterMask *pCtlMaskRequest;
1073
pCtlMaskRequest = (VMMDevCtlGuestFilterMask *)pRequestHeader;
1074
/* The HGCM events are enabled by the VMMDev device automatically when any
1075
* HGCM command is issued. The guest then can not disable these events.
1077
vmmdevCtlGuestFilterMask_EMT (pThis,
1078
pCtlMaskRequest->u32OrMask,
1079
pCtlMaskRequest->u32NotMask & ~VMMDEV_EVENT_HGCM);
1080
pRequestHeader->rc = VINF_SUCCESS;
1086
#ifdef VBOX_WITH_HGCM
1088
* Process HGCM request
1090
case VMMDevReq_HGCMConnect:
1092
if (pRequestHeader->size < sizeof(VMMDevHGCMConnect))
1094
AssertMsgFailed(("VMMDevReq_HGCMConnect structure has invalid size!\n"));
1095
pRequestHeader->rc = VERR_INVALID_PARAMETER;
1097
else if (!pThis->pHGCMDrv)
1099
Log(("VMMDevReq_HGCMConnect HGCM Connector is NULL!\n"));
1100
pRequestHeader->rc = VERR_NOT_SUPPORTED;
1104
VMMDevHGCMConnect *pHGCMConnect = (VMMDevHGCMConnect *)pRequestHeader;
1106
Log(("VMMDevReq_HGCMConnect\n"));
1108
pRequestHeader->rc = vmmdevHGCMConnect (pThis, pHGCMConnect, (RTGCPHYS)u32);
1113
case VMMDevReq_HGCMDisconnect:
1115
if (pRequestHeader->size < sizeof(VMMDevHGCMDisconnect))
1117
AssertMsgFailed(("VMMDevReq_HGCMDisconnect structure has invalid size!\n"));
1118
pRequestHeader->rc = VERR_INVALID_PARAMETER;
1120
else if (!pThis->pHGCMDrv)
1122
Log(("VMMDevReq_HGCMDisconnect HGCM Connector is NULL!\n"));
1123
pRequestHeader->rc = VERR_NOT_SUPPORTED;
1127
VMMDevHGCMDisconnect *pHGCMDisconnect = (VMMDevHGCMDisconnect *)pRequestHeader;
1129
Log(("VMMDevReq_VMMDevHGCMDisconnect\n"));
1130
pRequestHeader->rc = vmmdevHGCMDisconnect (pThis, pHGCMDisconnect, (RTGCPHYS)u32);
1135
#ifdef VBOX_WITH_64_BITS_GUESTS
1136
case VMMDevReq_HGCMCall32:
1137
case VMMDevReq_HGCMCall64:
1139
case VMMDevReq_HGCMCall:
1140
#endif /* VBOX_WITH_64_BITS_GUESTS */
1142
if (pRequestHeader->size < sizeof(VMMDevHGCMCall))
1144
AssertMsgFailed(("VMMDevReq_HGCMCall structure has invalid size!\n"));
1145
pRequestHeader->rc = VERR_INVALID_PARAMETER;
1147
else if (!pThis->pHGCMDrv)
1149
Log(("VMMDevReq_HGCMCall HGCM Connector is NULL!\n"));
1150
pRequestHeader->rc = VERR_NOT_SUPPORTED;
1154
VMMDevHGCMCall *pHGCMCall = (VMMDevHGCMCall *)pRequestHeader;
1156
Log2(("VMMDevReq_HGCMCall: sizeof (VMMDevHGCMRequest) = %04X\n", sizeof (VMMDevHGCMCall)));
1157
Log2(("%.*Rhxd\n", pRequestHeader->size, pRequestHeader));
1159
#ifdef VBOX_WITH_64_BITS_GUESTS
1160
bool f64Bits = (pRequestHeader->requestType == VMMDevReq_HGCMCall64);
1162
bool f64Bits = false;
1163
#endif /* VBOX_WITH_64_BITS_GUESTS */
1165
pRequestHeader->rc = vmmdevHGCMCall (pThis, pHGCMCall, (RTGCPHYS)u32, f64Bits);
1169
#endif /* VBOX_WITH_HGCM */
1171
case VMMDevReq_HGCMCancel:
1173
if (pRequestHeader->size < sizeof(VMMDevHGCMCancel))
1175
AssertMsgFailed(("VMMDevReq_HGCMCancel structure has invalid size!\n"));
1176
pRequestHeader->rc = VERR_INVALID_PARAMETER;
1178
else if (!pThis->pHGCMDrv)
1180
Log(("VMMDevReq_HGCMCancel HGCM Connector is NULL!\n"));
1181
pRequestHeader->rc = VERR_NOT_SUPPORTED;
1185
VMMDevHGCMCancel *pHGCMCancel = (VMMDevHGCMCancel *)pRequestHeader;
1187
Log(("VMMDevReq_VMMDevHGCMCancel\n"));
1188
pRequestHeader->rc = vmmdevHGCMCancel (pThis, pHGCMCancel, (RTGCPHYS)u32);
1193
case VMMDevReq_VideoAccelEnable:
1195
if (pRequestHeader->size < sizeof(VMMDevVideoAccelEnable))
1197
Log(("VMMDevReq_VideoAccelEnable request size too small!!!\n"));
1198
pRequestHeader->rc = VERR_INVALID_PARAMETER;
1200
else if (!pThis->pDrv)
1202
Log(("VMMDevReq_VideoAccelEnable Connector is NULL!!!\n"));
1203
pRequestHeader->rc = VERR_NOT_SUPPORTED;
1207
VMMDevVideoAccelEnable *ptr = (VMMDevVideoAccelEnable *)pRequestHeader;
1209
if (ptr->cbRingBuffer != VBVA_RING_BUFFER_SIZE)
1211
/* The guest driver seems compiled with another headers. */
1212
Log(("VMMDevReq_VideoAccelEnable guest ring buffer size %d, should be %d!!!\n", ptr->cbRingBuffer, VBVA_RING_BUFFER_SIZE));
1213
pRequestHeader->rc = VERR_INVALID_PARAMETER;
1217
/* The request is correct. */
1218
ptr->fu32Status |= VBVA_F_STATUS_ACCEPTED;
1220
LogFlow(("VMMDevReq_VideoAccelEnable ptr->u32Enable = %d\n", ptr->u32Enable));
1222
pRequestHeader->rc = ptr->u32Enable?
1223
pThis->pDrv->pfnVideoAccelEnable (pThis->pDrv, true, &pThis->pVMMDevRAMR3->vbvaMemory):
1224
pThis->pDrv->pfnVideoAccelEnable (pThis->pDrv, false, NULL);
1227
&& RT_SUCCESS (pRequestHeader->rc))
1229
ptr->fu32Status |= VBVA_F_STATUS_ENABLED;
1231
/* Remember that guest successfully enabled acceleration.
1232
* We need to reestablish it on restoring the VM from saved state.
1234
pThis->u32VideoAccelEnabled = 1;
1238
/* The acceleration was not enabled. Remember that. */
1239
pThis->u32VideoAccelEnabled = 0;
1246
case VMMDevReq_VideoAccelFlush:
1248
if (pRequestHeader->size < sizeof(VMMDevVideoAccelFlush))
1250
AssertMsgFailed(("VMMDevReq_VideoAccelFlush request size too small.\n"));
1251
pRequestHeader->rc = VERR_INVALID_PARAMETER;
1253
else if (!pThis->pDrv)
1255
Log(("VMMDevReq_VideoAccelFlush Connector is NULL!\n"));
1256
pRequestHeader->rc = VERR_NOT_SUPPORTED;
1260
pThis->pDrv->pfnVideoAccelFlush (pThis->pDrv);
1262
pRequestHeader->rc = VINF_SUCCESS;
1267
case VMMDevReq_VideoSetVisibleRegion:
1269
if (pRequestHeader->size < sizeof(VMMDevVideoSetVisibleRegion))
1271
Log(("VMMDevReq_VideoSetVisibleRegion request size too small!!!\n"));
1272
pRequestHeader->rc = VERR_INVALID_PARAMETER;
1274
else if (!pThis->pDrv)
1276
Log(("VMMDevReq_VideoSetVisibleRegion Connector is NULL!!!\n"));
1277
pRequestHeader->rc = VERR_NOT_SUPPORTED;
1281
VMMDevVideoSetVisibleRegion *ptr = (VMMDevVideoSetVisibleRegion *)pRequestHeader;
1285
Log(("VMMDevReq_VideoSetVisibleRegion no rectangles!!!\n"));
1286
pRequestHeader->rc = VERR_INVALID_PARAMETER;
1289
if (pRequestHeader->size != sizeof(VMMDevVideoSetVisibleRegion) + (ptr->cRect-1)*sizeof(RTRECT))
1291
Log(("VMMDevReq_VideoSetVisibleRegion request size too small!!!\n"));
1292
pRequestHeader->rc = VERR_INVALID_PARAMETER;
1296
Log(("VMMDevReq_VideoSetVisibleRegion %d rectangles\n", ptr->cRect));
1297
/* forward the call */
1298
pRequestHeader->rc = pThis->pDrv->pfnSetVisibleRegion(pThis->pDrv, ptr->cRect, &ptr->Rect);
1304
case VMMDevReq_GetSeamlessChangeRequest:
1306
if (pRequestHeader->size != sizeof(VMMDevSeamlessChangeRequest))
1308
pRequestHeader->rc = VERR_INVALID_PARAMETER;
1312
VMMDevSeamlessChangeRequest *seamlessChangeRequest = (VMMDevSeamlessChangeRequest*)pRequestHeader;
1313
/* just pass on the information */
1314
Log(("VMMDev: returning seamless change request mode=%d\n", pThis->fSeamlessEnabled));
1315
if (pThis->fSeamlessEnabled)
1316
seamlessChangeRequest->mode = VMMDev_Seamless_Visible_Region;
1318
seamlessChangeRequest->mode = VMMDev_Seamless_Disabled;
1320
if (seamlessChangeRequest->eventAck == VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST)
1322
/* Remember which mode the client has queried. */
1323
pThis->fLastSeamlessEnabled = pThis->fSeamlessEnabled;
1326
pRequestHeader->rc = VINF_SUCCESS;
1331
case VMMDevReq_GetVRDPChangeRequest:
1333
if (pRequestHeader->size != sizeof(VMMDevVRDPChangeRequest))
1335
pRequestHeader->rc = VERR_INVALID_PARAMETER;
1339
VMMDevVRDPChangeRequest *vrdpChangeRequest = (VMMDevVRDPChangeRequest*)pRequestHeader;
1340
/* just pass on the information */
1341
Log(("VMMDev: returning VRDP status %d level %d\n", pThis->fVRDPEnabled, pThis->u32VRDPExperienceLevel));
1343
vrdpChangeRequest->u8VRDPActive = pThis->fVRDPEnabled;
1344
vrdpChangeRequest->u32VRDPExperienceLevel = pThis->u32VRDPExperienceLevel;
1346
pRequestHeader->rc = VINF_SUCCESS;
1351
case VMMDevReq_GetMemBalloonChangeRequest:
1353
Log(("VMMDevReq_GetMemBalloonChangeRequest\n"));
1354
if (pRequestHeader->size != sizeof(VMMDevGetMemBalloonChangeRequest))
1357
pRequestHeader->rc = VERR_INVALID_PARAMETER;
1361
VMMDevGetMemBalloonChangeRequest *memBalloonChangeRequest = (VMMDevGetMemBalloonChangeRequest*)pRequestHeader;
1362
/* just pass on the information */
1363
Log(("VMMDev: returning memory balloon size =%d\n", pThis->u32MemoryBalloonSize));
1364
memBalloonChangeRequest->u32BalloonSize = pThis->u32MemoryBalloonSize;
1365
memBalloonChangeRequest->u32PhysMemSize = pThis->cbGuestRAM / (uint64_t)_1M;
1367
if (memBalloonChangeRequest->eventAck == VMMDEV_EVENT_BALLOON_CHANGE_REQUEST)
1369
/* Remember which mode the client has queried. */
1370
pThis->u32LastMemoryBalloonSize = pThis->u32MemoryBalloonSize;
1373
pRequestHeader->rc = VINF_SUCCESS;
1378
case VMMDevReq_ChangeMemBalloon:
1380
VMMDevChangeMemBalloon *memBalloonChange = (VMMDevChangeMemBalloon*)pRequestHeader;
1382
Log(("VMMDevReq_ChangeMemBalloon\n"));
1383
if ( pRequestHeader->size < sizeof(VMMDevChangeMemBalloon)
1384
|| memBalloonChange->cPages != VMMDEV_MEMORY_BALLOON_CHUNK_PAGES
1385
|| pRequestHeader->size != (uint32_t)RT_OFFSETOF(VMMDevChangeMemBalloon, aPhysPage[memBalloonChange->cPages]))
1388
pRequestHeader->rc = VERR_INVALID_PARAMETER;
1392
pRequestHeader->rc = pThis->pDrv->pfnChangeMemoryBalloon(pThis->pDrv, !!memBalloonChange->fInflate, memBalloonChange->cPages, memBalloonChange->aPhysPage);
1397
case VMMDevReq_GetStatisticsChangeRequest:
1399
Log(("VMMDevReq_GetStatisticsChangeRequest\n"));
1400
if (pRequestHeader->size != sizeof(VMMDevGetStatisticsChangeRequest))
1403
pRequestHeader->rc = VERR_INVALID_PARAMETER;
1407
VMMDevGetStatisticsChangeRequest *statIntervalChangeRequest = (VMMDevGetStatisticsChangeRequest*)pRequestHeader;
1408
/* just pass on the information */
1409
Log(("VMMDev: returning statistics interval %d seconds\n", pThis->u32StatIntervalSize));
1410
statIntervalChangeRequest->u32StatInterval = pThis->u32StatIntervalSize;
1412
if (statIntervalChangeRequest->eventAck == VMMDEV_EVENT_STATISTICS_INTERVAL_CHANGE_REQUEST)
1414
/* Remember which mode the client has queried. */
1415
pThis->u32LastStatIntervalSize= pThis->u32StatIntervalSize;
1418
pRequestHeader->rc = VINF_SUCCESS;
1423
case VMMDevReq_ReportGuestStats:
1425
Log(("VMMDevReq_ReportGuestStats\n"));
1426
if (pRequestHeader->size != sizeof(VMMDevReportGuestStats))
1428
pRequestHeader->rc = VERR_INVALID_PARAMETER;
1432
VMMDevReportGuestStats *stats = (VMMDevReportGuestStats*)pRequestHeader;
1435
VBoxGuestStatistics *pGuestStats = &stats->guestStats;
1437
Log(("Current statistics:\n"));
1438
if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_CPU_LOAD_IDLE)
1439
Log(("CPU%d: CPU Load Idle %-3d%%\n", pGuestStats->u32CpuId, pGuestStats->u32CpuLoad_Idle));
1441
if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_CPU_LOAD_KERNEL)
1442
Log(("CPU%d: CPU Load Kernel %-3d%%\n", pGuestStats->u32CpuId, pGuestStats->u32CpuLoad_Kernel));
1444
if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_CPU_LOAD_USER)
1445
Log(("CPU%d: CPU Load User %-3d%%\n", pGuestStats->u32CpuId, pGuestStats->u32CpuLoad_User));
1447
if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_THREADS)
1448
Log(("CPU%d: Thread %d\n", pGuestStats->u32CpuId, pGuestStats->u32Threads));
1450
if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_PROCESSES)
1451
Log(("CPU%d: Processes %d\n", pGuestStats->u32CpuId, pGuestStats->u32Processes));
1453
if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_HANDLES)
1454
Log(("CPU%d: Handles %d\n", pGuestStats->u32CpuId, pGuestStats->u32Handles));
1456
if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_MEMORY_LOAD)
1457
Log(("CPU%d: Memory Load %d%%\n", pGuestStats->u32CpuId, pGuestStats->u32MemoryLoad));
1459
/* Note that reported values are in pages; upper layers expect them in megabytes */
1460
Assert(pGuestStats->u32PageSize == 4096);
1461
if (pGuestStats->u32PageSize != 4096)
1462
pGuestStats->u32PageSize = 4096;
1464
if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_PHYS_MEM_TOTAL)
1465
Log(("CPU%d: Total physical memory %-4d MB\n", pGuestStats->u32CpuId, (pGuestStats->u32PhysMemTotal + (_1M/pGuestStats->u32PageSize)-1)/ (_1M/pGuestStats->u32PageSize)));
1467
if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_PHYS_MEM_AVAIL)
1468
Log(("CPU%d: Free physical memory %-4d MB\n", pGuestStats->u32CpuId, pGuestStats->u32PhysMemAvail / (_1M/pGuestStats->u32PageSize)));
1470
if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_PHYS_MEM_BALLOON)
1471
Log(("CPU%d: Memory balloon size %-4d MB\n", pGuestStats->u32CpuId, pGuestStats->u32PhysMemBalloon / (_1M/pGuestStats->u32PageSize)));
1473
if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_MEM_COMMIT_TOTAL)
1474
Log(("CPU%d: Committed memory %-4d MB\n", pGuestStats->u32CpuId, pGuestStats->u32MemCommitTotal / (_1M/pGuestStats->u32PageSize)));
1476
if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_MEM_KERNEL_TOTAL)
1477
Log(("CPU%d: Total kernel memory %-4d MB\n", pGuestStats->u32CpuId, pGuestStats->u32MemKernelTotal / (_1M/pGuestStats->u32PageSize)));
1479
if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_MEM_KERNEL_PAGED)
1480
Log(("CPU%d: Paged kernel memory %-4d MB\n", pGuestStats->u32CpuId, pGuestStats->u32MemKernelPaged / (_1M/pGuestStats->u32PageSize)));
1482
if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_MEM_KERNEL_NONPAGED)
1483
Log(("CPU%d: Nonpaged kernel memory %-4d MB\n", pGuestStats->u32CpuId, pGuestStats->u32MemKernelNonPaged / (_1M/pGuestStats->u32PageSize)));
1485
if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_MEM_SYSTEM_CACHE)
1486
Log(("CPU%d: System cache size %-4d MB\n", pGuestStats->u32CpuId, pGuestStats->u32MemSystemCache / (_1M/pGuestStats->u32PageSize)));
1488
if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_PAGE_FILE_SIZE)
1489
Log(("CPU%d: Page file size %-4d MB\n", pGuestStats->u32CpuId, pGuestStats->u32PageFileSize / (_1M/pGuestStats->u32PageSize)));
1490
Log(("Statistics end *******************\n"));
1493
/* forward the call */
1494
pRequestHeader->rc = pThis->pDrv->pfnReportStatistics(pThis->pDrv, &stats->guestStats);
1499
case VMMDevReq_QueryCredentials:
1501
if (pRequestHeader->size != sizeof(VMMDevCredentials))
1503
AssertMsgFailed(("VMMDevReq_QueryCredentials request size too small.\n"));
1504
pRequestHeader->rc = VERR_INVALID_PARAMETER;
1508
VMMDevCredentials *credentials = (VMMDevCredentials*)pRequestHeader;
1510
/* let's start by nulling out the data */
1511
memset(credentials->szUserName, '\0', VMMDEV_CREDENTIALS_STRLEN);
1512
memset(credentials->szPassword, '\0', VMMDEV_CREDENTIALS_STRLEN);
1513
memset(credentials->szDomain, '\0', VMMDEV_CREDENTIALS_STRLEN);
1515
/* should we return whether we got credentials for a logon? */
1516
if (credentials->u32Flags & VMMDEV_CREDENTIALS_QUERYPRESENCE)
1518
if ( pThis->credentialsLogon.szUserName[0]
1519
|| pThis->credentialsLogon.szPassword[0]
1520
|| pThis->credentialsLogon.szDomain[0])
1522
credentials->u32Flags |= VMMDEV_CREDENTIALS_PRESENT;
1526
credentials->u32Flags &= ~VMMDEV_CREDENTIALS_PRESENT;
1530
/* does the guest want to read logon credentials? */
1531
if (credentials->u32Flags & VMMDEV_CREDENTIALS_READ)
1533
if (pThis->credentialsLogon.szUserName[0])
1534
strcpy(credentials->szUserName, pThis->credentialsLogon.szUserName);
1535
if (pThis->credentialsLogon.szPassword[0])
1536
strcpy(credentials->szPassword, pThis->credentialsLogon.szPassword);
1537
if (pThis->credentialsLogon.szDomain[0])
1538
strcpy(credentials->szDomain, pThis->credentialsLogon.szDomain);
1539
if (!pThis->credentialsLogon.fAllowInteractiveLogon)
1540
credentials->u32Flags |= VMMDEV_CREDENTIALS_NOLOCALLOGON;
1542
credentials->u32Flags &= ~VMMDEV_CREDENTIALS_NOLOCALLOGON;
1545
if (!pThis->fKeepCredentials)
1547
/* does the caller want us to destroy the logon credentials? */
1548
if (credentials->u32Flags & VMMDEV_CREDENTIALS_CLEAR)
1550
memset(pThis->credentialsLogon.szUserName, '\0', VMMDEV_CREDENTIALS_STRLEN);
1551
memset(pThis->credentialsLogon.szPassword, '\0', VMMDEV_CREDENTIALS_STRLEN);
1552
memset(pThis->credentialsLogon.szDomain, '\0', VMMDEV_CREDENTIALS_STRLEN);
1556
/* does the guest want to read credentials for verification? */
1557
if (credentials->u32Flags & VMMDEV_CREDENTIALS_READJUDGE)
1559
if (pThis->credentialsJudge.szUserName[0])
1560
strcpy(credentials->szUserName, pThis->credentialsJudge.szUserName);
1561
if (pThis->credentialsJudge.szPassword[0])
1562
strcpy(credentials->szPassword, pThis->credentialsJudge.szPassword);
1563
if (pThis->credentialsJudge.szDomain[0])
1564
strcpy(credentials->szDomain, pThis->credentialsJudge.szDomain);
1567
/* does the caller want us to destroy the judgement credentials? */
1568
if (credentials->u32Flags & VMMDEV_CREDENTIALS_CLEARJUDGE)
1570
memset(pThis->credentialsJudge.szUserName, '\0', VMMDEV_CREDENTIALS_STRLEN);
1571
memset(pThis->credentialsJudge.szPassword, '\0', VMMDEV_CREDENTIALS_STRLEN);
1572
memset(pThis->credentialsJudge.szDomain, '\0', VMMDEV_CREDENTIALS_STRLEN);
1575
pRequestHeader->rc = VINF_SUCCESS;
1580
case VMMDevReq_ReportCredentialsJudgement:
1582
if (pRequestHeader->size != sizeof(VMMDevCredentials))
1584
AssertMsgFailed(("VMMDevReq_ReportCredentialsJudgement request size too small.\n"));
1585
pRequestHeader->rc = VERR_INVALID_PARAMETER;
1589
VMMDevCredentials *credentials = (VMMDevCredentials*)pRequestHeader;
1591
/* what does the guest think about the credentials? (note: the order is important here!) */
1592
if (credentials->u32Flags & VMMDEV_CREDENTIALS_JUDGE_DENY)
1594
pThis->pDrv->pfnSetCredentialsJudgementResult(pThis->pDrv, VMMDEV_CREDENTIALS_JUDGE_DENY);
1596
else if (credentials->u32Flags & VMMDEV_CREDENTIALS_JUDGE_NOJUDGEMENT)
1598
pThis->pDrv->pfnSetCredentialsJudgementResult(pThis->pDrv, VMMDEV_CREDENTIALS_JUDGE_NOJUDGEMENT);
1600
else if (credentials->u32Flags & VMMDEV_CREDENTIALS_JUDGE_OK)
1602
pThis->pDrv->pfnSetCredentialsJudgementResult(pThis->pDrv, VMMDEV_CREDENTIALS_JUDGE_OK);
1605
Log(("VMMDevReq_ReportCredentialsJudgement: invalid flags: %d!!!\n", credentials->u32Flags));
1607
pRequestHeader->rc = VINF_SUCCESS;
1613
case VMMDevReq_LogString:
1615
if (pRequestHeader->size < sizeof(VMMDevReqLogString))
1617
AssertMsgFailed(("VMMDevReq_LogString request size too small.\n"));
1618
pRequestHeader->rc = VERR_INVALID_PARAMETER;
1622
VMMDevReqLogString *pReqLogString = (VMMDevReqLogString*)pRequestHeader;
1624
#define LOG_GROUP LOG_GROUP_DEV_VMM_BACKDOOR
1625
// Log(("Guest Log: %s", pReqLogString->szString));
1626
Log(("DEBUG LOG: %s", pReqLogString->szString));
1629
#define LOG_GROUP LOG_GROUP_DEV_VMM
1630
pRequestHeader->rc = VINF_SUCCESS;
1637
pRequestHeader->rc = VERR_NOT_IMPLEMENTED;
1639
Log(("VMMDev unknown request type %d\n", pRequestHeader->requestType));
1646
/* Write the result back to guest memory */
1649
PDMDevHlpPhysWrite(pDevIns, (RTGCPHYS)u32, pRequestHeader, pRequestHeader->size);
1650
RTMemFree(pRequestHeader);
1654
/* early error case; write back header only */
1655
PDMDevHlpPhysWrite(pDevIns, (RTGCPHYS)u32, &requestHeader, sizeof(requestHeader));
1658
PDMCritSectLeave(&pThis->CritSect);
1663
* Callback function for mapping an PCI I/O region.
1665
* @return VBox status code.
1666
* @param pPciDev Pointer to PCI device. Use pPciDev->pDevIns to get the device instance.
1667
* @param iRegion The region number.
1668
* @param GCPhysAddress Physical address of the region. If iType is PCI_ADDRESS_SPACE_IO, this is an
1669
* I/O port, else it's a physical address.
1670
* This address is *NOT* relative to pci_mem_base like earlier!
1671
* @param enmType One of the PCI_ADDRESS_SPACE_* values.
1673
static DECLCALLBACK(int) vmmdevIORAMRegionMap(PPCIDEVICE pPciDev, /*unsigned*/ int iRegion, RTGCPHYS GCPhysAddress, uint32_t cb, PCIADDRESSSPACE enmType)
1675
LogFlow(("vmmdevR3IORAMRegionMap: iRegion=%d GCPhysAddress=%RGp cb=%#x enmType=%d\n", iRegion, GCPhysAddress, cb, enmType));
1676
VMMDevState *pThis = PCIDEV_2_VMMDEVSTATE(pPciDev);
1681
AssertReturn(enmType == PCI_ADDRESS_SPACE_MEM, VERR_INTERNAL_ERROR);
1682
Assert(pThis->pVMMDevRAMR3 != NULL);
1683
if (GCPhysAddress != NIL_RTGCPHYS)
1686
* Map the MMIO2 memory.
1688
pThis->GCPhysVMMDevRAM = GCPhysAddress;
1689
Assert(pThis->GCPhysVMMDevRAM == GCPhysAddress);
1690
rc = PDMDevHlpMMIO2Map(pPciDev->pDevIns, iRegion, GCPhysAddress);
1695
* It is about to be unmapped, just clean up.
1697
pThis->GCPhysVMMDevRAM = NIL_RTGCPHYS32;
1701
else if (iRegion == 2)
1703
AssertReturn(enmType == PCI_ADDRESS_SPACE_MEM_PREFETCH, VERR_INTERNAL_ERROR);
1704
Assert(pThis->pVMMDevHeapR3 != NULL);
1705
if (GCPhysAddress != NIL_RTGCPHYS)
1708
* Map the MMIO2 memory.
1710
pThis->GCPhysVMMDevHeap = GCPhysAddress;
1711
Assert(pThis->GCPhysVMMDevHeap == GCPhysAddress);
1712
rc = PDMDevHlpMMIO2Map(pPciDev->pDevIns, iRegion, GCPhysAddress);
1714
rc = PDMDevHlpRegisterVMMDevHeap(pPciDev->pDevIns, GCPhysAddress, pThis->pVMMDevHeapR3, VMMDEV_HEAP_SIZE);
1719
* It is about to be unmapped, just clean up.
1721
PDMDevHlpUnregisterVMMDevHeap(pPciDev->pDevIns, pThis->GCPhysVMMDevHeap);
1722
pThis->GCPhysVMMDevHeap = NIL_RTGCPHYS32;
1728
AssertMsgFailed(("%d\n", iRegion));
1729
rc = VERR_INVALID_PARAMETER;
1737
* Callback function for mapping a PCI I/O region.
1739
* @return VBox status code.
1740
* @param pPciDev Pointer to PCI device. Use pPciDev->pDevIns to get the device instance.
1741
* @param iRegion The region number.
1742
* @param GCPhysAddress Physical address of the region. If iType is PCI_ADDRESS_SPACE_IO, this is an
1743
* I/O port, else it's a physical address.
1744
* This address is *NOT* relative to pci_mem_base like earlier!
1745
* @param enmType One of the PCI_ADDRESS_SPACE_* values.
1747
static DECLCALLBACK(int) vmmdevIOPortRegionMap(PPCIDEVICE pPciDev, /*unsigned*/ int iRegion, RTGCPHYS GCPhysAddress, uint32_t cb, PCIADDRESSSPACE enmType)
1749
VMMDevState *pThis = PCIDEV_2_VMMDEVSTATE(pPciDev);
1750
int rc = VINF_SUCCESS;
1752
Assert(enmType == PCI_ADDRESS_SPACE_IO);
1753
Assert(iRegion == 0);
1754
AssertMsg(RT_ALIGN(GCPhysAddress, 8) == GCPhysAddress, ("Expected 8 byte alignment. GCPhysAddress=%#x\n", GCPhysAddress));
1757
* Save the base port address to simplify Port offset calculations.
1759
pThis->PortBase = (RTIOPORT)GCPhysAddress;
1762
* Register our port IO handlers.
1764
rc = PDMDevHlpIOPortRegister(pPciDev->pDevIns,
1765
(RTIOPORT)GCPhysAddress + PORT_VMMDEV_REQUEST_OFFSET, 1,
1766
(void*)pThis, vmmdevRequestHandler,
1767
NULL, NULL, NULL, "VMMDev Request Handler");
1773
* Queries an interface to the driver.
1775
* @returns Pointer to interface.
1776
* @returns NULL if the interface was not supported by the driver.
1777
* @param pInterface Pointer to this interface structure.
1778
* @param enmInterface The requested interface identification.
1779
* @thread Any thread.
1781
static DECLCALLBACK(void *) vmmdevPortQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface)
1783
VMMDevState *pThis = (VMMDevState*)((uintptr_t)pInterface - RT_OFFSETOF(VMMDevState, Base));
1784
switch (enmInterface)
1786
case PDMINTERFACE_BASE:
1787
return &pThis->Base;
1788
case PDMINTERFACE_VMMDEV_PORT:
1789
return &pThis->Port;
1790
#ifdef VBOX_WITH_HGCM
1791
case PDMINTERFACE_HGCM_PORT:
1792
return &pThis->HGCMPort;
1794
case PDMINTERFACE_LED_PORTS:
1795
/* Currently only for shared folders */
1796
return &pThis->SharedFolders.ILeds;
1803
* Gets the pointer to the status LED of a unit.
1805
* @returns VBox status code.
1806
* @param pInterface Pointer to the interface structure containing the called function pointer.
1807
* @param iLUN The unit which status LED we desire.
1808
* @param ppLed Where to store the LED pointer.
1810
static DECLCALLBACK(int) vmmdevQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed)
1812
VMMDevState *pThis = (VMMDevState *)( (uintptr_t)pInterface - RT_OFFSETOF(VMMDevState, SharedFolders.ILeds) );
1813
if (iLUN == 0) /* LUN 0 is shared folders */
1815
*ppLed = &pThis->SharedFolders.Led;
1816
return VINF_SUCCESS;
1818
return VERR_PDM_LUN_NOT_FOUND;
1821
/* -=-=-=-=-=- IVMMDevPort -=-=-=-=-=- */
1823
/** Converts a VMMDev port interface pointer to a VMMDev state pointer. */
1824
#define IVMMDEVPORT_2_VMMDEVSTATE(pInterface) ( (VMMDevState*)((uintptr_t)pInterface - RT_OFFSETOF(VMMDevState, Port)) )
1828
* Return the current absolute mouse position in pixels
1830
* @returns VBox status code
1831
* @param pAbsX Pointer of result value, can be NULL
1832
* @param pAbsY Pointer of result value, can be NULL
1834
static DECLCALLBACK(int) vmmdevQueryAbsoluteMouse(PPDMIVMMDEVPORT pInterface, uint32_t *pAbsX, uint32_t *pAbsY)
1836
VMMDevState *pThis = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
1838
*pAbsX = pThis->mouseXAbs;
1840
*pAbsY = pThis->mouseYAbs;
1841
return VINF_SUCCESS;
1845
* Set the new absolute mouse position in pixels
1847
* @returns VBox status code
1848
* @param absX New absolute X position
1849
* @param absY New absolute Y position
1851
static DECLCALLBACK(int) vmmdevSetAbsoluteMouse(PPDMIVMMDEVPORT pInterface, uint32_t absX, uint32_t absY)
1853
VMMDevState *pThis = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
1854
if ((pThis->mouseXAbs == absX) && (pThis->mouseYAbs == absY))
1855
return VINF_SUCCESS;
1856
Log2(("vmmdevSetAbsoluteMouse: settings absolute position to x = %d, y = %d\n", absX, absY));
1857
pThis->mouseXAbs = absX;
1858
pThis->mouseYAbs = absY;
1859
VMMDevNotifyGuest (pThis, VMMDEV_EVENT_MOUSE_POSITION_CHANGED);
1860
return VINF_SUCCESS;
1864
* Return the current mouse capability flags
1866
* @returns VBox status code
1867
* @param pCapabilities Pointer of result value
1869
static DECLCALLBACK(int) vmmdevQueryMouseCapabilities(PPDMIVMMDEVPORT pInterface, uint32_t *pCapabilities)
1871
VMMDevState *pThis = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
1873
return VERR_INVALID_PARAMETER;
1874
*pCapabilities = pThis->mouseCapabilities;
1875
return VINF_SUCCESS;
1879
* Set the current mouse capability flag (host side)
1881
* @returns VBox status code
1882
* @param capabilities Capability mask
1884
static DECLCALLBACK(int) vmmdevSetMouseCapabilities(PPDMIVMMDEVPORT pInterface, uint32_t capabilities)
1886
VMMDevState *pThis = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
1888
bool bCapsChanged = ((capabilities & VMMDEV_MOUSEHOSTWANTSABS)
1889
!= (pThis->mouseCapabilities & VMMDEV_MOUSEHOSTWANTSABS));
1891
Log(("vmmdevSetMouseCapabilities: bCapsChanged %d\n", bCapsChanged));
1893
if (capabilities & VMMDEV_MOUSEHOSTCANNOTHWPOINTER)
1894
pThis->mouseCapabilities |= VMMDEV_MOUSEHOSTCANNOTHWPOINTER;
1896
pThis->mouseCapabilities &= ~VMMDEV_MOUSEHOSTCANNOTHWPOINTER;
1898
if (capabilities & VMMDEV_MOUSEHOSTWANTSABS)
1899
pThis->mouseCapabilities |= VMMDEV_MOUSEHOSTWANTSABS;
1901
pThis->mouseCapabilities &= ~VMMDEV_MOUSEHOSTWANTSABS;
1904
VMMDevNotifyGuest (pThis, VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED);
1906
return VINF_SUCCESS;
1910
static DECLCALLBACK(int) vmmdevRequestDisplayChange(PPDMIVMMDEVPORT pInterface, uint32_t xres, uint32_t yres, uint32_t bpp, uint32_t display)
1912
VMMDevState *pThis = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
1914
/* Verify that the new resolution is different and that guest does not yet know about it. */
1915
bool fSameResolution = (!xres || (pThis->lastReadDisplayChangeRequest.xres == xres)) &&
1916
(!yres || (pThis->lastReadDisplayChangeRequest.yres == yres)) &&
1917
(!bpp || (pThis->lastReadDisplayChangeRequest.bpp == bpp)) &&
1918
pThis->lastReadDisplayChangeRequest.display == display;
1920
if (!xres && !yres && !bpp)
1922
/* Special case of reset video mode. */
1923
fSameResolution = false;
1926
Log3(("vmmdevRequestDisplayChange: same=%d. new: xres=%d, yres=%d, bpp=%d, display=%d. old: xres=%d, yres=%d, bpp=%d, display=%d.\n",
1927
fSameResolution, xres, yres, bpp, display, pThis->lastReadDisplayChangeRequest.xres, pThis->lastReadDisplayChangeRequest.yres, pThis->lastReadDisplayChangeRequest.bpp, pThis->lastReadDisplayChangeRequest.display));
1929
if (!fSameResolution)
1931
LogRel(("VMMDev::SetVideoModeHint: got a video mode hint (%dx%dx%d) at %d\n",
1932
xres, yres, bpp, display));
1934
/* we could validate the information here but hey, the guest can do that as well! */
1935
pThis->displayChangeRequest.xres = xres;
1936
pThis->displayChangeRequest.yres = yres;
1937
pThis->displayChangeRequest.bpp = bpp;
1938
pThis->displayChangeRequest.display = display;
1940
/* IRQ so the guest knows what's going on */
1941
VMMDevNotifyGuest (pThis, VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST);
1944
return VINF_SUCCESS;
1947
static DECLCALLBACK(int) vmmdevRequestSeamlessChange(PPDMIVMMDEVPORT pInterface, bool fEnabled)
1949
VMMDevState *pThis = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
1951
/* Verify that the new resolution is different and that guest does not yet know about it. */
1952
bool fSameMode = (pThis->fLastSeamlessEnabled == fEnabled);
1954
Log(("vmmdevRequestSeamlessChange: same=%d. new=%d\n", fSameMode, fEnabled));
1958
/* we could validate the information here but hey, the guest can do that as well! */
1959
pThis->fSeamlessEnabled = fEnabled;
1961
/* IRQ so the guest knows what's going on */
1962
VMMDevNotifyGuest (pThis, VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST);
1965
return VINF_SUCCESS;
1968
static DECLCALLBACK(int) vmmdevSetMemoryBalloon(PPDMIVMMDEVPORT pInterface, uint32_t ulBalloonSize)
1970
VMMDevState *pThis = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
1972
/* Verify that the new resolution is different and that guest does not yet know about it. */
1973
bool fSame = (pThis->u32LastMemoryBalloonSize == ulBalloonSize);
1975
Log(("vmmdevSetMemoryBalloon: old=%d. new=%d\n", pThis->u32LastMemoryBalloonSize, ulBalloonSize));
1979
/* we could validate the information here but hey, the guest can do that as well! */
1980
pThis->u32MemoryBalloonSize = ulBalloonSize;
1982
/* IRQ so the guest knows what's going on */
1983
VMMDevNotifyGuest (pThis, VMMDEV_EVENT_BALLOON_CHANGE_REQUEST);
1986
return VINF_SUCCESS;
1989
static DECLCALLBACK(int) vmmdevVRDPChange(PPDMIVMMDEVPORT pInterface, bool fVRDPEnabled, uint32_t u32VRDPExperienceLevel)
1991
VMMDevState *pThis = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
1993
bool fSame = (pThis->fVRDPEnabled == fVRDPEnabled);
1995
Log(("vmmdevVRDPChange: old=%d. new=%d\n", pThis->fVRDPEnabled, fVRDPEnabled));
1999
pThis->fVRDPEnabled = fVRDPEnabled;
2000
pThis->u32VRDPExperienceLevel = u32VRDPExperienceLevel;
2002
VMMDevNotifyGuest (pThis, VMMDEV_EVENT_VRDP);
2005
return VINF_SUCCESS;
2008
static DECLCALLBACK(int) vmmdevSetStatisticsInterval(PPDMIVMMDEVPORT pInterface, uint32_t ulStatInterval)
2010
VMMDevState *pThis = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
2012
/* Verify that the new resolution is different and that guest does not yet know about it. */
2013
bool fSame = (pThis->u32LastStatIntervalSize == ulStatInterval);
2015
Log(("vmmdevSetStatisticsInterval: old=%d. new=%d\n", pThis->u32LastStatIntervalSize, ulStatInterval));
2019
/* we could validate the information here but hey, the guest can do that as well! */
2020
pThis->u32StatIntervalSize = ulStatInterval;
2022
/* IRQ so the guest knows what's going on */
2023
VMMDevNotifyGuest (pThis, VMMDEV_EVENT_STATISTICS_INTERVAL_CHANGE_REQUEST);
2026
return VINF_SUCCESS;
2030
static DECLCALLBACK(int) vmmdevSetCredentials(PPDMIVMMDEVPORT pInterface, const char *pszUsername,
2031
const char *pszPassword, const char *pszDomain,
2034
VMMDevState *pThis = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
2037
if (u32Flags & VMMDEV_SETCREDENTIALS_GUESTLOGON)
2039
/* memorize the data */
2040
strcpy(pThis->credentialsLogon.szUserName, pszUsername);
2041
strcpy(pThis->credentialsLogon.szPassword, pszPassword);
2042
strcpy(pThis->credentialsLogon.szDomain, pszDomain);
2043
pThis->credentialsLogon.fAllowInteractiveLogon = !(u32Flags & VMMDEV_SETCREDENTIALS_NOLOCALLOGON);
2045
/* credentials verification mode? */
2046
else if (u32Flags & VMMDEV_SETCREDENTIALS_JUDGE)
2048
/* memorize the data */
2049
strcpy(pThis->credentialsJudge.szUserName, pszUsername);
2050
strcpy(pThis->credentialsJudge.szPassword, pszPassword);
2051
strcpy(pThis->credentialsJudge.szDomain, pszDomain);
2053
VMMDevNotifyGuest (pThis, VMMDEV_EVENT_JUDGE_CREDENTIALS);
2056
return VERR_INVALID_PARAMETER;
2058
return VINF_SUCCESS;
2062
* Notification from the Display. Especially useful when
2063
* acceleration is disabled after a video mode change.
2065
* @param fEnable Current acceleration status.
2067
static DECLCALLBACK(void) vmmdevVBVAChange(PPDMIVMMDEVPORT pInterface, bool fEnabled)
2069
VMMDevState *pThis = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
2071
Log(("vmmdevVBVAChange: fEnabled = %d\n", fEnabled));
2075
pThis->u32VideoAccelEnabled = fEnabled;
2082
/* -=-=-=-=-=- IHGCMPort -=-=-=-=-=- */
2084
/** Converts a VMMDev port interface pointer to a VMMDev state pointer. */
2085
#define IHGCMPORT_2_VMMDEVSTATE(pInterface) ( (VMMDevState*)((uintptr_t)pInterface - RT_OFFSETOF(VMMDevState, HGCMPort)) )
2089
#define VMMDEV_SSM_VERSION 11
2092
* Saves a state of the VMM device.
2094
* @returns VBox status code.
2095
* @param pDevIns The device instance.
2096
* @param pSSMHandle The handle to save the state to.
2098
static DECLCALLBACK(int) vmmdevSaveState(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle)
2100
VMMDevState *pThis = PDMINS_2_DATA(pDevIns, VMMDevState*);
2101
SSMR3PutU32(pSSMHandle, pThis->hypervisorSize);
2102
SSMR3PutU32(pSSMHandle, pThis->mouseCapabilities);
2103
SSMR3PutU32(pSSMHandle, pThis->mouseXAbs);
2104
SSMR3PutU32(pSSMHandle, pThis->mouseYAbs);
2106
SSMR3PutBool(pSSMHandle, pThis->fNewGuestFilterMask);
2107
SSMR3PutU32(pSSMHandle, pThis->u32NewGuestFilterMask);
2108
SSMR3PutU32(pSSMHandle, pThis->u32GuestFilterMask);
2109
SSMR3PutU32(pSSMHandle, pThis->u32HostEventFlags);
2110
// here be dragons (probably)
2111
// SSMR3PutBool(pSSMHandle, pThis->pVMMDevRAMR3->V.V1_04.fHaveEvents);
2112
SSMR3PutMem(pSSMHandle, &pThis->pVMMDevRAMR3->V, sizeof (pThis->pVMMDevRAMR3->V));
2114
SSMR3PutMem(pSSMHandle, &pThis->guestInfo, sizeof (pThis->guestInfo));
2115
SSMR3PutU32(pSSMHandle, pThis->fu32AdditionsOk);
2116
SSMR3PutU32(pSSMHandle, pThis->u32VideoAccelEnabled);
2117
SSMR3PutBool(pSSMHandle, pThis->fGuestSentChangeEventAck);
2119
SSMR3PutU32(pSSMHandle, pThis->guestCaps);
2121
#ifdef VBOX_WITH_HGCM
2122
vmmdevHGCMSaveState (pThis, pSSMHandle);
2123
#endif /* VBOX_WITH_HGCM */
2125
SSMR3PutU32(pSSMHandle, pThis->fHostCursorRequested);
2127
return VINF_SUCCESS;
2131
* Loads the saved VMM device state.
2133
* @returns VBox status code.
2134
* @param pDevIns The device instance.
2135
* @param pSSMHandle The handle to the saved state.
2136
* @param u32Version The data unit version number.
2138
static DECLCALLBACK(int) vmmdevLoadState(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle, uint32_t u32Version)
2140
/** @todo The code load code is assuming we're always loaded into a fresh VM. */
2141
VMMDevState *pThis = PDMINS_2_DATA(pDevIns, VMMDevState*);
2142
if ( SSM_VERSION_MAJOR_CHANGED(u32Version, VMMDEV_SSM_VERSION)
2143
|| (SSM_VERSION_MINOR(u32Version) < 6))
2144
return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
2146
SSMR3GetU32(pSSMHandle, &pThis->hypervisorSize);
2147
SSMR3GetU32(pSSMHandle, &pThis->mouseCapabilities);
2148
SSMR3GetU32(pSSMHandle, &pThis->mouseXAbs);
2149
SSMR3GetU32(pSSMHandle, &pThis->mouseYAbs);
2151
SSMR3GetBool(pSSMHandle, &pThis->fNewGuestFilterMask);
2152
SSMR3GetU32(pSSMHandle, &pThis->u32NewGuestFilterMask);
2153
SSMR3GetU32(pSSMHandle, &pThis->u32GuestFilterMask);
2154
SSMR3GetU32(pSSMHandle, &pThis->u32HostEventFlags);
2155
// SSMR3GetBool(pSSMHandle, &pThis->pVMMDevRAMR3->fHaveEvents);
2156
// here be dragons (probably)
2157
SSMR3GetMem(pSSMHandle, &pThis->pVMMDevRAMR3->V, sizeof (pThis->pVMMDevRAMR3->V));
2159
SSMR3GetMem(pSSMHandle, &pThis->guestInfo, sizeof (pThis->guestInfo));
2160
SSMR3GetU32(pSSMHandle, &pThis->fu32AdditionsOk);
2161
SSMR3GetU32(pSSMHandle, &pThis->u32VideoAccelEnabled);
2162
if (u32Version > 10)
2163
SSMR3GetBool(pSSMHandle, &pThis->fGuestSentChangeEventAck);
2165
SSMR3GetU32(pSSMHandle, &pThis->guestCaps);
2167
/* Attributes which were temporarily introduced in r30072 */
2168
if ( SSM_VERSION_MAJOR(u32Version) == 0
2169
&& SSM_VERSION_MINOR(u32Version) == 7)
2172
SSMR3GetU32(pSSMHandle, &temp);
2173
SSMR3GetU32(pSSMHandle, &temp);
2176
#ifdef VBOX_WITH_HGCM
2177
vmmdevHGCMLoadState (pThis, pSSMHandle, u32Version);
2178
#endif /* VBOX_WITH_HGCM */
2180
if ( SSM_VERSION_MAJOR(u32Version) == 0
2181
&& SSM_VERSION_MINOR(u32Version) >= 10)
2182
SSMR3GetU32(pSSMHandle, &pThis->fHostCursorRequested);
2185
* On a resume, we send the capabilities changed message so
2186
* that listeners can sync their state again
2188
Log(("vmmdevLoadState: capabilities changed (%x), informing connector\n", pThis->mouseCapabilities));
2191
pThis->pDrv->pfnUpdateMouseCapabilities(pThis->pDrv, pThis->mouseCapabilities);
2192
if ( SSM_VERSION_MAJOR(u32Version) == 0
2193
&& SSM_VERSION_MINOR(u32Version) >= 10)
2194
pThis->pDrv->pfnUpdatePointerShape(pThis->pDrv,
2195
pThis->fHostCursorRequested,
2202
/* Reestablish the acceleration status. */
2203
if ( pThis->u32VideoAccelEnabled
2206
pThis->pDrv->pfnVideoAccelEnable (pThis->pDrv, !!pThis->u32VideoAccelEnabled, &pThis->pVMMDevRAMR3->vbvaMemory);
2209
if (pThis->fu32AdditionsOk)
2211
LogRel(("Guest Additions information report: additionsVersion = 0x%08X, osType = 0x%08X\n",
2212
pThis->guestInfo.additionsVersion,
2213
pThis->guestInfo.osType));
2215
pThis->pDrv->pfnUpdateGuestVersion(pThis->pDrv, &pThis->guestInfo);
2218
pThis->pDrv->pfnUpdateGuestCapabilities(pThis->pDrv, pThis->guestCaps);
2220
return VINF_SUCCESS;
2224
* Load state done callback. Notify guest of restore event.
2226
* @returns VBox status code.
2227
* @param pDevIns The device instance.
2228
* @param pSSMHandle The handle to the saved state.
2230
static DECLCALLBACK(int) vmmdevLoadStateDone(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle)
2232
VMMDevState *pThis = PDMINS_2_DATA(pDevIns, VMMDevState*);
2234
#ifdef VBOX_WITH_HGCM
2235
vmmdevHGCMLoadStateDone (pThis, pSSMHandle);
2236
#endif /* VBOX_WITH_HGCM */
2238
VMMDevNotifyGuest (pThis, VMMDEV_EVENT_RESTORED);
2240
return VINF_SUCCESS;
2244
* (Re-)initializes the MMIO2 data.
2246
* @param pThis Pointer to the VMMDev instance data.
2248
static void vmmdevInitRam(VMMDevState *pThis)
2250
memset(pThis->pVMMDevRAMR3, 0, sizeof(VMMDevMemory));
2251
pThis->pVMMDevRAMR3->u32Size = sizeof(VMMDevMemory);
2252
pThis->pVMMDevRAMR3->u32Version = VMMDEV_MEMORY_VERSION;
2256
* Construct a device instance for a VM.
2258
* @returns VBox status.
2259
* @param pDevIns The device instance data.
2260
* If the registration structure is needed, pDevIns->pDevReg points to it.
2261
* @param iInstance Instance number. Use this to figure out which registers and such to use.
2262
* The device number is also found in pDevIns->iInstance, but since it's
2263
* likely to be freqently used PDM passes it as parameter.
2264
* @param pCfgHandle Configuration node handle for the device. Use this to obtain the configuration
2265
* of the device instance. It's also found in pDevIns->pCfgHandle, but like
2266
* iInstance it's expected to be used a bit in this function.
2268
static DECLCALLBACK(int) vmmdevConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfgHandle)
2271
VMMDevState *pThis = PDMINS_2_DATA(pDevIns, VMMDevState *);
2273
Assert(iInstance == 0);
2276
* Validate and read the configuration.
2278
if (!CFGMR3AreValuesValid(pCfgHandle,
2279
"GetHostTimeDisabled\0"
2280
"BackdoorLogDisabled\0"
2284
return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES;
2286
rc = CFGMR3QueryBoolDef(pCfgHandle, "GetHostTimeDisabled", &pThis->fGetHostTimeDisabled, false);
2288
return PDMDEV_SET_ERROR(pDevIns, rc,
2289
N_("Configuration error: Failed querying \"GetHostTimeDisabled\" as a boolean"));
2291
rc = CFGMR3QueryBoolDef(pCfgHandle, "BackdoorLogDisabled", &pThis->fBackdoorLogDisabled, false);
2293
return PDMDEV_SET_ERROR(pDevIns, rc,
2294
N_("Configuration error: Failed querying \"BackdoorLogDisabled\" as a boolean"));
2296
rc = CFGMR3QueryBoolDef(pCfgHandle, "KeepCredentials", &pThis->fKeepCredentials, false);
2298
return PDMDEV_SET_ERROR(pDevIns, rc,
2299
N_("Configuration error: Failed querying \"KeepCredentials\" as a boolean"));
2302
rc = CFGMR3QueryBoolDef(pCfgHandle, "HeapEnabled", &fHeapEnabled, true);
2304
return PDMDEV_SET_ERROR(pDevIns, rc,
2305
N_("Configuration error: Failed querying \"HeapEnabled\" as a boolean"));
2308
* Initialize data (most of it anyway).
2310
/* Save PDM device instance data for future reference. */
2311
pThis->pDevIns = pDevIns;
2313
/* PCI vendor, just a free bogus value */
2314
pThis->dev.config[0x00] = 0xee;
2315
pThis->dev.config[0x01] = 0x80;
2317
pThis->dev.config[0x02] = 0xfe;
2318
pThis->dev.config[0x03] = 0xca;
2319
/* class sub code (other type of system peripheral) */
2320
pThis->dev.config[0x0a] = 0x80;
2321
/* class base code (base system peripheral) */
2322
pThis->dev.config[0x0b] = 0x08;
2324
pThis->dev.config[0x0e] = 0x00;
2325
/* interrupt on pin 0 */
2326
pThis->dev.config[0x3d] = 0x01;
2332
pThis->Base.pfnQueryInterface = vmmdevPortQueryInterface;
2335
pThis->Port.pfnQueryAbsoluteMouse = vmmdevQueryAbsoluteMouse;
2336
pThis->Port.pfnSetAbsoluteMouse = vmmdevSetAbsoluteMouse;
2337
pThis->Port.pfnQueryMouseCapabilities = vmmdevQueryMouseCapabilities;
2338
pThis->Port.pfnSetMouseCapabilities = vmmdevSetMouseCapabilities;
2339
pThis->Port.pfnRequestDisplayChange = vmmdevRequestDisplayChange;
2340
pThis->Port.pfnSetCredentials = vmmdevSetCredentials;
2341
pThis->Port.pfnVBVAChange = vmmdevVBVAChange;
2342
pThis->Port.pfnRequestSeamlessChange = vmmdevRequestSeamlessChange;
2343
pThis->Port.pfnSetMemoryBalloon = vmmdevSetMemoryBalloon;
2344
pThis->Port.pfnSetStatisticsInterval = vmmdevSetStatisticsInterval;
2345
pThis->Port.pfnVRDPChange = vmmdevVRDPChange;
2347
/* Shared folder LED */
2348
pThis->SharedFolders.Led.u32Magic = PDMLED_MAGIC;
2349
pThis->SharedFolders.ILeds.pfnQueryStatusLed = vmmdevQueryStatusLed;
2351
#ifdef VBOX_WITH_HGCM
2353
pThis->HGCMPort.pfnCompleted = hgcmCompleted;
2356
/** @todo convert this into a config parameter like we do everywhere else! */
2357
pThis->cbGuestRAM = MMR3PhysGetRamSize(PDMDevHlpGetVM(pDevIns));
2360
* Create the critical section for the device.
2362
rc = PDMDevHlpCritSectInit(pDevIns, &pThis->CritSect, "VMMDev");
2363
AssertRCReturn(rc, rc);
2364
/* Later: pDevIns->pCritSectR3 = &pThis->CritSect; */
2367
* Register the backdoor logging port
2369
rc = PDMDevHlpIOPortRegister(pDevIns, RTLOG_DEBUG_PORT, 1, NULL, vmmdevBackdoorLog, NULL, NULL, NULL, "VMMDev backdoor logging");
2370
AssertRCReturn(rc, rc);
2372
#ifdef TIMESYNC_BACKDOOR
2374
* Alternative timesync source (temporary!)
2376
rc = PDMDevHlpIOPortRegister(pDevIns, 0x505, 1, NULL, vmmdevTimesyncBackdoorWrite, vmmdevTimesyncBackdoorRead, NULL, NULL, "VMMDev timesync backdoor");
2377
AssertRCReturn(rc, rc);
2381
* Allocate and initialize the MMIO2 memory.
2383
rc = PDMDevHlpMMIO2Register(pDevIns, 1 /*iRegion*/, VMMDEV_RAM_SIZE, 0 /*fFlags*/, (void **)&pThis->pVMMDevRAMR3, "VMMDev");
2385
return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
2386
N_("Failed to allocate %u bytes of memory for the VMM device"), VMMDEV_RAM_SIZE);
2387
vmmdevInitRam(pThis);
2391
rc = PDMDevHlpMMIO2Register(pDevIns, 2 /*iRegion*/, VMMDEV_HEAP_SIZE, 0 /*fFlags*/, (void **)&pThis->pVMMDevHeapR3, "VMMDev Heap");
2393
return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
2394
N_("Failed to allocate %u bytes of memory for the VMM device heap"), PAGE_SIZE);
2398
* Register the PCI device.
2400
rc = PDMDevHlpPCIRegister(pDevIns, &pThis->dev);
2403
if (pThis->dev.devfn == 32 || iInstance != 0)
2404
Log(("!!WARNING!!: pThis->dev.devfn=%d (ignore if testcase or no started by Main)\n", pThis->dev.devfn));
2405
rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0, 0x20, PCI_ADDRESS_SPACE_IO, vmmdevIOPortRegionMap);
2408
rc = PDMDevHlpPCIIORegionRegister(pDevIns, 1, VMMDEV_RAM_SIZE, PCI_ADDRESS_SPACE_MEM, vmmdevIORAMRegionMap);
2413
rc = PDMDevHlpPCIIORegionRegister(pDevIns, 2, VMMDEV_HEAP_SIZE, PCI_ADDRESS_SPACE_MEM_PREFETCH, vmmdevIORAMRegionMap);
2419
* Get the corresponding connector interface
2421
rc = PDMDevHlpDriverAttach(pDevIns, 0, &pThis->Base, &pThis->pDrvBase, "VMM Driver Port");
2424
pThis->pDrv = (PPDMIVMMDEVCONNECTOR)pThis->pDrvBase->pfnQueryInterface(pThis->pDrvBase, PDMINTERFACE_VMMDEV_CONNECTOR);
2426
AssertMsgFailedReturn(("LUN #0 doesn't have a VMMDev connector interface!\n"), VERR_PDM_MISSING_INTERFACE);
2427
#ifdef VBOX_WITH_HGCM
2428
pThis->pHGCMDrv = (PPDMIHGCMCONNECTOR)pThis->pDrvBase->pfnQueryInterface(pThis->pDrvBase, PDMINTERFACE_HGCM_CONNECTOR);
2429
if (!pThis->pHGCMDrv)
2431
Log(("LUN #0 doesn't have a HGCM connector interface, HGCM is not supported. rc=%Rrc\n", rc));
2432
/* this is not actually an error, just means that there is no support for HGCM */
2436
else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
2438
Log(("%s/%d: warning: no driver attached to LUN #0!\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
2442
AssertMsgFailedReturn(("Failed to attach LUN #0! rc=%Rrc\n", rc), rc);
2445
* Attach status driver for shared folders (optional).
2448
rc = PDMDevHlpDriverAttach(pDevIns, PDM_STATUS_LUN, &pThis->Base, &pBase, "Status Port");
2450
pThis->SharedFolders.pLedsConnector = (PPDMILEDCONNECTORS)
2451
pBase->pfnQueryInterface(pBase, PDMINTERFACE_LED_CONNECTORS);
2452
else if (rc != VERR_PDM_NO_ATTACHED_DRIVER)
2454
AssertMsgFailed(("Failed to attach to status driver. rc=%Rrc\n", rc));
2459
* Register saved state and init the HGCM CmdList critsect.
2461
rc = PDMDevHlpSSMRegister(pDevIns, "VMMDev", iInstance, VMMDEV_SSM_VERSION, sizeof(*pThis),
2462
NULL, vmmdevSaveState, NULL,
2463
NULL, vmmdevLoadState, vmmdevLoadStateDone);
2464
AssertRCReturn(rc, rc);
2466
#ifdef VBOX_WITH_HGCM
2467
pThis->pHGCMCmdList = NULL;
2468
rc = RTCritSectInit(&pThis->critsectHGCMCmdList);
2469
AssertRCReturn(rc, rc);
2470
pThis->u32HGCMEnabled = 0;
2471
#endif /* VBOX_WITH_HGCM */
2477
* Reset notification.
2479
* @returns VBox status.
2480
* @param pDrvIns The driver instance data.
2482
static DECLCALLBACK(void) vmmdevReset(PPDMDEVINS pDevIns)
2484
VMMDevState *pThis = PDMINS_2_DATA(pDevIns, VMMDevState*);
2487
* Reset the mouse integration feature bit
2489
if (pThis->mouseCapabilities & (VMMDEV_MOUSEGUESTWANTSABS|VMMDEV_MOUSEGUESTNEEDSHOSTCUR))
2491
pThis->mouseCapabilities &= ~VMMDEV_MOUSEGUESTWANTSABS;
2492
/* notify the connector */
2493
Log(("vmmdevReset: capabilities changed (%x), informing connector\n", pThis->mouseCapabilities));
2494
pThis->pDrv->pfnUpdateMouseCapabilities(pThis->pDrv, pThis->mouseCapabilities);
2496
pThis->fHostCursorRequested = false;
2498
pThis->hypervisorSize = 0;
2500
pThis->u32HostEventFlags = 0;
2502
/* re-initialize the VMMDev memory */
2503
if (pThis->pVMMDevRAMR3)
2504
vmmdevInitRam(pThis);
2506
/* credentials have to go away (by default) */
2507
if (!pThis->fKeepCredentials)
2509
memset(pThis->credentialsLogon.szUserName, '\0', VMMDEV_CREDENTIALS_STRLEN);
2510
memset(pThis->credentialsLogon.szPassword, '\0', VMMDEV_CREDENTIALS_STRLEN);
2511
memset(pThis->credentialsLogon.szDomain, '\0', VMMDEV_CREDENTIALS_STRLEN);
2513
memset(pThis->credentialsJudge.szUserName, '\0', VMMDEV_CREDENTIALS_STRLEN);
2514
memset(pThis->credentialsJudge.szPassword, '\0', VMMDEV_CREDENTIALS_STRLEN);
2515
memset(pThis->credentialsJudge.szDomain, '\0', VMMDEV_CREDENTIALS_STRLEN);
2517
/* Reset means that additions will report again. */
2518
const bool fVersionChanged = pThis->fu32AdditionsOk
2519
|| pThis->guestInfo.additionsVersion
2520
|| pThis->guestInfo.osType != VBOXOSTYPE_Unknown;
2521
if (fVersionChanged)
2522
Log(("vmmdevReset: fu32AdditionsOk=%d additionsVersion=%x osType=%#x\n",
2523
pThis->fu32AdditionsOk, pThis->guestInfo.additionsVersion, pThis->guestInfo.osType));
2524
pThis->fu32AdditionsOk = false;
2525
memset (&pThis->guestInfo, 0, sizeof (pThis->guestInfo));
2527
/* clear pending display change request. */
2528
memset (&pThis->lastReadDisplayChangeRequest, 0, sizeof (pThis->lastReadDisplayChangeRequest));
2529
pThis->fGuestSentChangeEventAck = false;
2531
/* disable seamless mode */
2532
pThis->fLastSeamlessEnabled = false;
2534
/* disabled memory ballooning */
2535
pThis->u32LastMemoryBalloonSize = 0;
2537
/* disabled statistics updating */
2538
pThis->u32LastStatIntervalSize = 0;
2540
/* Clear the "HGCM event enabled" flag so the event can be automatically reenabled. */
2541
pThis->u32HGCMEnabled = 0;
2544
* Clear the event variables.
2546
* Note: The pThis->u32HostEventFlags is not cleared.
2547
* It is designed that way so host events do not
2548
* depend on guest resets.
2550
pThis->u32GuestFilterMask = 0;
2551
pThis->u32NewGuestFilterMask = 0;
2552
pThis->fNewGuestFilterMask = 0;
2554
/* This is the default, as Windows and OS/2 guests take this for granted. (Actually, neither does...) */
2555
/** @todo change this when we next bump the interface version */
2556
const bool fCapsChanged = pThis->guestCaps != VMMDEV_GUEST_SUPPORTS_GRAPHICS;
2558
Log(("vmmdevReset: fCapsChanged=%#x -> %#x\n", pThis->guestCaps, VMMDEV_GUEST_SUPPORTS_GRAPHICS));
2559
pThis->guestCaps = VMMDEV_GUEST_SUPPORTS_GRAPHICS; /** @todo r=bird: why? I cannot see this being done at construction?*/
2562
* Call the update functions as required.
2564
if (fVersionChanged)
2565
pThis->pDrv->pfnUpdateGuestVersion(pThis->pDrv, &pThis->guestInfo);
2567
pThis->pDrv->pfnUpdateGuestCapabilities(pThis->pDrv, pThis->guestCaps);
2572
* The device registration structure.
2574
extern "C" const PDMDEVREG g_DeviceVMMDev =
2584
/* pszDescription */
2585
"VirtualBox VMM Device\n",
2587
PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GUEST_BITS_32,
2589
PDM_DEVREG_CLASS_VMM_DEV,
2593
sizeof(VMMDevState),
2614
/* pfnQueryInterface. */
2616
/* pfnInitComplete */
2625
#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */