VirtualBox

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

Last change on this file since 1 was 1, checked in by vboxsync, 55 years ago

import

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