~ubuntu-branches/ubuntu/trusty/virtualbox-ose/trusty

« back to all changes in this revision

Viewing changes to src/VBox/Devices/VMMDev/VBoxDev.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2009-12-18 16:44:29 UTC
  • mfrom: (0.3.3 upstream) (0.4.6 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091218164429-jd34ccexpv5na11a
Tags: 3.1.2-dfsg-1ubuntu1
* Merge from Debian unstable (LP: #498219), remaining changes:
  - Disable update action
    - debian/patches/u01-disable-update-action.dpatch
  - VirtualBox should go in Accessories, not in System tools (LP: #288590)
    - debian/virtualbox-ose-qt.files/virtualbox-ose.desktop
  - Add Apport hook
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Add Launchpad integration
    - debian/control
    - debian/lpi-bug.xpm
    - debian/patches/u02-lp-integration.dpatch
* Fixes the following bugs:
  - Kernel module fails to build with Linux >= 2.6.32 (LP: #474625)
  - X.Org drivers need to be rebuilt against X-Server 1.7 (LP: #495935)
  - The *-source packages try to build the kernel modules even though the
    kernel headers aren't available (LP: #473334)
* Replace *-source packages with transitional packages for *-dkms.
* Adapt u01-disable-update-action.dpatch and u02-lp-integration.dpatch for
  new upstream version.

Show diffs side-by-side

added added

removed removed

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