VirtualBox

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

Last change on this file since 229 was 211, checked in by vboxsync, 18 years ago

Use the special backdoor logging group for backdoor logging (rest is too noisy)

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