VirtualBox

source: vbox/trunk/src/VBox/Devices/VMMDev/VBoxDev.cpp@ 4532

Last change on this file since 4532 was 4532, checked in by vboxsync, 17 years ago

Memory balloon size change updates

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 83.2 KB
Line 
1/** @file
2 *
3 * VBox Guest/VMM/host communication:
4 * Virtual communication device
5 */
6
7/*
8 * Copyright (C) 2006-2007 innotek GmbH
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License as published by the Free Software Foundation,
14 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
15 * distribution. VirtualBox OSE is distributed in the hope that it will
16 * be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19/* #define LOG_ENABLED */
20
21#include <stdio.h>
22#include <string.h>
23
24#define LOG_GROUP LOG_GROUP_DEV_VMM
25#include <VBox/log.h>
26
27#include <VBox/VBoxDev.h>
28#include <VBox/VBoxGuest.h>
29#include <VBox/param.h>
30#include <VBox/mm.h>
31#include <VBox/pgm.h>
32#include <VBox/err.h>
33#include <VBox/vm.h> /* for VM_IS_EMT */
34
35#include <iprt/assert.h>
36#include <iprt/time.h>
37
38#include "VMMDevState.h"
39
40#ifdef VBOX_HGCM
41#include "VMMDevHGCM.h"
42#endif
43
44#define PCIDEV_2_VMMDEVSTATE(pPciDev) ( (VMMDevState *)(pPciDev) )
45#define VMMDEVSTATE_2_DEVINS(pVMMDevState) ( (pVMMDevState)->pDevIns )
46
47#define VBOX_GUEST_ADDITIONS_VERSION_1_03(s) \
48 ((RT_HIWORD ((s)->guestInfo.additionsVersion) == 1) && \
49 (RT_LOWORD ((s)->guestInfo.additionsVersion) == 3))
50
51#define VBOX_GUEST_ADDITIONS_VERSION_OK(additionsVersion) \
52 (RT_HIWORD(additionsVersion) == RT_HIWORD(VMMDEV_VERSION) \
53 && RT_LOWORD(additionsVersion) <= RT_LOWORD(VMMDEV_VERSION))
54
55#define VBOX_GUEST_ADDITIONS_VERSION_OLD(additionsVersion) \
56 ((RT_HIWORD(additionsVersion) < RT_HIWORD(VMMDEV_VERSION) \
57 || ((RT_HIWORD(additionsVersion) == RT_HIWORD(VMMDEV_VERSION) \
58 && RT_LOWORD(additionsVersion) <= RT_LOWORD(VMMDEV_VERSION))
59
60#define VBOX_GUEST_ADDITIONS_VERSION_TOO_OLD(additionsVersion) \
61 (RT_HIWORD(additionsVersion) < RT_HIWORD(VMMDEV_VERSION))
62
63#define VBOX_GUEST_ADDITIONS_VERSION_NEW(additionsVersion) \
64 ((RT_HIWORD(additionsVersion) > RT_HIWORD(VMMDEV_VERSION) \
65 || ((RT_HIWORD(additionsVersion) == RT_HIWORD(VMMDEV_VERSION) \
66 && RT_LOWORD(additionsVersion) > RT_LOWORD(VMMDEV_VERSION))
67
68#ifndef VBOX_DEVICE_STRUCT_TESTCASE
69
70/* Whenever host wants to inform guest about something
71 * an IRQ notification will be raised.
72 *
73 * VMMDev PDM interface will contain the guest notification method.
74 *
75 * There is a 32 bit event mask which will be read
76 * by guest on an interrupt. A non zero bit in the mask
77 * means that the specific event occured and requires
78 * processing on guest side.
79 *
80 * After reading the event mask guest must issue a
81 * generic request AcknowlegdeEvents.
82 *
83 * IRQ line is set to 1 (request) if there are unprocessed
84 * events, that is the event mask is not zero.
85 *
86 * After receiving an interrupt and checking event mask,
87 * the guest must process events using the event specific
88 * mechanism.
89 *
90 * That is if mouse capabilities were changed,
91 * guest will use VMMDev_GetMouseStatus generic request.
92 *
93 * Event mask is only a set of flags indicating that guest
94 * must proceed with a procedure.
95 *
96 * Unsupported events are therefore ignored.
97 * The guest additions must inform host which events they
98 * want to receive, to avoid unnecessary IRQ processing.
99 * By default no events are signalled to guest.
100 *
101 * This seems to be fast method. It requires
102 * only one context switch for an event processing.
103 *
104 */
105
106static void vmmdevSetIRQ_Legacy_EMT (VMMDevState *pVMMDevState)
107{
108 if (!pVMMDevState->fu32AdditionsOk)
109 {
110 Log(("vmmdevSetIRQ: IRQ is not generated, guest has not yet reported to us.\n"));
111 return;
112 }
113
114 uint32_t u32IRQLevel = 0;
115
116 /* Filter unsupported events */
117 uint32_t u32EventFlags =
118 pVMMDevState->u32HostEventFlags
119 & pVMMDevState->pVMMDevRAMHC->V.V1_03.u32GuestEventMask;
120
121 Log(("vmmdevSetIRQ: u32EventFlags = 0x%08X, "
122 "pVMMDevState->u32HostEventFlags = 0x%08X, "
123 "pVMMDevState->pVMMDevRAMHC->u32GuestEventMask = 0x%08X\n",
124 u32EventFlags,
125 pVMMDevState->u32HostEventFlags,
126 pVMMDevState->pVMMDevRAMHC->V.V1_03.u32GuestEventMask));
127
128 /* Move event flags to VMMDev RAM */
129 pVMMDevState->pVMMDevRAMHC->V.V1_03.u32HostEvents = u32EventFlags;
130
131 if (u32EventFlags)
132 {
133 /* Clear host flags which will be delivered to guest. */
134 pVMMDevState->u32HostEventFlags &= ~u32EventFlags;
135 Log(("vmmdevSetIRQ: pVMMDevState->u32HostEventFlags = 0x%08X\n",
136 pVMMDevState->u32HostEventFlags));
137 u32IRQLevel = 1;
138 }
139
140 /* Set IRQ level for pin 0 */
141 /** @todo make IRQ pin configurable, at least a symbolic constant */
142 PPDMDEVINS pDevIns = VMMDEVSTATE_2_DEVINS(pVMMDevState);
143 PDMDevHlpPCISetIrqNoWait(pDevIns, 0, u32IRQLevel);
144 Log(("vmmdevSetIRQ: IRQ set %d\n", u32IRQLevel));
145}
146
147static void vmmdevMaybeSetIRQ_EMT (VMMDevState *pVMMDevState)
148{
149 PPDMDEVINS pDevIns = VMMDEVSTATE_2_DEVINS (pVMMDevState);
150
151#ifdef DEBUG_sunlover
152 Log(("vmmdevMaybeSetIRQ_EMT: u32HostEventFlags = 0x%08X, u32GuestFilterMask = 0x%08X.\n",
153 pVMMDevState->u32HostEventFlags, pVMMDevState->u32GuestFilterMask));
154#endif /* DEBUG_sunlover */
155
156 if (pVMMDevState->u32HostEventFlags & pVMMDevState->u32GuestFilterMask)
157 {
158 pVMMDevState->pVMMDevRAMHC->V.V1_04.fHaveEvents = true;
159 PDMDevHlpPCISetIrqNoWait (pDevIns, 0, 1);
160#ifdef DEBUG_sunlover
161 Log(("vmmdevMaybeSetIRQ_EMT: IRQ set.\n"));
162#endif /* DEBUG_sunlover */
163 }
164}
165
166static void vmmdevNotifyGuest_EMT (VMMDevState *pVMMDevState, uint32_t u32EventMask)
167{
168#ifdef DEBUG_sunlover
169 Log(("VMMDevNotifyGuest_EMT: u32EventMask = 0x%08X.\n", u32EventMask));
170#endif /* DEBUG_sunlover */
171
172 if (VBOX_GUEST_ADDITIONS_VERSION_1_03 (pVMMDevState))
173 {
174#ifdef DEBUG_sunlover
175 Log(("VMMDevNotifyGuest_EMT: Old additions detected.\n"));
176#endif /* DEBUG_sunlover */
177
178 pVMMDevState->u32HostEventFlags |= u32EventMask;
179 vmmdevSetIRQ_Legacy_EMT (pVMMDevState);
180 }
181 else
182 {
183#ifdef DEBUG_sunlover
184 Log(("VMMDevNotifyGuest_EMT: New additions detected.\n"));
185#endif /* DEBUG_sunlover */
186
187 if (!pVMMDevState->fu32AdditionsOk)
188 {
189 pVMMDevState->u32HostEventFlags |= u32EventMask;
190 Log(("vmmdevNotifyGuest_EMT: IRQ is not generated, guest has not yet reported to us.\n"));
191 return;
192 }
193
194 const bool fHadEvents =
195 (pVMMDevState->u32HostEventFlags & pVMMDevState->u32GuestFilterMask) != 0;
196
197#ifdef DEBUG_sunlover
198 Log(("VMMDevNotifyGuest_EMT: fHadEvents = %d, u32HostEventFlags = 0x%08X, u32GuestFilterMask = 0x%08X.\n",
199 fHadEvents, pVMMDevState->u32HostEventFlags, pVMMDevState->u32GuestFilterMask));
200#endif /* DEBUG_sunlover */
201
202 pVMMDevState->u32HostEventFlags |= u32EventMask;
203
204 if (!fHadEvents)
205 vmmdevMaybeSetIRQ_EMT (pVMMDevState);
206 }
207}
208
209static void vmmdevCtlGuestFilterMask_EMT (VMMDevState *pVMMDevState,
210 uint32_t u32OrMask,
211 uint32_t u32NotMask)
212{
213 const bool fHadEvents =
214 (pVMMDevState->u32HostEventFlags & pVMMDevState->u32GuestFilterMask) != 0;
215
216 Log(("vmmdevCtlGuestFilterMask_EMT: u32OrMask = 0x%08X, u32NotMask = 0x%08X, fHadEvents = %d.\n", u32OrMask, u32NotMask, fHadEvents));
217 if (fHadEvents)
218 {
219 if (!pVMMDevState->fNewGuestFilterMask)
220 pVMMDevState->u32NewGuestFilterMask = pVMMDevState->u32GuestFilterMask;
221
222 pVMMDevState->u32NewGuestFilterMask |= u32OrMask;
223 pVMMDevState->u32NewGuestFilterMask &= ~u32NotMask;
224 pVMMDevState->fNewGuestFilterMask = true;
225 }
226 else
227 {
228 pVMMDevState->u32GuestFilterMask |= u32OrMask;
229 pVMMDevState->u32GuestFilterMask &= ~u32NotMask;
230 vmmdevMaybeSetIRQ_EMT (pVMMDevState);
231 }
232}
233
234void VMMDevCtlSetGuestFilterMask (VMMDevState *pVMMDevState,
235 uint32_t u32OrMask,
236 uint32_t u32NotMask)
237{
238 PPDMDEVINS pDevIns = VMMDEVSTATE_2_DEVINS(pVMMDevState);
239 PVM pVM = PDMDevHlpGetVM(pDevIns);
240
241 Log(("VMMDevCtlSetGuestFilterMask: u32OrMask = 0x%08X, u32NotMask = 0x%08X.\n", u32OrMask, u32NotMask));
242
243 if (VM_IS_EMT(pVM))
244 {
245 vmmdevCtlGuestFilterMask_EMT (pVMMDevState, u32OrMask, u32NotMask);
246 }
247 else
248 {
249 int rc;
250 PVMREQ pReq;
251
252 rc = VMR3ReqCallVoid (pVM, &pReq, RT_INDEFINITE_WAIT,
253 (PFNRT) vmmdevCtlGuestFilterMask_EMT,
254 3, pVMMDevState, u32OrMask, u32NotMask);
255 AssertReleaseRC (rc);
256 VMR3ReqFree (pReq);
257 }
258}
259
260void VMMDevNotifyGuest (VMMDevState *pVMMDevState, uint32_t u32EventMask)
261{
262 PPDMDEVINS pDevIns = VMMDEVSTATE_2_DEVINS(pVMMDevState);
263 PVM pVM = PDMDevHlpGetVM(pDevIns);
264 int rc;
265 PVMREQ pReq;
266
267#ifdef DEBUG_sunlover
268 Log(("VMMDevNotifyGuest: u32EventMask = 0x%08X.\n", u32EventMask));
269#endif /* DEBUG_sunlover */
270
271 rc = VMR3ReqCallVoid (pVM, &pReq, RT_INDEFINITE_WAIT,
272 (PFNRT) vmmdevNotifyGuest_EMT,
273 2, pVMMDevState, u32EventMask);
274 AssertReleaseRC (rc);
275 VMR3ReqFree (pReq);
276}
277
278/**
279 * Port I/O Handler for OUT operations.
280 *
281 * @returns VBox status code.
282 *
283 * @param pDevIns The device instance.
284 * @param pvUser User argument - ignored.
285 * @param uPort Port number used for the IN operation.
286 * @param u32 The value to output.
287 * @param cb The value size in bytes.
288 */
289#undef LOG_GROUP
290#define LOG_GROUP LOG_GROUP_DEV_VMM_BACKDOOR
291
292static DECLCALLBACK(int) vmmdevBackdoorLog(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
293{
294 VMMDevState *pData = PDMINS2DATA(pDevIns, VMMDevState *);
295
296 if (!pData->fBackdoorLogDisabled && cb == 1 && Port == RTLOG_DEBUG_PORT)
297 {
298
299 /* The raw version. */
300 switch (u32)
301 {
302 case '\r': Log2(("vmmdev: <return>\n")); break;
303 case '\n': Log2(("vmmdev: <newline>\n")); break;
304 case '\t': Log2(("vmmdev: <tab>\n")); break;
305 default: Log2(("vmmdev: %c (%02x)\n", u32, u32)); break;
306 }
307
308 /* The readable, buffered version. */
309 if (u32 == '\n' || u32 == '\r')
310 {
311 pData->szMsg[pData->iMsg] = '\0';
312 if (pData->iMsg)
313 LogRel(("Guest Log: %s\n", pData->szMsg));
314 pData->iMsg = 0;
315 }
316 else
317 {
318 if (pData->iMsg >= sizeof(pData->szMsg)-1)
319 {
320 pData->szMsg[pData->iMsg] = '\0';
321 LogRel(("Guest Log: %s\n", pData->szMsg));
322 pData->iMsg = 0;
323 }
324 pData->szMsg[pData->iMsg] = (char )u32;
325 pData->szMsg[++pData->iMsg] = '\0';
326 }
327 }
328 return VINF_SUCCESS;
329}
330#undef LOG_GROUP
331#define LOG_GROUP LOG_GROUP_DEV_VMM
332
333#ifdef TIMESYNC_BACKDOOR
334/**
335 * Port I/O Handler for OUT operations.
336 *
337 * @returns VBox status code.
338 *
339 * @param pDevIns The device instance.
340 * @param pvUser User argument - ignored.
341 * @param uPort Port number used for the IN operation.
342 * @param u32 The value to output.
343 * @param cb The value size in bytes.
344 */
345static DECLCALLBACK(int) vmmdevTimesyncBackdoorWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
346{
347 NOREF(pvUser);
348 if (cb == 4)
349 {
350 VMMDevState *pData = PDMINS2DATA(pDevIns, VMMDevState *);
351 switch (u32)
352 {
353 case 0:
354 pData->fTimesyncBackdoorLo = false;
355 break;
356 case 1:
357 pData->fTimesyncBackdoorLo = true;
358 }
359 return VINF_SUCCESS;
360
361 }
362 return VINF_SUCCESS;
363}
364
365/**
366 * Port I/O Handler for backdoor timesync IN operations.
367 *
368 * @returns VBox status code.
369 *
370 * @param pDevIns The device instance.
371 * @param pvUser User argument - ignored.
372 * @param uPort Port number used for the IN operation.
373 * @param pu32 Where to store the result.
374 * @param cb Number of bytes read.
375 */
376static DECLCALLBACK(int) vmmdevTimesyncBackdoorRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
377{
378 int rc;
379 NOREF(pvUser);
380 if (cb == 4)
381 {
382 VMMDevState *pData = PDMINS2DATA(pDevIns, VMMDevState *);
383 RTTIMESPEC now;
384
385 if (pData->fTimesyncBackdoorLo)
386 {
387 *pu32 = (uint32_t)(pData->hostTime & (uint64_t)0xFFFFFFFF);
388 }
389 else
390 {
391 pData->hostTime = RTTimeSpecGetMilli(PDMDevHlpUTCNow(pDevIns, &now));
392 *pu32 = (uint32_t)(pData->hostTime >> 32);
393 }
394 rc = VINF_SUCCESS;
395 }
396 else
397 rc = VERR_IOM_IOPORT_UNUSED;
398 return rc;
399}
400#endif /* TIMESYNC_BACKDOOR */
401
402/**
403 * Port I/O Handler for the generic request interface
404 * @see FNIOMIOPORTOUT for details.
405 */
406static DECLCALLBACK(int) vmmdevRequestHandler(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
407{
408 VMMDevState *pData = (VMMDevState*)pvUser;
409 int rcRet = VINF_SUCCESS;
410 int rc;
411
412 /*
413 * The caller has passed the guest context physical address
414 * of the request structure. Get the corresponding host virtual
415 * address.
416 */
417 VMMDevRequestHeader *requestHeader = NULL;
418 rc = PDMDevHlpPhys2HCVirt(pDevIns, (RTGCPHYS)u32, 0, (PRTHCPTR)&requestHeader);
419 if (VBOX_FAILURE(rc) || !requestHeader)
420 {
421 AssertMsgFailed(("VMMDev could not convert guest physical address to host virtual! rc = %Vrc\n", rc));
422 return VINF_SUCCESS;
423 }
424
425 /* the structure size must be greater or equal to the header size */
426 if (requestHeader->size < sizeof(VMMDevRequestHeader))
427 {
428 Log(("VMMDev request header size too small! size = %d\n", requestHeader->size));
429 return VINF_SUCCESS;
430 }
431
432 /* check the version of the header structure */
433 if (requestHeader->version != VMMDEV_REQUEST_HEADER_VERSION)
434 {
435 Log(("VMMDev: guest header version (0x%08X) differs from ours (0x%08X)\n", requestHeader->version, VMMDEV_REQUEST_HEADER_VERSION));
436 return VINF_SUCCESS;
437 }
438
439 Log2(("VMMDev request issued: %d\n", requestHeader->requestType));
440
441 if (requestHeader->requestType != VMMDevReq_ReportGuestInfo
442 && !pData->fu32AdditionsOk)
443 {
444 Log(("VMMDev: guest has not yet reported to us. Refusing operation.\n"));
445 requestHeader->rc = VERR_NOT_SUPPORTED;
446 return VINF_SUCCESS;
447 }
448
449 /* which request was sent? */
450 switch (requestHeader->requestType)
451 {
452 /*
453 * Guest wants to give up a timeslice
454 */
455 case VMMDevReq_Idle:
456 {
457 /* just return to EMT telling it that we want to halt */
458 return VINF_EM_HALT;
459 break;
460 }
461
462 /*
463 * Guest is reporting its information
464 */
465 case VMMDevReq_ReportGuestInfo:
466 {
467 if (requestHeader->size < sizeof(VMMDevReportGuestInfo))
468 {
469 AssertMsgFailed(("VMMDev guest information structure has invalid size!\n"));
470 requestHeader->rc = VERR_INVALID_PARAMETER;
471 }
472 else
473 {
474 VMMDevReportGuestInfo *guestInfo = (VMMDevReportGuestInfo*)requestHeader;
475
476 if (memcmp (&pData->guestInfo, &guestInfo->guestInfo, sizeof (guestInfo->guestInfo)) != 0)
477 {
478 /* make a copy of supplied information */
479 pData->guestInfo = guestInfo->guestInfo;
480
481 /* Check additions version */
482 pData->fu32AdditionsOk = VBOX_GUEST_ADDITIONS_VERSION_OK(pData->guestInfo.additionsVersion);
483
484 LogRel(("Guest Additions information report: additionsVersion = 0x%08X osType = 0x%08X\n",
485 pData->guestInfo.additionsVersion,
486 pData->guestInfo.osType));
487 pData->pDrv->pfnUpdateGuestVersion(pData->pDrv, &pData->guestInfo);
488 }
489
490 if (pData->fu32AdditionsOk)
491 {
492 requestHeader->rc = VINF_SUCCESS;
493 }
494 else
495 {
496 requestHeader->rc = VERR_VERSION_MISMATCH;
497 }
498 }
499 break;
500 }
501
502 /* Report guest capabilities */
503 case VMMDevReq_ReportGuestCapabilities:
504 {
505 if (requestHeader->size != sizeof(VMMDevReqGuestCapabilities))
506 {
507 AssertMsgFailed(("VMMDev guest caps structure has invalid size!\n"));
508 requestHeader->rc = VERR_INVALID_PARAMETER;
509 }
510 else
511 {
512 VMMDevReqGuestCapabilities *guestCaps = (VMMDevReqGuestCapabilities*)requestHeader;
513
514 if (pData->guestCaps != guestCaps->caps)
515 {
516 /* make a copy of supplied information */
517 pData->guestCaps = guestCaps->caps;
518
519 LogRel(("Guest Additions capability report: (0x%x) "
520 "VMMDEV_GUEST_SUPPORTS_SEAMLESS: %s "
521 "VMMDEV_GUEST_SUPPORTS_GUEST_HOST_WINDOW_MAPPING: %s\n",
522 guestCaps->caps,
523 guestCaps->caps & VMMDEV_GUEST_SUPPORTS_SEAMLESS ? "yes" : "no",
524 guestCaps->caps & VMMDEV_GUEST_SUPPORTS_GUEST_HOST_WINDOW_MAPPING ? "yes" : "no"));
525
526 pData->pDrv->pfnUpdateGuestCapabilities(pData->pDrv, guestCaps->caps);
527 }
528 requestHeader->rc = VINF_SUCCESS;
529 }
530 break;
531 }
532
533 /*
534 * Retrieve mouse information
535 */
536 case VMMDevReq_GetMouseStatus:
537 {
538 if (requestHeader->size != sizeof(VMMDevReqMouseStatus))
539 {
540 AssertMsgFailed(("VMMDev mouse status structure has invalid size!\n"));
541 requestHeader->rc = VERR_INVALID_PARAMETER;
542 }
543 else
544 {
545 VMMDevReqMouseStatus *mouseStatus = (VMMDevReqMouseStatus*)requestHeader;
546 mouseStatus->mouseFeatures = 0;
547 if (pData->mouseCapabilities & VMMDEV_MOUSEHOSTWANTSABS)
548 {
549 mouseStatus->mouseFeatures |= VBOXGUEST_MOUSE_HOST_CAN_ABSOLUTE;
550 }
551 if (pData->mouseCapabilities & VMMDEV_MOUSEGUESTWANTSABS)
552 {
553 mouseStatus->mouseFeatures |= VBOXGUEST_MOUSE_GUEST_CAN_ABSOLUTE;
554 }
555 if (pData->mouseCapabilities & VMMDEV_MOUSEHOSTCANNOTHWPOINTER)
556 {
557 mouseStatus->mouseFeatures |= VBOXGUEST_MOUSE_HOST_CANNOT_HWPOINTER;
558 }
559 mouseStatus->pointerXPos = pData->mouseXAbs;
560 mouseStatus->pointerYPos = pData->mouseYAbs;
561 Log2(("returning mouse status: features = %d, absX = %d, absY = %d\n", mouseStatus->mouseFeatures,
562 mouseStatus->pointerXPos, mouseStatus->pointerYPos));
563 requestHeader->rc = VINF_SUCCESS;
564 }
565 break;
566 }
567
568 /*
569 * Set mouse information
570 */
571 case VMMDevReq_SetMouseStatus:
572 {
573 if (requestHeader->size != sizeof(VMMDevReqMouseStatus))
574 {
575 AssertMsgFailed(("VMMDev mouse status structure has invalid size %d (%#x) version=%d!\n",
576 requestHeader->size, requestHeader->size, requestHeader->size, requestHeader->version));
577 requestHeader->rc = VERR_INVALID_PARAMETER;
578 }
579 else
580 {
581 bool bCapsChanged = false;
582
583 VMMDevReqMouseStatus *mouseStatus = (VMMDevReqMouseStatus*)requestHeader;
584
585 /* check if the guest wants absolute coordinates */
586 if (mouseStatus->mouseFeatures & VBOXGUEST_MOUSE_GUEST_CAN_ABSOLUTE)
587 {
588 /* set the capability flag and the changed flag if it's actually a change */
589 if (!(pData->mouseCapabilities & VMMDEV_MOUSEGUESTWANTSABS))
590 {
591 pData->mouseCapabilities |= VMMDEV_MOUSEGUESTWANTSABS;
592 bCapsChanged = true;
593 LogRel(("Guest requests mouse pointer integration\n"));
594 }
595 } else
596 {
597 if (pData->mouseCapabilities & VMMDEV_MOUSEGUESTWANTSABS)
598 {
599 pData->mouseCapabilities &= ~VMMDEV_MOUSEGUESTWANTSABS;
600 bCapsChanged = true;
601 LogRel(("Guest disables mouse pointer integration\n"));
602 }
603 }
604 if (mouseStatus->mouseFeatures & VBOXGUEST_MOUSE_GUEST_NEEDS_HOST_CURSOR)
605 pData->mouseCapabilities |= VMMDEV_MOUSEGUESTNEEDSHOSTCUR;
606 else
607 pData->mouseCapabilities &= ~VMMDEV_MOUSEGUESTNEEDSHOSTCUR;
608
609 /*
610 * Notify connector if something has changed
611 */
612 if (bCapsChanged)
613 {
614 Log(("VMMDevReq_SetMouseStatus: capabilities changed (%x), informing connector\n", pData->mouseCapabilities));
615 pData->pDrv->pfnUpdateMouseCapabilities(pData->pDrv, pData->mouseCapabilities);
616 }
617 requestHeader->rc = VINF_SUCCESS;
618 }
619
620 break;
621 }
622
623 /*
624 * Set a new mouse pointer shape
625 */
626 case VMMDevReq_SetPointerShape:
627 {
628 if (requestHeader->size < sizeof(VMMDevReqMousePointer))
629 {
630 AssertMsg(requestHeader->size == 0x10028 && requestHeader->version == 10000, /* don't bitch about legacy!!! */
631 ("VMMDev mouse shape structure has invalid size %d (%#x) version=%d!\n",
632 requestHeader->size, requestHeader->size, requestHeader->size, requestHeader->version));
633 requestHeader->rc = VERR_INVALID_PARAMETER;
634 }
635 else
636 {
637 VMMDevReqMousePointer *pointerShape = (VMMDevReqMousePointer*)requestHeader;
638
639 bool fVisible = (pointerShape->fFlags & VBOX_MOUSE_POINTER_VISIBLE) != 0;
640 bool fAlpha = (pointerShape->fFlags & VBOX_MOUSE_POINTER_ALPHA) != 0;
641 bool fShape = (pointerShape->fFlags & VBOX_MOUSE_POINTER_SHAPE) != 0;
642
643 Log(("VMMDevReq_SetPointerShape: visible: %d, alpha: %d, shape = %d, width: %d, height: %d\n",
644 fVisible, fAlpha, fShape, pointerShape->width, pointerShape->height));
645
646 /* forward call to driver */
647 if (fShape)
648 {
649 pData->pDrv->pfnUpdatePointerShape(pData->pDrv,
650 fVisible,
651 fAlpha,
652 pointerShape->xHot, pointerShape->yHot,
653 pointerShape->width, pointerShape->height,
654 pointerShape->pointerData);
655 }
656 else
657 {
658 pData->pDrv->pfnUpdatePointerShape(pData->pDrv,
659 fVisible,
660 0,
661 0, 0,
662 0, 0,
663 NULL);
664 }
665 requestHeader->rc = VINF_SUCCESS;
666 }
667 break;
668 }
669
670 /*
671 * Query the system time from the host
672 */
673 case VMMDevReq_GetHostTime:
674 {
675 if (requestHeader->size != sizeof(VMMDevReqHostTime))
676 {
677 AssertMsgFailed(("VMMDev host time structure has invalid size!\n"));
678 requestHeader->rc = VERR_INVALID_PARAMETER;
679 }
680 else if (RT_UNLIKELY(pData->fGetHostTimeDisabled))
681 requestHeader->rc = VERR_NOT_SUPPORTED;
682 else
683 {
684 VMMDevReqHostTime *hostTimeReq = (VMMDevReqHostTime*)requestHeader;
685 RTTIMESPEC now;
686 hostTimeReq->time = RTTimeSpecGetMilli(PDMDevHlpUTCNow(pDevIns, &now));
687 requestHeader->rc = VINF_SUCCESS;
688 }
689 break;
690 }
691
692 /*
693 * Query information about the hypervisor
694 */
695 case VMMDevReq_GetHypervisorInfo:
696 {
697 if (requestHeader->size != sizeof(VMMDevReqHypervisorInfo))
698 {
699 AssertMsgFailed(("VMMDev hypervisor info structure has invalid size!\n"));
700 requestHeader->rc = VERR_INVALID_PARAMETER;
701 }
702 else
703 {
704 VMMDevReqHypervisorInfo *hypervisorInfo = (VMMDevReqHypervisorInfo*)requestHeader;
705 PVM pVM = PDMDevHlpGetVM(pDevIns);
706 size_t hypervisorSize = 0;
707 requestHeader->rc = PGMR3MappingsSize(pVM, &hypervisorSize);
708 hypervisorInfo->hypervisorSize = (uint32_t)hypervisorSize;
709 Assert(hypervisorInfo->hypervisorSize == hypervisorSize);
710 }
711 break;
712 }
713
714 /*
715 * Set hypervisor information
716 */
717 case VMMDevReq_SetHypervisorInfo:
718 {
719 if (requestHeader->size != sizeof(VMMDevReqHypervisorInfo))
720 {
721 AssertMsgFailed(("VMMDev hypervisor info structure has invalid size!\n"));
722 requestHeader->rc = VERR_INVALID_PARAMETER;
723 }
724 else
725 {
726 VMMDevReqHypervisorInfo *hypervisorInfo = (VMMDevReqHypervisorInfo*)requestHeader;
727 PVM pVM = PDMDevHlpGetVM(pDevIns);
728 if (hypervisorInfo->hypervisorStart == 0)
729 {
730 requestHeader->rc = PGMR3MappingsUnfix(pVM);
731 } else
732 {
733 /* only if the client has queried the size before! */
734 size_t mappingsSize;
735 requestHeader->rc = PGMR3MappingsSize(pVM, &mappingsSize);
736 if (VBOX_SUCCESS(requestHeader->rc) && (hypervisorInfo->hypervisorSize == mappingsSize))
737 {
738 /* new reservation */
739 requestHeader->rc = PGMR3MappingsFix(pVM, hypervisorInfo->hypervisorStart,
740 hypervisorInfo->hypervisorSize);
741 LogRel(("Guest reported fixed hypervisor window at 0x%p (size = 0x%x, rc = %Vrc)\n",
742 hypervisorInfo->hypervisorStart,
743 hypervisorInfo->hypervisorSize,
744 requestHeader->rc));
745 }
746 }
747 }
748 break;
749 }
750
751 /*
752 * Set the system power status
753 */
754 case VMMDevReq_SetPowerStatus:
755 {
756 if (requestHeader->size != sizeof(VMMDevPowerStateRequest))
757 {
758 AssertMsgFailed(("VMMDev power state request structure has invalid size!\n"));
759 requestHeader->rc = VERR_INVALID_PARAMETER;
760 }
761 else
762 {
763 VMMDevPowerStateRequest *powerStateRequest = (VMMDevPowerStateRequest*)requestHeader;
764 switch(powerStateRequest->powerState)
765 {
766 case VMMDevPowerState_Pause:
767 {
768 LogRel(("Guest requests the VM to be suspended (paused)\n"));
769 requestHeader->rc = rcRet = PDMDevHlpVMSuspend(pDevIns);
770 break;
771 }
772
773 case VMMDevPowerState_PowerOff:
774 {
775 LogRel(("Guest requests the VM to be turned off\n"));
776 requestHeader->rc = rcRet = PDMDevHlpVMPowerOff(pDevIns);
777 break;
778 }
779
780 case VMMDevPowerState_SaveState:
781 {
782 /** @todo no API for that yet */
783 requestHeader->rc = VERR_NOT_IMPLEMENTED;
784 break;
785 }
786
787 default:
788 AssertMsgFailed(("VMMDev invalid power state request: %d\n", powerStateRequest->powerState));
789 requestHeader->rc = VERR_INVALID_PARAMETER;
790 break;
791 }
792 }
793 break;
794 }
795
796 /*
797 * Get display change request
798 */
799 case VMMDevReq_GetDisplayChangeRequest:
800 {
801 if (requestHeader->size != sizeof(VMMDevDisplayChangeRequest))
802 {
803 /* Assert only if the size also not equal to a previous version size to prevent
804 * assertion with old additions.
805 */
806 AssertMsg(requestHeader->size == sizeof(VMMDevDisplayChangeRequest) - sizeof (uint32_t),
807 ("VMMDev display change request structure has invalid size!\n"));
808 requestHeader->rc = VERR_INVALID_PARAMETER;
809 }
810 else
811 {
812 VMMDevDisplayChangeRequest *displayChangeRequest = (VMMDevDisplayChangeRequest*)requestHeader;
813 /* just pass on the information */
814 Log(("VMMDev: returning display change request xres = %d, yres = %d, bpp = %d\n",
815 pData->displayChangeRequest.xres, pData->displayChangeRequest.yres, pData->displayChangeRequest.bpp));
816 displayChangeRequest->xres = pData->displayChangeRequest.xres;
817 displayChangeRequest->yres = pData->displayChangeRequest.yres;
818 displayChangeRequest->bpp = pData->displayChangeRequest.bpp;
819
820 if (displayChangeRequest->eventAck == VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST)
821 {
822 /* Remember which resolution the client has queried. */
823 pData->lastReadDisplayChangeRequest = pData->displayChangeRequest;
824 }
825
826 requestHeader->rc = VINF_SUCCESS;
827 }
828 break;
829 }
830
831 case VMMDevReq_GetDisplayChangeRequest2:
832 {
833 if (requestHeader->size != sizeof(VMMDevDisplayChangeRequest2))
834 {
835 requestHeader->rc = VERR_INVALID_PARAMETER;
836 }
837 else
838 {
839 VMMDevDisplayChangeRequest2 *displayChangeRequest = (VMMDevDisplayChangeRequest2*)requestHeader;
840 /* just pass on the information */
841 Log(("VMMDev: returning display change request xres = %d, yres = %d, bpp = %d at %d\n",
842 pData->displayChangeRequest.xres, pData->displayChangeRequest.yres, pData->displayChangeRequest.bpp, pData->displayChangeRequest.display));
843 displayChangeRequest->xres = pData->displayChangeRequest.xres;
844 displayChangeRequest->yres = pData->displayChangeRequest.yres;
845 displayChangeRequest->bpp = pData->displayChangeRequest.bpp;
846 displayChangeRequest->display = pData->displayChangeRequest.display;
847
848 if (displayChangeRequest->eventAck == VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST)
849 {
850 /* Remember which resolution the client has queried. */
851 pData->lastReadDisplayChangeRequest = pData->displayChangeRequest;
852 }
853
854 requestHeader->rc = VINF_SUCCESS;
855 }
856 break;
857 }
858
859 /*
860 * Query whether the given video mode is supported
861 */
862 case VMMDevReq_VideoModeSupported:
863 {
864 if (requestHeader->size != sizeof(VMMDevVideoModeSupportedRequest))
865 {
866 AssertMsgFailed(("VMMDev video mode supported request structure has invalid size!\n"));
867 requestHeader->rc = VERR_INVALID_PARAMETER;
868 }
869 else
870 {
871 VMMDevVideoModeSupportedRequest *videoModeSupportedRequest = (VMMDevVideoModeSupportedRequest*)requestHeader;
872 /* forward the call */
873 requestHeader->rc = pData->pDrv->pfnVideoModeSupported(pData->pDrv,
874 videoModeSupportedRequest->width,
875 videoModeSupportedRequest->height,
876 videoModeSupportedRequest->bpp,
877 &videoModeSupportedRequest->fSupported);
878 }
879 break;
880 }
881
882 /*
883 * Query the height reduction in pixels
884 */
885 case VMMDevReq_GetHeightReduction:
886 {
887 if (requestHeader->size != sizeof(VMMDevGetHeightReductionRequest))
888 {
889 AssertMsgFailed(("VMMDev height reduction request structure has invalid size!\n"));
890 requestHeader->rc = VERR_INVALID_PARAMETER;
891 }
892 else
893 {
894 VMMDevGetHeightReductionRequest *heightReductionRequest = (VMMDevGetHeightReductionRequest*)requestHeader;
895 /* forward the call */
896 requestHeader->rc = pData->pDrv->pfnGetHeightReduction(pData->pDrv,
897 &heightReductionRequest->heightReduction);
898 }
899 break;
900 }
901
902 /*
903 * Acknowledge VMMDev events
904 */
905 case VMMDevReq_AcknowledgeEvents:
906 {
907 if (requestHeader->size != sizeof(VMMDevEvents))
908 {
909 AssertMsgFailed(("VMMDevReq_AcknowledgeEvents structure has invalid size!\n"));
910 requestHeader->rc = VERR_INVALID_PARAMETER;
911 }
912 else
913 {
914 if (VBOX_GUEST_ADDITIONS_VERSION_1_03 (pData))
915 {
916 vmmdevSetIRQ_Legacy_EMT (pData);
917 }
918 else
919 {
920 VMMDevEvents *pAckRequest;
921
922 if (pData->fNewGuestFilterMask)
923 {
924 pData->fNewGuestFilterMask = false;
925 pData->u32GuestFilterMask = pData->u32NewGuestFilterMask;
926 }
927
928 pAckRequest = (VMMDevEvents *) requestHeader;
929 pAckRequest->events =
930 pData->u32HostEventFlags & pData->u32GuestFilterMask;
931
932 pData->u32HostEventFlags &= ~pData->u32GuestFilterMask;
933 pData->pVMMDevRAMHC->V.V1_04.fHaveEvents = false;
934 PDMDevHlpPCISetIrqNoWait (pData->pDevIns, 0, 0);
935 }
936 requestHeader->rc = VINF_SUCCESS;
937 }
938 break;
939 }
940
941 /*
942 * Change guest filter mask
943 */
944 case VMMDevReq_CtlGuestFilterMask:
945 {
946 if (requestHeader->size != sizeof(VMMDevCtlGuestFilterMask))
947 {
948 AssertMsgFailed(("VMMDevReq_AcknowledgeEvents structure has invalid size!\n"));
949 requestHeader->rc = VERR_INVALID_PARAMETER;
950 }
951 else
952 {
953 VMMDevCtlGuestFilterMask *pCtlMaskRequest;
954
955 pCtlMaskRequest = (VMMDevCtlGuestFilterMask *) requestHeader;
956 /* The HGCM events are enabled by the VMMDev device automatically when any
957 * HGCM command is issued. The guest then can not disable these events.
958 */
959 vmmdevCtlGuestFilterMask_EMT (pData,
960 pCtlMaskRequest->u32OrMask,
961 pCtlMaskRequest->u32NotMask & ~VMMDEV_EVENT_HGCM);
962 requestHeader->rc = VINF_SUCCESS;
963
964 }
965 break;
966 }
967
968#ifdef VBOX_HGCM
969 /*
970 * Process HGCM request
971 */
972 case VMMDevReq_HGCMConnect:
973 {
974 if (requestHeader->size < sizeof(VMMDevHGCMConnect))
975 {
976 AssertMsgFailed(("VMMDevReq_HGCMConnect structure has invalid size!\n"));
977 requestHeader->rc = VERR_INVALID_PARAMETER;
978 }
979 else if (!pData->pHGCMDrv)
980 {
981 Log(("VMMDevReq_HGCMConnect HGCM Connector is NULL!\n"));
982 requestHeader->rc = VERR_NOT_SUPPORTED;
983 }
984 else
985 {
986 VMMDevHGCMConnect *pHGCMConnect = (VMMDevHGCMConnect *)requestHeader;
987
988 Log(("VMMDevReq_HGCMConnect\n"));
989
990 requestHeader->rc = vmmdevHGCMConnect (pData, pHGCMConnect, (RTGCPHYS)u32);
991 }
992 break;
993 }
994
995 case VMMDevReq_HGCMDisconnect:
996 {
997 if (requestHeader->size < sizeof(VMMDevHGCMDisconnect))
998 {
999 AssertMsgFailed(("VMMDevReq_HGCMDisconnect structure has invalid size!\n"));
1000 requestHeader->rc = VERR_INVALID_PARAMETER;
1001 }
1002 else if (!pData->pHGCMDrv)
1003 {
1004 Log(("VMMDevReq_HGCMDisconnect HGCM Connector is NULL!\n"));
1005 requestHeader->rc = VERR_NOT_SUPPORTED;
1006 }
1007 else
1008 {
1009 VMMDevHGCMDisconnect *pHGCMDisconnect = (VMMDevHGCMDisconnect *)requestHeader;
1010
1011 Log(("VMMDevReq_VMMDevHGCMDisconnect\n"));
1012 requestHeader->rc = vmmdevHGCMDisconnect (pData, pHGCMDisconnect, (RTGCPHYS)u32);
1013 }
1014 break;
1015 }
1016
1017 case VMMDevReq_HGCMCall:
1018 {
1019 if (requestHeader->size < sizeof(VMMDevHGCMCall))
1020 {
1021 AssertMsgFailed(("VMMDevReq_HGCMCall structure has invalid size!\n"));
1022 requestHeader->rc = VERR_INVALID_PARAMETER;
1023 }
1024 else if (!pData->pHGCMDrv)
1025 {
1026 Log(("VMMDevReq_HGCMCall HGCM Connector is NULL!\n"));
1027 requestHeader->rc = VERR_NOT_SUPPORTED;
1028 }
1029 else
1030 {
1031 VMMDevHGCMCall *pHGCMCall = (VMMDevHGCMCall *)requestHeader;
1032
1033 Log2(("VMMDevReq_HGCMCall: sizeof (VMMDevHGCMRequest) = %04X\n", sizeof (VMMDevHGCMCall)));
1034 Log2(("%.*Vhxd\n", requestHeader->size, requestHeader));
1035
1036 requestHeader->rc = vmmdevHGCMCall (pData, pHGCMCall, (RTGCPHYS)u32);
1037 }
1038 break;
1039 }
1040#endif /* VBOX_HGCM */
1041
1042 case VMMDevReq_VideoAccelEnable:
1043 {
1044 if (requestHeader->size < sizeof(VMMDevVideoAccelEnable))
1045 {
1046 Log(("VMMDevReq_VideoAccelEnable request size too small!!!\n"));
1047 requestHeader->rc = VERR_INVALID_PARAMETER;
1048 }
1049 else if (!pData->pDrv)
1050 {
1051 Log(("VMMDevReq_VideoAccelEnable Connector is NULL!!!\n"));
1052 requestHeader->rc = VERR_NOT_SUPPORTED;
1053 }
1054 else
1055 {
1056 VMMDevVideoAccelEnable *ptr = (VMMDevVideoAccelEnable *)requestHeader;
1057
1058 if (ptr->cbRingBuffer != VBVA_RING_BUFFER_SIZE)
1059 {
1060 /* The guest driver seems compiled with another headers. */
1061 Log(("VMMDevReq_VideoAccelEnable guest ring buffer size %d, should be %d!!!\n", ptr->cbRingBuffer, VBVA_RING_BUFFER_SIZE));
1062 requestHeader->rc = VERR_INVALID_PARAMETER;
1063 }
1064 else
1065 {
1066 /* The request is correct. */
1067 ptr->fu32Status |= VBVA_F_STATUS_ACCEPTED;
1068
1069 LogFlow(("VMMDevReq_VideoAccelEnable ptr->u32Enable = %d\n", ptr->u32Enable));
1070
1071 requestHeader->rc = ptr->u32Enable?
1072 pData->pDrv->pfnVideoAccelEnable (pData->pDrv, true, &pData->pVMMDevRAMHC->vbvaMemory):
1073 pData->pDrv->pfnVideoAccelEnable (pData->pDrv, false, NULL);
1074
1075 if ( ptr->u32Enable
1076 && VBOX_SUCCESS (requestHeader->rc))
1077 {
1078 ptr->fu32Status |= VBVA_F_STATUS_ENABLED;
1079
1080 /* Remember that guest successfully enabled acceleration.
1081 * We need to reestablish it on restoring the VM from saved state.
1082 */
1083 pData->u32VideoAccelEnabled = 1;
1084 }
1085 else
1086 {
1087 /* The acceleration was not enabled. Remember that. */
1088 pData->u32VideoAccelEnabled = 0;
1089 }
1090 }
1091 }
1092 break;
1093 }
1094
1095 case VMMDevReq_VideoAccelFlush:
1096 {
1097 if (requestHeader->size < sizeof(VMMDevVideoAccelFlush))
1098 {
1099 AssertMsgFailed(("VMMDevReq_VideoAccelFlush request size too small.\n"));
1100 requestHeader->rc = VERR_INVALID_PARAMETER;
1101 }
1102 else if (!pData->pDrv)
1103 {
1104 Log(("VMMDevReq_VideoAccelFlush Connector is NULL!\n"));
1105 requestHeader->rc = VERR_NOT_SUPPORTED;
1106 }
1107 else
1108 {
1109 pData->pDrv->pfnVideoAccelFlush (pData->pDrv);
1110
1111 requestHeader->rc = VINF_SUCCESS;
1112 }
1113 break;
1114 }
1115
1116 case VMMDevReq_VideoSetVisibleRegion:
1117 {
1118 if (requestHeader->size < sizeof(VMMDevVideoSetVisibleRegion))
1119 {
1120 Log(("VMMDevReq_VideoSetVisibleRegion request size too small!!!\n"));
1121 requestHeader->rc = VERR_INVALID_PARAMETER;
1122 }
1123 else if (!pData->pDrv)
1124 {
1125 Log(("VMMDevReq_VideoSetVisibleRegion Connector is NULL!!!\n"));
1126 requestHeader->rc = VERR_NOT_SUPPORTED;
1127 }
1128 else
1129 {
1130 VMMDevVideoSetVisibleRegion *ptr = (VMMDevVideoSetVisibleRegion *)requestHeader;
1131
1132 if (!ptr->cRect)
1133 {
1134 Log(("VMMDevReq_VideoSetVisibleRegion no rectangles!!!\n"));
1135 requestHeader->rc = VERR_INVALID_PARAMETER;
1136 }
1137 else
1138 if (requestHeader->size != sizeof(VMMDevVideoSetVisibleRegion) + (ptr->cRect-1)*sizeof(RTRECT))
1139 {
1140 Log(("VMMDevReq_VideoSetVisibleRegion request size too small!!!\n"));
1141 requestHeader->rc = VERR_INVALID_PARAMETER;
1142 }
1143 else
1144 {
1145 Log(("VMMDevReq_VideoSetVisibleRegion %d rectangles\n", ptr->cRect));
1146 /* forward the call */
1147 requestHeader->rc = pData->pDrv->pfnSetVisibleRegion(pData->pDrv, ptr->cRect, &ptr->Rect);
1148 }
1149 }
1150 break;
1151 }
1152
1153 case VMMDevReq_GetSeamlessChangeRequest:
1154 {
1155 if (requestHeader->size != sizeof(VMMDevSeamlessChangeRequest))
1156 {
1157 requestHeader->rc = VERR_INVALID_PARAMETER;
1158 }
1159 else
1160 {
1161 VMMDevSeamlessChangeRequest *seamlessChangeRequest = (VMMDevSeamlessChangeRequest*)requestHeader;
1162 /* just pass on the information */
1163 Log(("VMMDev: returning seamless change request mode=%d\n", pData->fSeamlessEnabled));
1164 if (pData->fSeamlessEnabled)
1165 seamlessChangeRequest->mode = VMMDev_Seamless_Visible_Region;
1166 else
1167 seamlessChangeRequest->mode = VMMDev_Seamless_Disabled;
1168
1169 if (seamlessChangeRequest->eventAck == VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST)
1170 {
1171 /* Remember which mode the client has queried. */
1172 pData->fLastSeamlessEnabled = pData->fSeamlessEnabled;
1173 }
1174
1175 requestHeader->rc = VINF_SUCCESS;
1176 }
1177 break;
1178 }
1179
1180
1181 case VMMDevReq_GetMemBalloonChangeRequest:
1182 {
1183 Log(("VMMDevReq_GetMemBalloonChangeRequest\n"));
1184 if (requestHeader->size != sizeof(VMMDevGetMemBalloonChangeRequest))
1185 {
1186 AssertFailed();
1187 requestHeader->rc = VERR_INVALID_PARAMETER;
1188 }
1189 else
1190 {
1191 VMMDevGetMemBalloonChangeRequest *memBalloonChangeRequest = (VMMDevGetMemBalloonChangeRequest*)requestHeader;
1192 /* just pass on the information */
1193 Log(("VMMDev: returning memory balloon size =%d\n", pData->u32MemoryBalloonSize));
1194 memBalloonChangeRequest->u32BalloonSize = pData->u32MemoryBalloonSize;
1195
1196 if (memBalloonChangeRequest->eventAck == VMMDEV_EVENT_BALLOON_CHANGE_REQUEST)
1197 {
1198 /* Remember which mode the client has queried. */
1199 pData->u32LastMemoryBalloonSize = pData->u32MemoryBalloonSize;
1200 }
1201
1202 requestHeader->rc = VINF_SUCCESS;
1203 }
1204 break;
1205 }
1206
1207 case VMMDevReq_ChangeMemBalloon:
1208 {
1209 VMMDevChangeMemBalloon *memBalloonChange = (VMMDevChangeMemBalloon*)requestHeader;
1210
1211 Log(("VMMDevReq_ChangeMemBalloon\n"));
1212 if ( requestHeader->size < sizeof(VMMDevChangeMemBalloon)
1213 || requestHeader->size != RT_OFFSETOF(VMMDevChangeMemBalloon, aPhysPage[memBalloonChange->cPages]))
1214 {
1215 AssertFailed();
1216 requestHeader->rc = VERR_INVALID_PARAMETER;
1217 }
1218 else
1219 {
1220 requestHeader->rc = pData->pDrv->pfnChangeMemoryBalloon(pData->pDrv, !!memBalloonChange->fInflate, memBalloonChange->cPages, memBalloonChange->aPhysPage);
1221 }
1222 break;
1223 }
1224
1225 case VMMDevReq_GetStatisticsChangeRequest:
1226 {
1227 Log(("VMMDevReq_GetStatisticsChangeRequest\n"));
1228 if (requestHeader->size != sizeof(VMMDevGetStatisticsChangeRequest))
1229 {
1230 AssertFailed();
1231 requestHeader->rc = VERR_INVALID_PARAMETER;
1232 }
1233 else
1234 {
1235 VMMDevGetStatisticsChangeRequest *statIntervalChangeRequest = (VMMDevGetStatisticsChangeRequest*)requestHeader;
1236 /* just pass on the information */
1237 Log(("VMMDev: returning statistics interval %d seconds\n", pData->u32StatIntervalSize));
1238 statIntervalChangeRequest->u32StatInterval = pData->u32StatIntervalSize;
1239
1240 if (statIntervalChangeRequest->eventAck == VMMDEV_EVENT_STATISTICS_INTERVAL_CHANGE_REQUEST)
1241 {
1242 /* Remember which mode the client has queried. */
1243 pData->u32LastStatIntervalSize= pData->u32StatIntervalSize;
1244 }
1245
1246 requestHeader->rc = VINF_SUCCESS;
1247 }
1248 break;
1249 }
1250
1251 case VMMDevReq_ReportGuestStats:
1252 {
1253 Log(("VMMDevReq_ReportGuestStats\n"));
1254 if (requestHeader->size != sizeof(VMMDevReportGuestStats))
1255 {
1256 requestHeader->rc = VERR_INVALID_PARAMETER;
1257 }
1258 else
1259 {
1260 VMMDevReportGuestStats *stats = (VMMDevReportGuestStats*)requestHeader;
1261
1262 /* Update the last known memory balloon size */
1263 if (stats->guestStats.u32StatCaps & VBOX_GUEST_STAT_PHYS_MEM_BALLOON)
1264 pData->u32LastMemoryBalloonSize = stats->guestStats.u32PhysMemBalloon;
1265
1266 /* forward the call */
1267 requestHeader->rc = pData->pDrv->pfnReportStatistics(pData->pDrv, &stats->guestStats);
1268 }
1269 break;
1270 }
1271
1272 case VMMDevReq_QueryCredentials:
1273 {
1274 if (requestHeader->size != sizeof(VMMDevCredentials))
1275 {
1276 AssertMsgFailed(("VMMDevReq_QueryCredentials request size too small.\n"));
1277 requestHeader->rc = VERR_INVALID_PARAMETER;
1278 }
1279 else
1280 {
1281 VMMDevCredentials *credentials = (VMMDevCredentials*)requestHeader;
1282
1283 /* let's start by nulling out the data */
1284 memset(credentials->szUserName, '\0', VMMDEV_CREDENTIALS_STRLEN);
1285 memset(credentials->szPassword, '\0', VMMDEV_CREDENTIALS_STRLEN);
1286 memset(credentials->szDomain, '\0', VMMDEV_CREDENTIALS_STRLEN);
1287
1288 /* should we return whether we got credentials for a logon? */
1289 if (credentials->u32Flags & VMMDEV_CREDENTIALS_QUERYPRESENCE)
1290 {
1291 if ( pData->credentialsLogon.szUserName[0]
1292 || pData->credentialsLogon.szPassword[0]
1293 || pData->credentialsLogon.szDomain[0])
1294 {
1295 credentials->u32Flags |= VMMDEV_CREDENTIALS_PRESENT;
1296 }
1297 else
1298 {
1299 credentials->u32Flags &= ~VMMDEV_CREDENTIALS_PRESENT;
1300 }
1301 }
1302
1303 /* does the guest want to read logon credentials? */
1304 if (credentials->u32Flags & VMMDEV_CREDENTIALS_READ)
1305 {
1306 if (pData->credentialsLogon.szUserName[0])
1307 strcpy(credentials->szUserName, pData->credentialsLogon.szUserName);
1308 if (pData->credentialsLogon.szPassword[0])
1309 strcpy(credentials->szPassword, pData->credentialsLogon.szPassword);
1310 if (pData->credentialsLogon.szDomain[0])
1311 strcpy(credentials->szDomain, pData->credentialsLogon.szDomain);
1312 if (!pData->credentialsLogon.fAllowInteractiveLogon)
1313 credentials->u32Flags |= VMMDEV_CREDENTIALS_NOLOCALLOGON;
1314 else
1315 credentials->u32Flags &= ~VMMDEV_CREDENTIALS_NOLOCALLOGON;
1316 }
1317
1318 /* does the caller want us to destroy the logon credentials? */
1319 if (credentials->u32Flags & VMMDEV_CREDENTIALS_CLEAR)
1320 {
1321 memset(pData->credentialsLogon.szUserName, '\0', VMMDEV_CREDENTIALS_STRLEN);
1322 memset(pData->credentialsLogon.szPassword, '\0', VMMDEV_CREDENTIALS_STRLEN);
1323 memset(pData->credentialsLogon.szDomain, '\0', VMMDEV_CREDENTIALS_STRLEN);
1324 }
1325
1326 /* does the guest want to read credentials for verification? */
1327 if (credentials->u32Flags & VMMDEV_CREDENTIALS_READJUDGE)
1328 {
1329 if (pData->credentialsJudge.szUserName[0])
1330 strcpy(credentials->szUserName, pData->credentialsJudge.szUserName);
1331 if (pData->credentialsJudge.szPassword[0])
1332 strcpy(credentials->szPassword, pData->credentialsJudge.szPassword);
1333 if (pData->credentialsJudge.szDomain[0])
1334 strcpy(credentials->szDomain, pData->credentialsJudge.szDomain);
1335 }
1336
1337 /* does the caller want us to destroy the judgement credentials? */
1338 if (credentials->u32Flags & VMMDEV_CREDENTIALS_CLEARJUDGE)
1339 {
1340 memset(pData->credentialsJudge.szUserName, '\0', VMMDEV_CREDENTIALS_STRLEN);
1341 memset(pData->credentialsJudge.szPassword, '\0', VMMDEV_CREDENTIALS_STRLEN);
1342 memset(pData->credentialsJudge.szDomain, '\0', VMMDEV_CREDENTIALS_STRLEN);
1343 }
1344
1345 requestHeader->rc = VINF_SUCCESS;
1346 }
1347 break;
1348 }
1349
1350 case VMMDevReq_ReportCredentialsJudgement:
1351 {
1352 if (requestHeader->size != sizeof(VMMDevCredentials))
1353 {
1354 AssertMsgFailed(("VMMDevReq_ReportCredentialsJudgement request size too small.\n"));
1355 requestHeader->rc = VERR_INVALID_PARAMETER;
1356 }
1357 else
1358 {
1359 VMMDevCredentials *credentials = (VMMDevCredentials*)requestHeader;
1360
1361 /* what does the guest think about the credentials? (note: the order is important here!) */
1362 if (credentials->u32Flags & VMMDEV_CREDENTIALS_JUDGE_DENY)
1363 {
1364 pData->pDrv->pfnSetCredentialsJudgementResult(pData->pDrv, VMMDEV_CREDENTIALS_JUDGE_DENY);
1365 }
1366 else if (credentials->u32Flags & VMMDEV_CREDENTIALS_JUDGE_NOJUDGEMENT)
1367 {
1368 pData->pDrv->pfnSetCredentialsJudgementResult(pData->pDrv, VMMDEV_CREDENTIALS_JUDGE_NOJUDGEMENT);
1369 }
1370 else if (credentials->u32Flags & VMMDEV_CREDENTIALS_JUDGE_OK)
1371 {
1372 pData->pDrv->pfnSetCredentialsJudgementResult(pData->pDrv, VMMDEV_CREDENTIALS_JUDGE_OK);
1373 }
1374 else
1375 Log(("VMMDevReq_ReportCredentialsJudgement: invalid flags: %d!!!\n", credentials->u32Flags));
1376
1377 requestHeader->rc = VINF_SUCCESS;
1378 }
1379 break;
1380 }
1381
1382#ifdef DEBUG
1383 case VMMDevReq_LogString:
1384 {
1385 if (requestHeader->size < sizeof(VMMDevReqLogString))
1386 {
1387 AssertMsgFailed(("VMMDevReq_LogString request size too small.\n"));
1388 requestHeader->rc = VERR_INVALID_PARAMETER;
1389 }
1390 else
1391 {
1392 VMMDevReqLogString *pReqLogString = (VMMDevReqLogString*)requestHeader;
1393#undef LOG_GROUP
1394#define LOG_GROUP LOG_GROUP_DEV_VMM_BACKDOOR
1395// Log(("Guest Log: %s", pReqLogString->szString));
1396 Log(("DEBUG LOG: %s", pReqLogString->szString));
1397
1398#undef LOG_GROUP
1399#define LOG_GROUP LOG_GROUP_DEV_VMM
1400 requestHeader->rc = VINF_SUCCESS;
1401 }
1402 break;
1403 }
1404#endif
1405 default:
1406 {
1407 requestHeader->rc = VERR_NOT_IMPLEMENTED;
1408
1409 Log(("VMMDev unknown request type %d\n", requestHeader->requestType));
1410
1411 break;
1412 }
1413 }
1414
1415 return rcRet;
1416}
1417
1418/**
1419 * Callback function for mapping an PCI I/O region.
1420 *
1421 * @return VBox status code.
1422 * @param pPciDev Pointer to PCI device. Use pPciDev->pDevIns to get the device instance.
1423 * @param iRegion The region number.
1424 * @param GCPhysAddress Physical address of the region. If iType is PCI_ADDRESS_SPACE_IO, this is an
1425 * I/O port, else it's a physical address.
1426 * This address is *NOT* relative to pci_mem_base like earlier!
1427 * @param enmType One of the PCI_ADDRESS_SPACE_* values.
1428 */
1429static DECLCALLBACK(int) vmmdevIORAMRegionMap(PPCIDEVICE pPciDev, /*unsigned*/ int iRegion, RTGCPHYS GCPhysAddress, uint32_t cb, PCIADDRESSSPACE enmType)
1430{
1431 int rc;
1432 VMMDevState *pData = PCIDEV_2_VMMDEVSTATE(pPciDev);
1433 LogFlow(("vmmdevR3IORAMRegionMap: iRegion=%d GCPhysAddress=%VGp cb=%#x enmType=%d\n", iRegion, GCPhysAddress, cb, enmType));
1434
1435
1436 Assert(pData->pVMMDevRAMHC != NULL);
1437
1438 memset (pData->pVMMDevRAMHC, 0, sizeof (VMMDevMemory));
1439 pData->pVMMDevRAMHC->u32Size = sizeof (VMMDevMemory);
1440 pData->pVMMDevRAMHC->u32Version = VMMDEV_MEMORY_VERSION;
1441
1442 /*
1443 * VMMDev RAM mapping.
1444 */
1445 if (iRegion == 1 && enmType == PCI_ADDRESS_SPACE_MEM)
1446 {
1447 /*
1448 * Register and lock the RAM.
1449 *
1450 * Windows usually re-initializes the PCI devices, so we have to check whether the memory was
1451 * already registered before trying to do that all over again.
1452 */
1453 PVM pVM = PDMDevHlpGetVM(pPciDev->pDevIns);
1454
1455 if (pData->GCPhysVMMDevRAM)
1456 {
1457 /*
1458 * Relocate the already registered VMMDevRAM.
1459 */
1460 rc = MMR3PhysRelocate(pVM, pData->GCPhysVMMDevRAM, GCPhysAddress, VMMDEV_RAM_SIZE);
1461 if (VBOX_SUCCESS(rc))
1462 {
1463 pData->GCPhysVMMDevRAM = GCPhysAddress;
1464 return VINF_SUCCESS;
1465 }
1466 AssertReleaseMsgFailed(("Failed to relocate VMMDev RAM from %VGp to %VGp! rc=%Vra\n", pData->GCPhysVMMDevRAM, GCPhysAddress, rc));
1467 }
1468 else
1469 {
1470 /*
1471 * Register and lock the VMMDevRAM.
1472 */
1473 /** @todo MM_RAM_FLAGS_MMIO2 seems to be appropriate for a RW memory.
1474 * Need to check. May be a RO memory is enough for the device.
1475 */
1476 rc = MMR3PhysRegister(pVM, pData->pVMMDevRAMHC, GCPhysAddress, VMMDEV_RAM_SIZE, MM_RAM_FLAGS_MMIO2, "VBoxDev");
1477 if (VBOX_SUCCESS(rc))
1478 {
1479 pData->GCPhysVMMDevRAM = GCPhysAddress;
1480 return VINF_SUCCESS;
1481 }
1482 AssertReleaseMsgFailed(("Failed to register VMMDev RAM! rc=%Vra\n", rc));
1483 }
1484 return rc;
1485 }
1486
1487 AssertReleaseMsgFailed(("VMMDev wrong region type: iRegion=%d enmType=%d\n", iRegion, enmType));
1488 return VERR_INTERNAL_ERROR;
1489}
1490
1491
1492/**
1493 * Callback function for mapping a PCI I/O region.
1494 *
1495 * @return VBox status code.
1496 * @param pPciDev Pointer to PCI device. Use pPciDev->pDevIns to get the device instance.
1497 * @param iRegion The region number.
1498 * @param GCPhysAddress Physical address of the region. If iType is PCI_ADDRESS_SPACE_IO, this is an
1499 * I/O port, else it's a physical address.
1500 * This address is *NOT* relative to pci_mem_base like earlier!
1501 * @param enmType One of the PCI_ADDRESS_SPACE_* values.
1502 */
1503static DECLCALLBACK(int) vmmdevIOPortRegionMap(PPCIDEVICE pPciDev, /*unsigned*/ int iRegion, RTGCPHYS GCPhysAddress, uint32_t cb, PCIADDRESSSPACE enmType)
1504{
1505 VMMDevState *pData = PCIDEV_2_VMMDEVSTATE(pPciDev);
1506 int rc = VINF_SUCCESS;
1507
1508 Assert(enmType == PCI_ADDRESS_SPACE_IO);
1509 Assert(iRegion == 0);
1510 AssertMsg(RT_ALIGN(GCPhysAddress, 8) == GCPhysAddress, ("Expected 8 byte alignment. GCPhysAddress=%#x\n", GCPhysAddress));
1511
1512 /*
1513 * Save the base port address to simplify Port offset calculations.
1514 */
1515 pData->PortBase = (RTIOPORT)GCPhysAddress;
1516
1517 /*
1518 * Register our port IO handlers.
1519 */
1520 rc = PDMDevHlpIOPortRegister(pPciDev->pDevIns,
1521 (RTIOPORT)GCPhysAddress + PORT_VMMDEV_REQUEST_OFFSET, 1,
1522 (void*)pData, vmmdevRequestHandler,
1523 NULL, NULL, NULL, "VMMDev Request Handler");
1524 AssertRC(rc);
1525 return rc;
1526}
1527
1528/**
1529 * Queries an interface to the driver.
1530 *
1531 * @returns Pointer to interface.
1532 * @returns NULL if the interface was not supported by the driver.
1533 * @param pInterface Pointer to this interface structure.
1534 * @param enmInterface The requested interface identification.
1535 * @thread Any thread.
1536 */
1537static DECLCALLBACK(void *) vmmdevPortQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface)
1538{
1539 VMMDevState *pData = (VMMDevState*)((uintptr_t)pInterface - RT_OFFSETOF(VMMDevState, Base));
1540 switch (enmInterface)
1541 {
1542 case PDMINTERFACE_BASE:
1543 return &pData->Base;
1544 case PDMINTERFACE_VMMDEV_PORT:
1545 return &pData->Port;
1546#ifdef VBOX_HGCM
1547 case PDMINTERFACE_HGCM_PORT:
1548 return &pData->HGCMPort;
1549#endif
1550 case PDMINTERFACE_LED_PORTS:
1551 /* Currently only for shared folders */
1552 return &pData->SharedFolders.ILeds;
1553 default:
1554 return NULL;
1555 }
1556}
1557
1558/**
1559 * Gets the pointer to the status LED of a unit.
1560 *
1561 * @returns VBox status code.
1562 * @param pInterface Pointer to the interface structure containing the called function pointer.
1563 * @param iLUN The unit which status LED we desire.
1564 * @param ppLed Where to store the LED pointer.
1565 */
1566static DECLCALLBACK(int) vmmdevQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed)
1567{
1568 VMMDevState *pData = (VMMDevState *)( (uintptr_t)pInterface - RT_OFFSETOF(VMMDevState, SharedFolders.ILeds) );
1569 if (iLUN == 0) /* LUN 0 is shared folders */
1570 {
1571 *ppLed = &pData->SharedFolders.Led;
1572 return VINF_SUCCESS;
1573 }
1574 return VERR_PDM_LUN_NOT_FOUND;
1575}
1576
1577/* -=-=-=-=-=- IVMMDevPort -=-=-=-=-=- */
1578
1579/** Converts a VMMDev port interface pointer to a VMMDev state pointer. */
1580#define IVMMDEVPORT_2_VMMDEVSTATE(pInterface) ( (VMMDevState*)((uintptr_t)pInterface - RT_OFFSETOF(VMMDevState, Port)) )
1581
1582
1583/**
1584 * Return the current absolute mouse position in pixels
1585 *
1586 * @returns VBox status code
1587 * @param pAbsX Pointer of result value, can be NULL
1588 * @param pAbsY Pointer of result value, can be NULL
1589 */
1590static DECLCALLBACK(int) vmmdevQueryAbsoluteMouse(PPDMIVMMDEVPORT pInterface, uint32_t *pAbsX, uint32_t *pAbsY)
1591{
1592 VMMDevState *pData = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
1593 if (pAbsX)
1594 *pAbsX = pData->mouseXAbs;
1595 if (pAbsY)
1596 *pAbsY = pData->mouseYAbs;
1597 return VINF_SUCCESS;
1598}
1599
1600/**
1601 * Set the new absolute mouse position in pixels
1602 *
1603 * @returns VBox status code
1604 * @param absX New absolute X position
1605 * @param absY New absolute Y position
1606 */
1607static DECLCALLBACK(int) vmmdevSetAbsoluteMouse(PPDMIVMMDEVPORT pInterface, uint32_t absX, uint32_t absY)
1608{
1609 VMMDevState *pData = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
1610 Log2(("vmmdevSetAbsoluteMouse: settings absolute position to x = %d, y = %d\n", absX, absY));
1611 pData->mouseXAbs = absX;
1612 pData->mouseYAbs = absY;
1613 return VINF_SUCCESS;
1614}
1615
1616/**
1617 * Return the current mouse capability flags
1618 *
1619 * @returns VBox status code
1620 * @param pCapabilities Pointer of result value
1621 */
1622static DECLCALLBACK(int) vmmdevQueryMouseCapabilities(PPDMIVMMDEVPORT pInterface, uint32_t *pCapabilities)
1623{
1624 VMMDevState *pData = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
1625 if (!pCapabilities)
1626 return VERR_INVALID_PARAMETER;
1627 *pCapabilities = pData->mouseCapabilities;
1628 return VINF_SUCCESS;
1629}
1630
1631/**
1632 * Set the current mouse capability flag (host side)
1633 *
1634 * @returns VBox status code
1635 * @param capabilities Capability mask
1636 */
1637static DECLCALLBACK(int) vmmdevSetMouseCapabilities(PPDMIVMMDEVPORT pInterface, uint32_t capabilities)
1638{
1639 VMMDevState *pData = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
1640
1641 bool bCapsChanged = ((capabilities & VMMDEV_MOUSEHOSTWANTSABS)
1642 != (pData->mouseCapabilities & VMMDEV_MOUSEHOSTWANTSABS));
1643
1644 Log(("vmmdevSetMouseCapabilities: bCapsChanged %d\n", bCapsChanged));
1645
1646 if (capabilities & VMMDEV_MOUSEHOSTCANNOTHWPOINTER)
1647 pData->mouseCapabilities |= VMMDEV_MOUSEHOSTCANNOTHWPOINTER;
1648 else
1649 pData->mouseCapabilities &= ~VMMDEV_MOUSEHOSTCANNOTHWPOINTER;
1650
1651 if (capabilities & VMMDEV_MOUSEHOSTWANTSABS)
1652 pData->mouseCapabilities |= VMMDEV_MOUSEHOSTWANTSABS;
1653 else
1654 pData->mouseCapabilities &= ~VMMDEV_MOUSEHOSTWANTSABS;
1655
1656 if (bCapsChanged)
1657 VMMDevNotifyGuest (pData, VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED);
1658
1659 return VINF_SUCCESS;
1660}
1661
1662
1663static DECLCALLBACK(int) vmmdevRequestDisplayChange(PPDMIVMMDEVPORT pInterface, uint32_t xres, uint32_t yres, uint32_t bpp, uint32_t display)
1664{
1665 VMMDevState *pData = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
1666
1667 /* Verify that the new resolution is different and that guest does not yet know about it. */
1668 bool fSameResolution = (!xres || (pData->lastReadDisplayChangeRequest.xres == xres)) &&
1669 (!yres || (pData->lastReadDisplayChangeRequest.yres == yres)) &&
1670 (!bpp || (pData->lastReadDisplayChangeRequest.bpp == bpp)) &&
1671 pData->lastReadDisplayChangeRequest.display == display;
1672
1673 if (!xres && !yres && !bpp)
1674 {
1675 /* Special case of reset video mode. */
1676 fSameResolution = false;
1677 }
1678
1679#ifdef DEBUG_sunlover
1680 Log(("vmmdevRequestDisplayChange: same=%d. new: xres=%d, yres=%d, bpp=%d, display=%d. old: xres=%d, yres=%d, bpp=%d, display=%d.\n",
1681 fSameResolution, xres, yres, bpp, display, pData->lastReadDisplayChangeRequest.xres, pData->lastReadDisplayChangeRequest.yres, pData->lastReadDisplayChangeRequest.bpp, pData->lastReadDisplayChangeRequest.display));
1682#endif /* DEBUG_sunlover */
1683
1684 if (!fSameResolution)
1685 {
1686 LogRel(("VMMDev::SetVideoModeHint: got a video mode hint (%dx%dx%d) at %d\n",
1687 xres, yres, bpp, display));
1688
1689 /* we could validate the information here but hey, the guest can do that as well! */
1690 pData->displayChangeRequest.xres = xres;
1691 pData->displayChangeRequest.yres = yres;
1692 pData->displayChangeRequest.bpp = bpp;
1693 pData->displayChangeRequest.display = display;
1694
1695 /* IRQ so the guest knows what's going on */
1696 VMMDevNotifyGuest (pData, VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST);
1697 }
1698
1699 return VINF_SUCCESS;
1700}
1701
1702static DECLCALLBACK(int) vmmdevRequestSeamlessChange(PPDMIVMMDEVPORT pInterface, bool fEnabled)
1703{
1704 VMMDevState *pData = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
1705
1706 /* Verify that the new resolution is different and that guest does not yet know about it. */
1707 bool fSameMode = (pData->fLastSeamlessEnabled == fEnabled);
1708
1709 Log(("vmmdevRequestSeamlessChange: same=%d. new=%d\n", fSameMode, fEnabled));
1710
1711 if (!fSameMode)
1712 {
1713 /* we could validate the information here but hey, the guest can do that as well! */
1714 pData->fSeamlessEnabled = fEnabled;
1715
1716 /* IRQ so the guest knows what's going on */
1717 VMMDevNotifyGuest (pData, VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST);
1718 }
1719
1720 return VINF_SUCCESS;
1721}
1722
1723static DECLCALLBACK(int) vmmdevSetMemoryBalloon(PPDMIVMMDEVPORT pInterface, uint32_t ulBalloonSize)
1724{
1725 VMMDevState *pData = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
1726
1727 /* Verify that the new resolution is different and that guest does not yet know about it. */
1728 bool fSame = (pData->u32LastMemoryBalloonSize == ulBalloonSize);
1729
1730 Log(("vmmdevSetMemoryBalloon: old=%d. new=%d\n", pData->u32LastMemoryBalloonSize, ulBalloonSize));
1731
1732 if (!fSame)
1733 {
1734 /* we could validate the information here but hey, the guest can do that as well! */
1735 pData->u32MemoryBalloonSize = ulBalloonSize;
1736
1737 /* IRQ so the guest knows what's going on */
1738 VMMDevNotifyGuest (pData, VMMDEV_EVENT_BALLOON_CHANGE_REQUEST);
1739 }
1740
1741 return VINF_SUCCESS;
1742}
1743
1744static DECLCALLBACK(int) vmmdevSetStatisticsInterval(PPDMIVMMDEVPORT pInterface, uint32_t ulStatInterval)
1745{
1746 VMMDevState *pData = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
1747
1748 /* Verify that the new resolution is different and that guest does not yet know about it. */
1749 bool fSame = (pData->u32LastStatIntervalSize == ulStatInterval);
1750
1751 Log(("vmmdevSetStatisticsInterval: old=%d. new=%d\n", pData->u32LastStatIntervalSize, ulStatInterval));
1752
1753 if (!fSame)
1754 {
1755 /* we could validate the information here but hey, the guest can do that as well! */
1756 pData->u32StatIntervalSize = ulStatInterval;
1757
1758 /* IRQ so the guest knows what's going on */
1759 VMMDevNotifyGuest (pData, VMMDEV_EVENT_STATISTICS_INTERVAL_CHANGE_REQUEST);
1760 }
1761
1762 return VINF_SUCCESS;
1763}
1764
1765
1766static DECLCALLBACK(int) vmmdevSetCredentials(PPDMIVMMDEVPORT pInterface, const char *pszUsername,
1767 const char *pszPassword, const char *pszDomain,
1768 uint32_t u32Flags)
1769{
1770 VMMDevState *pData = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
1771
1772 /* logon mode? */
1773 if (u32Flags & VMMDEV_SETCREDENTIALS_GUESTLOGON)
1774 {
1775 /* memorize the data */
1776 strcpy(pData->credentialsLogon.szUserName, pszUsername);
1777 strcpy(pData->credentialsLogon.szPassword, pszPassword);
1778 strcpy(pData->credentialsLogon.szDomain, pszDomain);
1779 pData->credentialsLogon.fAllowInteractiveLogon = !(u32Flags & VMMDEV_SETCREDENTIALS_NOLOCALLOGON);
1780 }
1781 /* credentials verification mode? */
1782 else if (u32Flags & VMMDEV_SETCREDENTIALS_JUDGE)
1783 {
1784 /* memorize the data */
1785 strcpy(pData->credentialsJudge.szUserName, pszUsername);
1786 strcpy(pData->credentialsJudge.szPassword, pszPassword);
1787 strcpy(pData->credentialsJudge.szDomain, pszDomain);
1788
1789 VMMDevNotifyGuest (pData, VMMDEV_EVENT_JUDGE_CREDENTIALS);
1790 }
1791 else
1792 return VERR_INVALID_PARAMETER;
1793
1794 return VINF_SUCCESS;
1795}
1796
1797/**
1798 * Notification from the Display. Especially useful when
1799 * acceleration is disabled after a video mode change.
1800 *
1801 * @param fEnable Current acceleration status.
1802 */
1803static DECLCALLBACK(void) vmmdevVBVAChange(PPDMIVMMDEVPORT pInterface, bool fEnabled)
1804{
1805 VMMDevState *pData = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
1806
1807 Log(("vmmdevVBVAChange: fEnabled = %d\n", fEnabled));
1808
1809 if (pData)
1810 {
1811 pData->u32VideoAccelEnabled = fEnabled;
1812 }
1813
1814 return;
1815}
1816
1817
1818/* -=-=-=-=-=- IHGCMPort -=-=-=-=-=- */
1819
1820/** Converts a VMMDev port interface pointer to a VMMDev state pointer. */
1821#define IHGCMPORT_2_VMMDEVSTATE(pInterface) ( (VMMDevState*)((uintptr_t)pInterface - RT_OFFSETOF(VMMDevState, HGCMPort)) )
1822
1823
1824
1825#define VMMDEV_SSM_VERSION 5
1826
1827/**
1828 * Saves a state of the VMM device.
1829 *
1830 * @returns VBox status code.
1831 * @param pDevIns The device instance.
1832 * @param pSSMHandle The handle to save the state to.
1833 */
1834static DECLCALLBACK(int) vmmdevSaveState(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle)
1835{
1836 VMMDevState *pData = PDMINS2DATA(pDevIns, VMMDevState*);
1837 SSMR3PutU32(pSSMHandle, pData->hypervisorSize);
1838 SSMR3PutU32(pSSMHandle, pData->mouseCapabilities);
1839 SSMR3PutU32(pSSMHandle, pData->mouseXAbs);
1840 SSMR3PutU32(pSSMHandle, pData->mouseYAbs);
1841
1842 SSMR3PutBool(pSSMHandle, pData->fNewGuestFilterMask);
1843 SSMR3PutU32(pSSMHandle, pData->u32NewGuestFilterMask);
1844 SSMR3PutU32(pSSMHandle, pData->u32GuestFilterMask);
1845 SSMR3PutU32(pSSMHandle, pData->u32HostEventFlags);
1846 // here be dragons (probably)
1847// SSMR3PutBool(pSSMHandle, pData->pVMMDevRAMHC->V.V1_04.fHaveEvents);
1848 SSMR3PutMem(pSSMHandle, &pData->pVMMDevRAMHC->V, sizeof (pData->pVMMDevRAMHC->V));
1849
1850 SSMR3PutMem(pSSMHandle, &pData->guestInfo, sizeof (pData->guestInfo));
1851 SSMR3PutU32(pSSMHandle, pData->fu32AdditionsOk);
1852 SSMR3PutU32(pSSMHandle, pData->u32VideoAccelEnabled);
1853
1854 SSMR3PutU32(pSSMHandle, pData->guestCaps);
1855
1856#ifdef VBOX_HGCM
1857 vmmdevHGCMSaveState (pData, pSSMHandle);
1858#endif /* VBOX_HGCM */
1859
1860 return VINF_SUCCESS;
1861}
1862
1863/**
1864 * Loads the saved VMM device state.
1865 *
1866 * @returns VBox status code.
1867 * @param pDevIns The device instance.
1868 * @param pSSMHandle The handle to the saved state.
1869 * @param u32Version The data unit version number.
1870 */
1871static DECLCALLBACK(int) vmmdevLoadState(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle, uint32_t u32Version)
1872{
1873 VMMDevState *pData = PDMINS2DATA(pDevIns, VMMDevState*);
1874 if (u32Version != VMMDEV_SSM_VERSION)
1875 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
1876 SSMR3GetU32(pSSMHandle, &pData->hypervisorSize);
1877 SSMR3GetU32(pSSMHandle, &pData->mouseCapabilities);
1878 SSMR3GetU32(pSSMHandle, &pData->mouseXAbs);
1879 SSMR3GetU32(pSSMHandle, &pData->mouseYAbs);
1880
1881 SSMR3GetBool(pSSMHandle, &pData->fNewGuestFilterMask);
1882 SSMR3GetU32(pSSMHandle, &pData->u32NewGuestFilterMask);
1883 SSMR3GetU32(pSSMHandle, &pData->u32GuestFilterMask);
1884 SSMR3GetU32(pSSMHandle, &pData->u32HostEventFlags);
1885// SSMR3GetBool(pSSMHandle, &pData->pVMMDevRAMHC->fHaveEvents);
1886 // here be dragons (probably)
1887 SSMR3GetMem(pSSMHandle, &pData->pVMMDevRAMHC->V, sizeof (pData->pVMMDevRAMHC->V));
1888
1889 SSMR3GetMem(pSSMHandle, &pData->guestInfo, sizeof (pData->guestInfo));
1890 SSMR3GetU32(pSSMHandle, &pData->fu32AdditionsOk);
1891 SSMR3GetU32(pSSMHandle, &pData->u32VideoAccelEnabled);
1892
1893 SSMR3GetU32(pSSMHandle, &pData->guestCaps);
1894
1895#ifdef VBOX_HGCM
1896 vmmdevHGCMLoadState (pData, pSSMHandle);
1897#endif /* VBOX_HGCM */
1898
1899 /*
1900 * On a resume, we send the capabilities changed message so
1901 * that listeners can sync their state again
1902 */
1903 Log(("vmmdevLoadState: capabilities changed (%x), informing connector\n", pData->mouseCapabilities));
1904 if (pData->pDrv)
1905 pData->pDrv->pfnUpdateMouseCapabilities(pData->pDrv, pData->mouseCapabilities);
1906
1907 /* Reestablish the acceleration status. */
1908 if ( pData->u32VideoAccelEnabled
1909 && pData->pDrv)
1910 {
1911 pData->pDrv->pfnVideoAccelEnable (pData->pDrv, !!pData->u32VideoAccelEnabled, &pData->pVMMDevRAMHC->vbvaMemory);
1912 }
1913
1914 if (pData->fu32AdditionsOk)
1915 {
1916 LogRel(("Guest Additions information report: additionsVersion = 0x%08X osType = 0x%08X\n",
1917 pData->guestInfo.additionsVersion,
1918 pData->guestInfo.osType));
1919 if (pData->pDrv)
1920 pData->pDrv->pfnUpdateGuestVersion(pData->pDrv, &pData->guestInfo);
1921 }
1922 if (pData->pDrv)
1923 pData->pDrv->pfnUpdateGuestCapabilities(pData->pDrv, pData->guestCaps);
1924
1925 return VINF_SUCCESS;
1926}
1927
1928/**
1929 * Load state done callback. Notify guest of restore event.
1930 *
1931 * @returns VBox status code.
1932 * @param pDevIns The device instance.
1933 * @param pSSMHandle The handle to the saved state.
1934 */
1935static DECLCALLBACK(int) vmmdevLoadStateDone(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle)
1936{
1937 VMMDevState *pData = PDMINS2DATA(pDevIns, VMMDevState*);
1938
1939#ifdef VBOX_HGCM
1940 vmmdevHGCMLoadStateDone (pData, pSSMHandle);
1941#endif /* VBOX_HGCM */
1942
1943 VMMDevNotifyGuest (pData, VMMDEV_EVENT_RESTORED);
1944
1945 return VINF_SUCCESS;
1946}
1947
1948/**
1949 * Construct a device instance for a VM.
1950 *
1951 * @returns VBox status.
1952 * @param pDevIns The device instance data.
1953 * If the registration structure is needed, pDevIns->pDevReg points to it.
1954 * @param iInstance Instance number. Use this to figure out which registers and such to use.
1955 * The device number is also found in pDevIns->iInstance, but since it's
1956 * likely to be freqently used PDM passes it as parameter.
1957 * @param pCfgHandle Configuration node handle for the device. Use this to obtain the configuration
1958 * of the device instance. It's also found in pDevIns->pCfgHandle, but like
1959 * iInstance it's expected to be used a bit in this function.
1960 */
1961static DECLCALLBACK(int) vmmdevConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfgHandle)
1962{
1963 int rc;
1964 VMMDevState *pData = PDMINS2DATA(pDevIns, VMMDevState *);
1965
1966 Assert(iInstance == 0);
1967
1968 /*
1969 * Validate and read the configuration.
1970 */
1971 if (!CFGMR3AreValuesValid(pCfgHandle, "GetHostTimeDisabled\0BackdoorLogDisabled\0"))
1972 return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES;
1973
1974 rc = CFGMR3QueryBool(pCfgHandle, "GetHostTimeDisabled", &pData->fGetHostTimeDisabled);
1975 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
1976 pData->fGetHostTimeDisabled = false;
1977 else if (VBOX_FAILURE(rc))
1978 return PDMDEV_SET_ERROR(pDevIns, rc,
1979 N_("Configuration error: Failed querying \"GetHostTimeDisabled\" as a boolean"));
1980
1981 rc = CFGMR3QueryBool(pCfgHandle, "BackdoorLogDisabled", &pData->fBackdoorLogDisabled);
1982 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
1983 pData->fBackdoorLogDisabled = false;
1984 else if (VBOX_FAILURE(rc))
1985 return PDMDEV_SET_ERROR(pDevIns, rc,
1986 N_("Configuration error: Failed querying \"BackdoorLogDisabled\" as a boolean"));
1987
1988 /*
1989 * Initialize data (most of it anyway).
1990 */
1991 /* Save PDM device instance data for future reference. */
1992 pData->pDevIns = pDevIns;
1993
1994 /* PCI vendor, just a free bogus value */
1995 pData->dev.config[0x00] = 0xee;
1996 pData->dev.config[0x01] = 0x80;
1997 /* device ID */
1998 pData->dev.config[0x02] = 0xfe;
1999 pData->dev.config[0x03] = 0xca;
2000 /* class sub code (other type of system peripheral) */
2001 pData->dev.config[0x0a] = 0x80;
2002 /* class base code (base system peripheral) */
2003 pData->dev.config[0x0b] = 0x08;
2004 /* header type */
2005 pData->dev.config[0x0e] = 0x00;
2006 /* interrupt on pin 0 */
2007 pData->dev.config[0x3d] = 0x01;
2008
2009 /*
2010 * Register the backdoor logging port
2011 */
2012 rc = PDMDevHlpIOPortRegister(pDevIns, RTLOG_DEBUG_PORT, 1, NULL, vmmdevBackdoorLog, NULL, NULL, NULL, "VMMDev backdoor logging");
2013 AssertRCReturn(rc, rc);
2014
2015#ifdef TIMESYNC_BACKDOOR
2016 /*
2017 * Alternative timesync source (temporary!)
2018 */
2019 rc = PDMDevHlpIOPortRegister(pDevIns, 0x505, 1, NULL, vmmdevTimesyncBackdoorWrite, vmmdevTimesyncBackdoorRead, NULL, NULL, "VMMDev timesync backdoor");
2020 AssertRCReturn(rc, rc);
2021#endif
2022
2023 /*
2024 * Register the PCI device.
2025 */
2026 rc = PDMDevHlpPCIRegister(pDevIns, &pData->dev);
2027 if (VBOX_FAILURE(rc))
2028 return rc;
2029 if (pData->dev.devfn == 32 || iInstance != 0)
2030 Log(("!!WARNING!!: pData->dev.devfn=%d (ignore if testcase or no started by Main)\n", pData->dev.devfn));
2031 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0, 0x20, PCI_ADDRESS_SPACE_IO, vmmdevIOPortRegionMap);
2032 if (VBOX_FAILURE(rc))
2033 return rc;
2034 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 1, VMMDEV_RAM_SIZE, PCI_ADDRESS_SPACE_MEM, vmmdevIORAMRegionMap);
2035 if (VBOX_FAILURE(rc))
2036 return rc;
2037
2038 /*
2039 * Interfaces
2040 */
2041 /* Base */
2042 pData->Base.pfnQueryInterface = vmmdevPortQueryInterface;
2043
2044 /* VMMDev port */
2045 pData->Port.pfnQueryAbsoluteMouse = vmmdevQueryAbsoluteMouse;
2046 pData->Port.pfnSetAbsoluteMouse = vmmdevSetAbsoluteMouse;
2047 pData->Port.pfnQueryMouseCapabilities = vmmdevQueryMouseCapabilities;
2048 pData->Port.pfnSetMouseCapabilities = vmmdevSetMouseCapabilities;
2049 pData->Port.pfnRequestDisplayChange = vmmdevRequestDisplayChange;
2050 pData->Port.pfnSetCredentials = vmmdevSetCredentials;
2051 pData->Port.pfnVBVAChange = vmmdevVBVAChange;
2052 pData->Port.pfnRequestSeamlessChange = vmmdevRequestSeamlessChange;
2053 pData->Port.pfnSetMemoryBalloon = vmmdevSetMemoryBalloon;
2054 pData->Port.pfnSetStatisticsInterval = vmmdevSetStatisticsInterval;
2055
2056 /* Shared folder LED */
2057 pData->SharedFolders.Led.u32Magic = PDMLED_MAGIC;
2058 pData->SharedFolders.ILeds.pfnQueryStatusLed = vmmdevQueryStatusLed;
2059
2060#ifdef VBOX_HGCM
2061 /* HGCM port */
2062 pData->HGCMPort.pfnCompleted = hgcmCompleted;
2063#endif
2064
2065 /*
2066 * Get the corresponding connector interface
2067 */
2068 rc = PDMDevHlpDriverAttach(pDevIns, 0, &pData->Base, &pData->pDrvBase, "VMM Driver Port");
2069 if (VBOX_SUCCESS(rc))
2070 {
2071 pData->pDrv = (PPDMIVMMDEVCONNECTOR)pData->pDrvBase->pfnQueryInterface(pData->pDrvBase, PDMINTERFACE_VMMDEV_CONNECTOR);
2072 if (!pData->pDrv)
2073 AssertMsgFailedReturn(("LUN #0 doesn't have a VMMDev connector interface!\n"), VERR_PDM_MISSING_INTERFACE);
2074#ifdef VBOX_HGCM
2075 pData->pHGCMDrv = (PPDMIHGCMCONNECTOR)pData->pDrvBase->pfnQueryInterface(pData->pDrvBase, PDMINTERFACE_HGCM_CONNECTOR);
2076 if (!pData->pHGCMDrv)
2077 {
2078 Log(("LUN #0 doesn't have a HGCM connector interface, HGCM is not supported. rc=%Vrc\n", rc));
2079 /* this is not actually an error, just means that there is no support for HGCM */
2080 }
2081#endif
2082 }
2083 else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
2084 {
2085 Log(("%s/%d: warning: no driver attached to LUN #0!\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
2086 rc = VINF_SUCCESS;
2087 }
2088 else
2089 AssertMsgFailedReturn(("Failed to attach LUN #0! rc=%Vrc\n", rc), rc);
2090
2091 /*
2092 * Attach status driver for shared folders (optional).
2093 */
2094 PPDMIBASE pBase;
2095 rc = PDMDevHlpDriverAttach(pDevIns, PDM_STATUS_LUN, &pData->Base, &pBase, "Status Port");
2096 if (VBOX_SUCCESS(rc))
2097 pData->SharedFolders.pLedsConnector = (PPDMILEDCONNECTORS)
2098 pBase->pfnQueryInterface(pBase, PDMINTERFACE_LED_CONNECTORS);
2099 else if (rc != VERR_PDM_NO_ATTACHED_DRIVER)
2100 {
2101 AssertMsgFailed(("Failed to attach to status driver. rc=%Vrc\n", rc));
2102 return rc;
2103 }
2104
2105 /*
2106 * Register saved state and init the HGCM CmdList critsect.
2107 */
2108 rc = PDMDevHlpSSMRegister(pDevIns, "VMMDev", iInstance, VMMDEV_SSM_VERSION, sizeof(*pData),
2109 NULL, vmmdevSaveState, NULL,
2110 NULL, vmmdevLoadState, vmmdevLoadStateDone);
2111 AssertRCReturn(rc, rc);
2112
2113#ifdef VBOX_HGCM
2114 pData->pHGCMCmdList = NULL;
2115 rc = RTCritSectInit(&pData->critsectHGCMCmdList);
2116 AssertRCReturn(rc, rc);
2117 pData->u32HGCMEnabled = 0;
2118#endif /* VBOX_HGCM */
2119
2120 /*
2121 * Allocate the VMMDev RAM region.
2122 */
2123 /** @todo freeing of the RAM. */
2124 rc = SUPPageAlloc(VMMDEV_RAM_SIZE >> PAGE_SHIFT, (void **)&pData->pVMMDevRAMHC);
2125 AssertMsgRCReturn(rc, ("VMMDev SUPPageAlloc(%#x,) -> %Vrc\n", VMMDEV_RAM_SIZE, rc), rc);
2126
2127 /* initialize the VMMDev memory */
2128 pData->pVMMDevRAMHC->u32Size = sizeof (VMMDevMemory);
2129 pData->pVMMDevRAMHC->u32Version = VMMDEV_MEMORY_VERSION;
2130
2131 return rc;
2132}
2133
2134/**
2135 * Reset notification.
2136 *
2137 * @returns VBox status.
2138 * @param pDrvIns The driver instance data.
2139 */
2140static DECLCALLBACK(void) vmmdevReset(PPDMDEVINS pDevIns)
2141{
2142 VMMDevState *pData = PDMINS2DATA(pDevIns, VMMDevState*);
2143 /*
2144 * Reset the mouse integration feature bit
2145 */
2146 if (pData->mouseCapabilities & (VMMDEV_MOUSEGUESTWANTSABS|VMMDEV_MOUSEGUESTNEEDSHOSTCUR))
2147 {
2148 pData->mouseCapabilities &= ~VMMDEV_MOUSEGUESTWANTSABS;
2149 /* notify the connector */
2150 Log(("vmmdevReset: capabilities changed (%x), informing connector\n", pData->mouseCapabilities));
2151 pData->pDrv->pfnUpdateMouseCapabilities(pData->pDrv, pData->mouseCapabilities);
2152 }
2153
2154 pData->hypervisorSize = 0;
2155
2156 pData->u32HostEventFlags = 0;
2157
2158 if (pData->pVMMDevRAMHC)
2159 {
2160 /* re-initialize the VMMDev memory */
2161 memset (pData->pVMMDevRAMHC, 0, VMMDEV_RAM_SIZE);
2162 pData->pVMMDevRAMHC->u32Size = sizeof (VMMDevMemory);
2163 pData->pVMMDevRAMHC->u32Version = VMMDEV_MEMORY_VERSION;
2164 }
2165
2166 /* credentials have to go away */
2167 memset(pData->credentialsLogon.szUserName, '\0', VMMDEV_CREDENTIALS_STRLEN);
2168 memset(pData->credentialsLogon.szPassword, '\0', VMMDEV_CREDENTIALS_STRLEN);
2169 memset(pData->credentialsLogon.szDomain, '\0', VMMDEV_CREDENTIALS_STRLEN);
2170 memset(pData->credentialsJudge.szUserName, '\0', VMMDEV_CREDENTIALS_STRLEN);
2171 memset(pData->credentialsJudge.szPassword, '\0', VMMDEV_CREDENTIALS_STRLEN);
2172 memset(pData->credentialsJudge.szDomain, '\0', VMMDEV_CREDENTIALS_STRLEN);
2173
2174 /* Reset means that additions will report again. */
2175 pData->fu32AdditionsOk = false;
2176 memset (&pData->guestInfo, 0, sizeof (pData->guestInfo));
2177 pData->guestCaps = 0;
2178
2179 memset (&pData->lastReadDisplayChangeRequest, 0, sizeof (pData->lastReadDisplayChangeRequest));
2180
2181 /* disable seamless mode */
2182 pData->fLastSeamlessEnabled = false;
2183
2184 /* disabled memory ballooning */
2185 pData->u32LastMemoryBalloonSize = 0;
2186
2187 /* disabled statistics updating */
2188 pData->u32LastStatIntervalSize = 0;
2189
2190 /* Clear the event variables.
2191 *
2192 * Note: The pData->u32HostEventFlags is not cleared.
2193 * It is designed that way so host events do not
2194 * depend on guest resets.
2195 */
2196 pData->u32GuestFilterMask = 0;
2197 pData->u32NewGuestFilterMask = 0;
2198 pData->fNewGuestFilterMask = 0;
2199}
2200
2201
2202/**
2203 * The device registration structure.
2204 */
2205extern "C" const PDMDEVREG g_DeviceVMMDev =
2206{
2207 /* u32Version */
2208 PDM_DEVREG_VERSION,
2209 /* szDeviceName */
2210 "VMMDev",
2211 /* szGCMod */
2212 "",
2213 /* szR0Mod */
2214 "",
2215 /* pszDescription */
2216 "VirtualBox VMM Device\n",
2217 /* fFlags */
2218 PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GUEST_BITS_32,
2219 /* fClass */
2220 PDM_DEVREG_CLASS_VMM_DEV,
2221 /* cMaxInstances */
2222 1,
2223 /* cbInstance */
2224 sizeof(VMMDevState),
2225 /* pfnConstruct */
2226 vmmdevConstruct,
2227 /* pfnDestruct */
2228 NULL,
2229 /* pfnRelocate */
2230 NULL,
2231 /* pfnIOCtl */
2232 NULL,
2233 /* pfnPowerOn */
2234 NULL,
2235 /* pfnReset */
2236 vmmdevReset,
2237 /* pfnSuspend */
2238 NULL,
2239 /* pfnResume */
2240 NULL,
2241 /* pfnAttach */
2242 NULL,
2243 /* pfnDetach */
2244 NULL,
2245 /* pfnQueryInterface. */
2246 NULL
2247};
2248#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
2249
Note: See TracBrowser for help on using the repository browser.

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