HGCMInternal.cpp revision 5c55eb4028136efa847b9c86d19bac3fc62406fc
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync/* $Revision$ */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync/** @file
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * VBoxGuestLib - Host-Guest Communication Manager internal functions, implemented by VBoxGuest
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync/*
c98fb3e16fcd571a790eab772c0c66173d225205vboxsync * Copyright (C) 2006-2007 Oracle Corporation
c98fb3e16fcd571a790eab772c0c66173d225205vboxsync *
c98fb3e16fcd571a790eab772c0c66173d225205vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
c98fb3e16fcd571a790eab772c0c66173d225205vboxsync * available from http://www.virtualbox.org. This file is free software;
c98fb3e16fcd571a790eab772c0c66173d225205vboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync *
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * The contents of this file may alternatively be used under the terms
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * of the Common Development and Distribution License Version 1.0
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution, in which case the provisions of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * CDDL are applicable instead of those of the GPL.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync *
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * You may elect to license modified versions of this file under the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * terms and conditions of either the GPL or the CDDL or both.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync/* Entire file is ifdef'ed with VBGL_VBOXGUEST */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#ifdef VBGL_VBOXGUEST
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync/*******************************************************************************
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync* Header Files *
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync*******************************************************************************/
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#define LOG_GROUP LOG_GROUP_HGCM
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#include "VBGLInternal.h"
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#include <iprt/alloca.h>
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#include <iprt/asm.h>
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#include <iprt/assert.h>
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#include <iprt/mem.h>
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#include <iprt/memobj.h>
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#include <iprt/string.h>
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#include <iprt/thread.h>
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#include <iprt/time.h>
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync/*******************************************************************************
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync* Defined Constants And Macros *
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync*******************************************************************************/
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync/** The max parameter buffer size for a user request. */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#define VBGLR0_MAX_HGCM_USER_PARM (24*_1M)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync/** The max parameter buffer size for a kernel request. */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#define VBGLR0_MAX_HGCM_KERNEL_PARM (16*_1M)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#ifdef RT_OS_LINUX
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync/** Linux needs to use bounce buffers since RTR0MemObjLockUser has unwanted
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * side effects. */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync# define USE_BOUNCE_BUFFERS
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#endif
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync/*******************************************************************************
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync* Structures and Typedefs *
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync*******************************************************************************/
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync/**
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * Lock info structure used by VbglR0HGCMInternalCall and its helpers.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsyncstruct VbglR0ParmInfo
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync{
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync uint32_t cLockBufs;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync struct
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync uint32_t iParm;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync RTR0MEMOBJ hObj;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#ifdef USE_BOUNCE_BUFFERS
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync void *pvSmallBuf;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#endif
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync } aLockBufs[10];
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync};
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync/* These functions can be only used by VBoxGuest. */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsyncDECLVBGL(int) VbglR0HGCMInternalConnect (VBoxGuestHGCMConnectInfo *pConnectInfo,
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync PFNVBGLHGCMCALLBACK pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync{
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync VMMDevHGCMConnect *pHGCMConnect;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync int rc;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (!pConnectInfo || !pfnAsyncCallback)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync return VERR_INVALID_PARAMETER;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pHGCMConnect = NULL;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /* Allocate request */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync rc = VbglGRAlloc ((VMMDevRequestHeader **)&pHGCMConnect, sizeof (VMMDevHGCMConnect), VMMDevReq_HGCMConnect);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (RT_SUCCESS(rc))
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /* Initialize request memory */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pHGCMConnect->header.fu32Flags = 0;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync memcpy (&pHGCMConnect->loc, &pConnectInfo->Loc, sizeof (HGCMServiceLocation));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pHGCMConnect->u32ClientID = 0;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /* Issue request */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync rc = VbglGRPerform (&pHGCMConnect->header.header);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (RT_SUCCESS(rc))
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /* Check if host decides to process the request asynchronously. */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (rc == VINF_HGCM_ASYNC_EXECUTE)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /* Wait for request completion interrupt notification from host */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pfnAsyncCallback (&pHGCMConnect->header, pvAsyncData, u32AsyncData);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pConnectInfo->result = pHGCMConnect->header.result;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (RT_SUCCESS (pConnectInfo->result))
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pConnectInfo->u32ClientID = pHGCMConnect->u32ClientID;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync VbglGRFree (&pHGCMConnect->header.header);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync return rc;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync}
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsyncDECLR0VBGL(int) VbglR0HGCMInternalDisconnect (VBoxGuestHGCMDisconnectInfo *pDisconnectInfo,
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync PFNVBGLHGCMCALLBACK pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync{
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync VMMDevHGCMDisconnect *pHGCMDisconnect;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync int rc;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (!pDisconnectInfo || !pfnAsyncCallback)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync return VERR_INVALID_PARAMETER;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pHGCMDisconnect = NULL;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /* Allocate request */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync rc = VbglGRAlloc ((VMMDevRequestHeader **)&pHGCMDisconnect, sizeof (VMMDevHGCMDisconnect), VMMDevReq_HGCMDisconnect);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (RT_SUCCESS(rc))
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /* Initialize request memory */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pHGCMDisconnect->header.fu32Flags = 0;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pHGCMDisconnect->u32ClientID = pDisconnectInfo->u32ClientID;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /* Issue request */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync rc = VbglGRPerform (&pHGCMDisconnect->header.header);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (RT_SUCCESS(rc))
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /* Check if host decides to process the request asynchronously. */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (rc == VINF_HGCM_ASYNC_EXECUTE)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /* Wait for request completion interrupt notification from host */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pfnAsyncCallback (&pHGCMDisconnect->header, pvAsyncData, u32AsyncData);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pDisconnectInfo->result = pHGCMDisconnect->header.result;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync VbglGRFree (&pHGCMDisconnect->header.header);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync return rc;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync}
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync/**
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * Preprocesses the HGCM call, validating and locking/buffering parameters.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync *
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * @returns VBox status code.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync *
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * @param pCallInfo The call info.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * @param cbCallInfo The size of the call info structure.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * @param fIsUser Is it a user request or kernel request.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * @param pcbExtra Where to return the extra request space needed for
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * physical page lists.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsyncstatic int vbglR0HGCMInternalPreprocessCall(VBoxGuestHGCMCallInfo const *pCallInfo, uint32_t cbCallInfo,
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync bool fIsUser, struct VbglR0ParmInfo *pParmInfo, size_t *pcbExtra)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync{
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync HGCMFunctionParameter const *pSrcParm = VBOXGUEST_HGCM_CALL_PARMS(pCallInfo);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync uint32_t cParms = pCallInfo->cParms;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync uint32_t iParm;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync uint32_t cb;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /*
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * Lock down the any linear buffers so we can get their addresses
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * and figure out how much extra storage we need for page lists.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync *
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * Note! With kernel mode users we can be assertive. For user mode users
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * we should just (debug) log it and fail without any fanfare.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync *pcbExtra = 0;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pParmInfo->cLockBufs = 0;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync for (iParm = 0; iParm < cParms; iParm++, pSrcParm++)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync switch (pSrcParm->type)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_32bit:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync Log4(("GstHGCMCall: parm=%u type=32bit: %#010x\n", iParm, pSrcParm->u.value32));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync break;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_64bit:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync Log4(("GstHGCMCall: parm=%u type=64bit: %#018x\n", iParm, pSrcParm->u.value64));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync break;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_PageList:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (fIsUser)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync return VERR_INVALID_PARAMETER;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync cb = pSrcParm->u.PageList.size;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (cb)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync uint32_t off = pSrcParm->u.PageList.offset;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync HGCMPageListInfo *pPgLst;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync uint32_t cPages;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync uint32_t u32;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync AssertMsgReturn(cb <= VBGLR0_MAX_HGCM_KERNEL_PARM, ("%#x > %#x\n", cb, VBGLR0_MAX_HGCM_KERNEL_PARM),
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync VERR_OUT_OF_RANGE);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync AssertMsgReturn( off >= pCallInfo->cParms * sizeof(HGCMFunctionParameter)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync && off <= cbCallInfo - sizeof(HGCMPageListInfo),
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync ("offset=%#x cParms=%#x cbCallInfo=%#x\n", off, pCallInfo->cParms, cbCallInfo),
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync VERR_INVALID_PARAMETER);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pPgLst = (HGCMPageListInfo *)((uint8_t *)pCallInfo + off);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync cPages = pPgLst->cPages;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync u32 = RT_OFFSETOF(HGCMPageListInfo, aPages[cPages]) + off;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync AssertMsgReturn(u32 <= cbCallInfo,
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync ("u32=%#x (cPages=%#x offset=%#x) cbCallInfo=%#x\n", u32, cPages, off, cbCallInfo),
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync VERR_INVALID_PARAMETER);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync AssertMsgReturn(pPgLst->offFirstPage < PAGE_SIZE, ("#x\n", pPgLst->offFirstPage), VERR_INVALID_PARAMETER);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync u32 = RT_ALIGN_32(pPgLst->offFirstPage + cb, PAGE_SIZE) >> PAGE_SHIFT;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync AssertMsgReturn(cPages == u32, ("cPages=%#x u32=%#x\n", cPages, u32), VERR_INVALID_PARAMETER);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync AssertMsgReturn(VBOX_HGCM_F_PARM_ARE_VALID(pPgLst->flags), ("%#x\n", pPgLst->flags), VERR_INVALID_PARAMETER);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync Log4(("GstHGCMCall: parm=%u type=pglst: cb=%#010x cPgs=%u offPg0=%#x flags=%#x\n",
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync iParm, cb, cPages, pPgLst->offFirstPage, pPgLst->flags));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync u32 = cPages;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync while (u32-- > 0)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync Log4(("GstHGCMCall: pg#%u=%RHp\n", u32, pPgLst->aPages[u32]));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync AssertMsgReturn(!(pPgLst->aPages[u32] & (PAGE_OFFSET_MASK | UINT64_C(0xfff0000000000000))),
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync ("pg#%u=%RHp\n", u32, pPgLst->aPages[u32]),
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync VERR_INVALID_PARAMETER);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync *pcbExtra += RT_OFFSETOF(HGCMPageListInfo, aPages[pPgLst->cPages]);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync else
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync Log4(("GstHGCMCall: parm=%u type=pglst: cb=0\n", iParm));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync break;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_LinAddr_Locked_In:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_LinAddr_Locked_Out:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_LinAddr_Locked:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (fIsUser)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync return VERR_INVALID_PARAMETER;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /* always perform it as !VBGLR0_CAN_USE_PHYS_PAGE_LIST() since otherwise
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * we end up creating a RTR0MEMOBJ and doing page lock again, which leads to undefined behavior and possible BSOD on Win */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync //if (!VBGLR0_CAN_USE_PHYS_PAGE_LIST())
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync cb = pSrcParm->u.Pointer.size;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync AssertMsgReturn(cb <= VBGLR0_MAX_HGCM_KERNEL_PARM, ("%#x > %#x\n", cb, VBGLR0_MAX_HGCM_KERNEL_PARM),
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync VERR_OUT_OF_RANGE);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (cb != 0)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync Log4(("GstHGCMCall: parm=%u type=%#x: cb=%#010x pv=%p\n",
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync iParm, pSrcParm->type, cb, pSrcParm->u.Pointer.u.linearAddr));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync else
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync Log4(("GstHGCMCall: parm=%u type=%#x: cb=0\n", iParm, pSrcParm->type));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync break;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /* fall thru */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_LinAddr_In:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_LinAddr_Out:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_LinAddr:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync cb = pSrcParm->u.Pointer.size;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (cb != 0)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#ifdef USE_BOUNCE_BUFFERS
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync void *pvSmallBuf = NULL;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#endif
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync uint32_t iLockBuf = pParmInfo->cLockBufs;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync RTR0MEMOBJ hObj;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync int rc;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync uint32_t fAccess = pSrcParm->type == VMMDevHGCMParmType_LinAddr_In
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync || pSrcParm->type == VMMDevHGCMParmType_LinAddr_Locked_In
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync ? RTMEM_PROT_READ
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync : RTMEM_PROT_READ | RTMEM_PROT_WRITE;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync AssertReturn(iLockBuf < RT_ELEMENTS(pParmInfo->aLockBufs), VERR_INVALID_PARAMETER);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (!fIsUser)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync AssertMsgReturn(cb <= VBGLR0_MAX_HGCM_KERNEL_PARM, ("%#x > %#x\n", cb, VBGLR0_MAX_HGCM_KERNEL_PARM),
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync VERR_OUT_OF_RANGE);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync rc = RTR0MemObjLockKernel(&hObj, (void *)pSrcParm->u.Pointer.u.linearAddr, cb, fAccess);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (RT_FAILURE(rc))
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync Log(("GstHGCMCall: id=%#x fn=%u parm=%u RTR0MemObjLockKernel(,%p,%#x) -> %Rrc\n",
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pCallInfo->u32ClientID, pCallInfo->u32Function, iParm, pSrcParm->u.Pointer.u.linearAddr, cb, rc));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync return rc;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync Log3(("GstHGCMCall: parm=%u type=%#x: cb=%#010x pv=%p locked kernel -> %p\n",
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync iParm, pSrcParm->type, cb, pSrcParm->u.Pointer.u.linearAddr, hObj));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync else if (cb > VBGLR0_MAX_HGCM_USER_PARM)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync Log(("GstHGCMCall: id=%#x fn=%u parm=%u pv=%p cb=%#x > %#x -> out of range\n",
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pCallInfo->u32ClientID, pCallInfo->u32Function, iParm, pSrcParm->u.Pointer.u.linearAddr,
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync cb, VBGLR0_MAX_HGCM_USER_PARM));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync return VERR_OUT_OF_RANGE;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync else
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#ifndef USE_BOUNCE_BUFFERS
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync rc = RTR0MemObjLockUser(&hObj, (RTR3PTR)pSrcParm->u.Pointer.u.linearAddr, cb, fAccess, NIL_RTR0PROCESS);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (RT_FAILURE(rc))
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync Log(("GstHGCMCall: id=%#x fn=%u parm=%u RTR0MemObjLockUser(,%p,%#x,nil) -> %Rrc\n",
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pCallInfo->u32ClientID, pCallInfo->u32Function, iParm, pSrcParm->u.Pointer.u.linearAddr, cb, rc));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync return rc;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync Log3(("GstHGCMCall: parm=%u type=%#x: cb=%#010x pv=%p locked user -> %p\n",
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync iParm, pSrcParm->type, cb, pSrcParm->u.Pointer.u.linearAddr, hObj));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#else /* USE_BOUNCE_BUFFERS */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /*
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * This is a bit massive, but we don't want to waste a
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * whole page for a 3 byte string buffer (guest props).
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync *
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * The threshold is ASSUMING sizeof(RTMEMHDR) == 16 and
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * the system is using some power of two allocator.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /** @todo A more efficient strategy would be to combine buffers. However it
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * is probably going to be more massive than the current code, so
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * it can wait till later. */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync bool fCopyIn = pSrcParm->type != VMMDevHGCMParmType_LinAddr_Out
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync && pSrcParm->type != VMMDevHGCMParmType_LinAddr_Locked_Out;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (cb <= PAGE_SIZE / 2 - 16)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pvSmallBuf = fCopyIn ? RTMemTmpAlloc(cb) : RTMemTmpAllocZ(cb);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (RT_UNLIKELY(!pvSmallBuf))
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync return VERR_NO_MEMORY;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (fCopyIn)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync rc = RTR0MemUserCopyFrom(pvSmallBuf, pSrcParm->u.Pointer.u.linearAddr, cb);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (RT_FAILURE(rc))
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync RTMemTmpFree(pvSmallBuf);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync Log(("GstHGCMCall: id=%#x fn=%u parm=%u RTR0MemUserCopyFrom(,%p,%#x) -> %Rrc\n",
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pCallInfo->u32ClientID, pCallInfo->u32Function, iParm,
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pSrcParm->u.Pointer.u.linearAddr, cb, rc));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync return rc;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync rc = RTR0MemObjLockKernel(&hObj, pvSmallBuf, cb, fAccess);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (RT_FAILURE(rc))
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync RTMemTmpFree(pvSmallBuf);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync Log(("GstHGCMCall: RTR0MemObjLockKernel failed for small buffer: rc=%Rrc pvSmallBuf=%p cb=%#x\n",
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync rc, pvSmallBuf, cb));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync return rc;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync Log3(("GstHGCMCall: parm=%u type=%#x: cb=%#010x pv=%p small buffer %p -> %p\n",
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync iParm, pSrcParm->type, cb, pSrcParm->u.Pointer.u.linearAddr, pvSmallBuf, hObj));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync else
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync rc = RTR0MemObjAllocPage(&hObj, cb, false /*fExecutable*/);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (RT_FAILURE(rc))
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync return rc;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (!fCopyIn)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync memset(RTR0MemObjAddress(hObj), '\0', cb);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync else
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync rc = RTR0MemUserCopyFrom(RTR0MemObjAddress(hObj), pSrcParm->u.Pointer.u.linearAddr, cb);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (RT_FAILURE(rc))
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync RTR0MemObjFree(hObj, false /*fFreeMappings*/);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync Log(("GstHGCMCall: id=%#x fn=%u parm=%u RTR0MemUserCopyFrom(,%p,%#x) -> %Rrc\n",
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pCallInfo->u32ClientID, pCallInfo->u32Function, iParm,
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pSrcParm->u.Pointer.u.linearAddr, cb, rc));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync return rc;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync Log3(("GstHGCMCall: parm=%u type=%#x: cb=%#010x pv=%p big buffer -> %p\n",
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync iParm, pSrcParm->type, cb, pSrcParm->u.Pointer.u.linearAddr, hObj));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#endif /* USE_BOUNCE_BUFFERS */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pParmInfo->aLockBufs[iLockBuf].iParm = iParm;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pParmInfo->aLockBufs[iLockBuf].hObj = hObj;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#ifdef USE_BOUNCE_BUFFERS
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pParmInfo->aLockBufs[iLockBuf].pvSmallBuf = pvSmallBuf;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#endif
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pParmInfo->cLockBufs = iLockBuf + 1;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (VBGLR0_CAN_USE_PHYS_PAGE_LIST())
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync size_t const cPages = RTR0MemObjSize(hObj) >> PAGE_SHIFT;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync *pcbExtra += RT_OFFSETOF(HGCMPageListInfo, aPages[cPages]);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync else
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync Log4(("GstHGCMCall: parm=%u type=%#x: cb=0\n", iParm, pSrcParm->type));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync break;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync default:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync return VERR_INVALID_PARAMETER;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync return VINF_SUCCESS;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync}
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync/**
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * Translates locked linear address to the normal type.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * The locked types are only for the guest side and not handled by the host.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync *
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * @returns normal linear address type.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * @param enmType The type.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsyncstatic HGCMFunctionParameterType vbglR0HGCMInternalConvertLinAddrType(HGCMFunctionParameterType enmType)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync{
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync switch (enmType)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_LinAddr_Locked_In:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync return VMMDevHGCMParmType_LinAddr_In;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_LinAddr_Locked_Out:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync return VMMDevHGCMParmType_LinAddr_Out;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_LinAddr_Locked:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync return VMMDevHGCMParmType_LinAddr;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync default:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync return enmType;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync}
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync/**
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * Translates linear address types to page list direction flags.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync *
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * @returns page list flags.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * @param enmType The type.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsyncstatic uint32_t vbglR0HGCMInternalLinAddrTypeToPageListFlags(HGCMFunctionParameterType enmType)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync{
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync switch (enmType)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_LinAddr_In:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_LinAddr_Locked_In:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync return VBOX_HGCM_F_PARM_DIRECTION_TO_HOST;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_LinAddr_Out:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_LinAddr_Locked_Out:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync return VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync default: AssertFailed();
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_LinAddr:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_LinAddr_Locked:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync return VBOX_HGCM_F_PARM_DIRECTION_BOTH;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync}
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync/**
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * Initializes the call request that we're sending to the host.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync *
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * @returns VBox status code.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync *
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * @param pCallInfo The call info.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * @param cbCallInfo The size of the call info structure.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * @param fIsUser Is it a user request or kernel request.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * @param pcbExtra Where to return the extra request space needed for
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * physical page lists.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsyncstatic void vbglR0HGCMInternalInitCall(VMMDevHGCMCall *pHGCMCall, VBoxGuestHGCMCallInfo const *pCallInfo,
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync uint32_t cbCallInfo, bool fIsUser, struct VbglR0ParmInfo *pParmInfo)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync{
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync HGCMFunctionParameter const *pSrcParm = VBOXGUEST_HGCM_CALL_PARMS(pCallInfo);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync HGCMFunctionParameter *pDstParm = VMMDEV_HGCM_CALL_PARMS(pHGCMCall);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync uint32_t cParms = pCallInfo->cParms;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync uint32_t offExtra = (uintptr_t)(pDstParm + cParms) - (uintptr_t)pHGCMCall;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync uint32_t iLockBuf = 0;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync uint32_t iParm;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /*
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * The call request headers.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pHGCMCall->header.fu32Flags = 0;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pHGCMCall->header.result = VINF_SUCCESS;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pHGCMCall->u32ClientID = pCallInfo->u32ClientID;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pHGCMCall->u32Function = pCallInfo->u32Function;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pHGCMCall->cParms = cParms;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /*
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * The parameters.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync for (iParm = 0; iParm < pCallInfo->cParms; iParm++, pSrcParm++, pDstParm++)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync switch (pSrcParm->type)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_32bit:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_64bit:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync *pDstParm = *pSrcParm;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync break;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_PageList:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pDstParm->type = VMMDevHGCMParmType_PageList;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pDstParm->u.PageList.size = pSrcParm->u.PageList.size;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (pSrcParm->u.PageList.size)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync HGCMPageListInfo const *pSrcPgLst = (HGCMPageListInfo *)((uint8_t *)pCallInfo + pSrcParm->u.PageList.offset);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync HGCMPageListInfo *pDstPgLst = (HGCMPageListInfo *)((uint8_t *)pHGCMCall + offExtra);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync uint32_t const cPages = pSrcPgLst->cPages;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync uint32_t iPage;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pDstParm->u.PageList.offset = offExtra;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pDstPgLst->flags = pSrcPgLst->flags;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pDstPgLst->offFirstPage = pSrcPgLst->offFirstPage;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pDstPgLst->cPages = cPages;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync for (iPage = 0; iPage < cPages; iPage++)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pDstPgLst->aPages[iPage] = pSrcPgLst->aPages[iPage];
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync offExtra += RT_OFFSETOF(HGCMPageListInfo, aPages[cPages]);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync else
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pDstParm->u.PageList.offset = 0;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync break;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_LinAddr_Locked_In:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_LinAddr_Locked_Out:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_LinAddr_Locked:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /* always perform it as !VBGLR0_CAN_USE_PHYS_PAGE_LIST() since otherwise
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * we end up creating a RTR0MEMOBJ and doing page lock again, which leads to undefined behavior and possible BSOD on Win */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync// if (!VBGLR0_CAN_USE_PHYS_PAGE_LIST())
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync *pDstParm = *pSrcParm;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pDstParm->type = vbglR0HGCMInternalConvertLinAddrType(pSrcParm->type);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync break;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /* fall thru */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_LinAddr_In:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_LinAddr_Out:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_LinAddr:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (pSrcParm->u.Pointer.size != 0)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#ifdef USE_BOUNCE_BUFFERS
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync void *pvSmallBuf = pParmInfo->aLockBufs[iLockBuf].pvSmallBuf;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#endif
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync RTR0MEMOBJ hObj = pParmInfo->aLockBufs[iLockBuf].hObj;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync Assert(iParm == pParmInfo->aLockBufs[iLockBuf].iParm);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (VBGLR0_CAN_USE_PHYS_PAGE_LIST())
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync HGCMPageListInfo *pDstPgLst = (HGCMPageListInfo *)((uint8_t *)pHGCMCall + offExtra);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync size_t const cPages = RTR0MemObjSize(hObj) >> PAGE_SHIFT;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync size_t iPage;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pDstParm->type = VMMDevHGCMParmType_PageList;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pDstParm->u.PageList.size = pSrcParm->u.Pointer.size;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pDstParm->u.PageList.offset = offExtra;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pDstPgLst->flags = vbglR0HGCMInternalLinAddrTypeToPageListFlags(pSrcParm->type);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#ifdef USE_BOUNCE_BUFFERS
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (fIsUser)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pDstPgLst->offFirstPage = (uintptr_t)pvSmallBuf & PAGE_OFFSET_MASK;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync else
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#endif
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pDstPgLst->offFirstPage = pSrcParm->u.Pointer.u.linearAddr & PAGE_OFFSET_MASK;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pDstPgLst->cPages = cPages; Assert(pDstPgLst->cPages == cPages);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync for (iPage = 0; iPage < cPages; iPage++)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pDstPgLst->aPages[iPage] = RTR0MemObjGetPagePhysAddr(hObj, iPage);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync Assert(pDstPgLst->aPages[iPage] != NIL_RTHCPHYS);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync offExtra += RT_OFFSETOF(HGCMPageListInfo, aPages[cPages]);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync else
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pDstParm->type = vbglR0HGCMInternalConvertLinAddrType(pSrcParm->type);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pDstParm->u.Pointer.size = pSrcParm->u.Pointer.size;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#ifdef USE_BOUNCE_BUFFERS
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (fIsUser)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pDstParm->u.Pointer.u.linearAddr = pvSmallBuf
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync ? (uintptr_t)pvSmallBuf
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync : (uintptr_t)RTR0MemObjAddress(hObj);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync else
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#endif
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pDstParm->u.Pointer.u.linearAddr = pSrcParm->u.Pointer.u.linearAddr;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync iLockBuf++;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync else
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pDstParm->type = vbglR0HGCMInternalConvertLinAddrType(pSrcParm->type);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pDstParm->u.Pointer.size = 0;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pDstParm->u.Pointer.u.linearAddr = 0;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync break;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync default:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync AssertFailed();
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pDstParm->type = VMMDevHGCMParmType_Invalid;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync break;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync}
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync/**
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * Performs the call and completion wait.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync *
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * @returns VBox status code of this operation, not necessarily the call.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync *
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * @param pHGCMCall The HGCM call info.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * @param pfnAsyncCallback The async callback that will wait for the call
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * to complete.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * @param pvAsyncData Argument for the callback.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * @param u32AsyncData Argument for the callback.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * @param pfLeakIt Where to return the leak it / free it,
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * indicator. Cancellation fun.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsyncstatic int vbglR0HGCMInternalDoCall(VMMDevHGCMCall *pHGCMCall, PFNVBGLHGCMCALLBACK pfnAsyncCallback,
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync void *pvAsyncData, uint32_t u32AsyncData, bool *pfLeakIt)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync{
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync int rc;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync Log(("calling VbglGRPerform\n"));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync rc = VbglGRPerform(&pHGCMCall->header.header);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync Log(("VbglGRPerform rc = %Rrc (header rc=%d)\n", rc, pHGCMCall->header.result));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /*
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * If the call failed, but as a result of the request itself, then pretend
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * success. Upper layers will interpret the result code in the packet.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if ( RT_FAILURE(rc)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync && rc == pHGCMCall->header.result)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync Assert(pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_DONE);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync rc = VINF_SUCCESS;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /*
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * Check if host decides to process the request asynchronously,
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * if so, we wait for it to complete using the caller supplied callback.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync *pfLeakIt = false;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (rc == VINF_HGCM_ASYNC_EXECUTE)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync Log(("Processing HGCM call asynchronously\n"));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync rc = pfnAsyncCallback(&pHGCMCall->header, pvAsyncData, u32AsyncData);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_DONE)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync Assert(!(pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_CANCELLED));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync rc = VINF_SUCCESS;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync else
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /*
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * The request didn't complete in time or the call was interrupted,
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * the RC from the callback indicates which. Try cancel the request.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync *
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * This is a bit messy because we're racing request completion. Sorry.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /** @todo It would be nice if we could use the waiter callback to do further
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * waiting in case of a completion race. If it wasn't for WINNT having its own
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * version of all that stuff, I would've done it already. */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync VMMDevHGCMCancel2 *pCancelReq;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync int rc2 = VbglGRAlloc((VMMDevRequestHeader **)&pCancelReq, sizeof(*pCancelReq), VMMDevReq_HGCMCancel2);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (RT_SUCCESS(rc2))
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pCancelReq->physReqToCancel = VbglPhysHeapGetPhysAddr(pHGCMCall);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync rc2 = VbglGRPerform(&pCancelReq->header);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync VbglGRFree(&pCancelReq->header);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#if 1 /** @todo ADDVER: Remove this on next minor version change. */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (rc2 == VERR_NOT_IMPLEMENTED)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /* host is too old, or we're out of heap. */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pHGCMCall->header.fu32Flags |= VBOX_HGCM_REQ_CANCELLED;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pHGCMCall->header.header.requestType = VMMDevReq_HGCMCancel;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync rc2 = VbglGRPerform(&pHGCMCall->header.header);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (rc2 == VERR_INVALID_PARAMETER)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync rc2 = VERR_NOT_FOUND;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync else if (RT_SUCCESS(rc))
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync RTThreadSleep(1);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#endif
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (RT_SUCCESS(rc)) rc = VERR_INTERRUPTED; /** @todo weed this out from the WINNT VBoxGuest code. */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (RT_SUCCESS(rc2))
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync Log(("vbglR0HGCMInternalDoCall: successfully cancelled\n"));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pHGCMCall->header.fu32Flags |= VBOX_HGCM_REQ_CANCELLED;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync else
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /*
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * Wait for a bit while the host (hopefully) completes it.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync uint64_t u64Start = RTTimeSystemMilliTS();
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync uint32_t cMilliesToWait = rc2 == VERR_NOT_FOUND || rc2 == VERR_SEM_DESTROYED ? 500 : 2000;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync uint64_t cElapsed = 0;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (rc2 != VERR_NOT_FOUND)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync static unsigned s_cErrors = 0;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (s_cErrors++ < 32)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync LogRel(("vbglR0HGCMInternalDoCall: Failed to cancel the HGCM call on %Rrc: rc2=%Rrc\n", rc, rc2));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync else
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync Log(("vbglR0HGCMInternalDoCall: Cancel race rc=%Rrc rc2=%Rrc\n", rc, rc2));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync do
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync ASMCompilerBarrier(); /* paranoia */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_DONE)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync break;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync RTThreadSleep(1);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync cElapsed = RTTimeSystemMilliTS() - u64Start;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync } while (cElapsed < cMilliesToWait);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync ASMCompilerBarrier(); /* paranoia^2 */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_DONE)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync rc = VINF_SUCCESS;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync else
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync LogRel(("vbglR0HGCMInternalDoCall: Leaking %u bytes. Pending call to %u with %u parms. (rc2=%Rrc)\n",
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pHGCMCall->header.header.size, pHGCMCall->u32Function, pHGCMCall->cParms, rc2));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync *pfLeakIt = true;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync Log(("vbglR0HGCMInternalDoCall: Cancel race ended with rc=%Rrc (rc2=%Rrc) after %llu ms\n", rc, rc2, cElapsed));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync Log(("GstHGCMCall: rc=%Rrc result=%Rrc fu32Flags=%#x fLeakIt=%d\n",
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync rc, pHGCMCall->header.result, pHGCMCall->header.fu32Flags, *pfLeakIt));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync return rc;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync}
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync/**
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * Copies the result of the call back to the caller info structure and user
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * buffers (if using bounce buffers).
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync *
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * @returns rc, unless RTR0MemUserCopyTo fails.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * @param pCallInfo Call info structure to update.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * @param pHGCMCall HGCM call request.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * @param pParmInfo Parameter locking/buffering info.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * @param fIsUser Is it a user (true) or kernel request.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * @param rc The current result code. Passed along to
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * preserve informational status codes.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsyncstatic int vbglR0HGCMInternalCopyBackResult(VBoxGuestHGCMCallInfo *pCallInfo, VMMDevHGCMCall const *pHGCMCall,
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync struct VbglR0ParmInfo *pParmInfo, bool fIsUser, int rc)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync{
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync HGCMFunctionParameter const *pSrcParm = VMMDEV_HGCM_CALL_PARMS(pHGCMCall);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync HGCMFunctionParameter *pDstParm = VBOXGUEST_HGCM_CALL_PARMS(pCallInfo);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync uint32_t cParms = pCallInfo->cParms;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#ifdef USE_BOUNCE_BUFFERS
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync uint32_t iLockBuf = 0;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#endif
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync uint32_t iParm;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /*
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * The call result.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pCallInfo->result = pHGCMCall->header.result;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /*
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * Copy back parameters.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync for (iParm = 0; iParm < cParms; iParm++, pSrcParm++, pDstParm++)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync switch (pDstParm->type)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_32bit:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_64bit:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync *pDstParm = *pSrcParm;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync break;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_PageList:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pDstParm->u.PageList.size = pSrcParm->u.PageList.size;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync break;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_LinAddr_Locked_In:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_LinAddr_In:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#ifdef USE_BOUNCE_BUFFERS
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if ( fIsUser
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync && iLockBuf < pParmInfo->cLockBufs
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync && iParm == pParmInfo->aLockBufs[iLockBuf].iParm)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync iLockBuf++;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#endif
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pDstParm->u.Pointer.size = pSrcParm->u.Pointer.size;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync break;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_LinAddr_Locked_Out:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_LinAddr_Locked:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /* always perform it as !VBGLR0_CAN_USE_PHYS_PAGE_LIST() since otherwise
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * we end up creating a RTR0MEMOBJ and doing page lock again, which leads to undefined behavior and possible BSOD on Win */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync// if (!VBGLR0_CAN_USE_PHYS_PAGE_LIST())
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pDstParm->u.Pointer.size = pSrcParm->u.Pointer.size;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync break;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /* fall thru */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_LinAddr_Out:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_LinAddr:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#ifdef USE_BOUNCE_BUFFERS
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (fIsUser)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync size_t cbOut = RT_MIN(pSrcParm->u.Pointer.size, pDstParm->u.Pointer.size);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (cbOut)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync int rc2;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync Assert(pParmInfo->aLockBufs[iLockBuf].iParm == iParm);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync rc2 = RTR0MemUserCopyTo((RTR3PTR)pDstParm->u.Pointer.u.linearAddr,
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pParmInfo->aLockBufs[iLockBuf].pvSmallBuf
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync ? pParmInfo->aLockBufs[iLockBuf].pvSmallBuf
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync : RTR0MemObjAddress(pParmInfo->aLockBufs[iLockBuf].hObj),
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync cbOut);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (RT_FAILURE(rc2))
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync return rc2;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync iLockBuf++;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync else if ( iLockBuf < pParmInfo->cLockBufs
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync && iParm == pParmInfo->aLockBufs[iLockBuf].iParm)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync iLockBuf++;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#endif
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pDstParm->u.Pointer.size = pSrcParm->u.Pointer.size;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync break;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync default:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync AssertFailed();
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync rc = VERR_INTERNAL_ERROR_4;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync break;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#ifdef USE_BOUNCE_BUFFERS
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync Assert(!fIsUser || pParmInfo->cLockBufs == iLockBuf);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#endif
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync return rc;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync}
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsyncDECLR0VBGL(int) VbglR0HGCMInternalCall(VBoxGuestHGCMCallInfo *pCallInfo, uint32_t cbCallInfo, uint32_t fFlags,
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync PFNVBGLHGCMCALLBACK pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync{
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync bool fIsUser = (fFlags & VBGLR0_HGCMCALL_F_MODE_MASK) == VBGLR0_HGCMCALL_F_USER;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync struct VbglR0ParmInfo ParmInfo;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync size_t cbExtra;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync int rc;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /*
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * Basic validation.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync AssertMsgReturn( !pCallInfo
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync || !pfnAsyncCallback
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync || pCallInfo->cParms > VBOX_HGCM_MAX_PARMS
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync || !(fFlags & ~VBGLR0_HGCMCALL_F_MODE_MASK),
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync ("pCallInfo=%p pfnAsyncCallback=%p fFlags=%#x\n", pCallInfo, pfnAsyncCallback, fFlags),
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync VERR_INVALID_PARAMETER);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync AssertReturn( cbCallInfo >= sizeof(VBoxGuestHGCMCallInfo)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync || cbCallInfo >= pCallInfo->cParms * sizeof(HGCMFunctionParameter),
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync VERR_INVALID_PARAMETER);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync Log(("GstHGCMCall: u32ClientID=%#x u32Function=%u cParms=%u cbCallInfo=%#x fFlags=%#x\n",
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pCallInfo->u32ClientID, pCallInfo->u32ClientID, pCallInfo->u32Function, pCallInfo->cParms, cbCallInfo, fFlags));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /*
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * Validate, lock and buffer the parameters for the call.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * This will calculate the amount of extra space for physical page list.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync rc = vbglR0HGCMInternalPreprocessCall(pCallInfo, cbCallInfo, fIsUser, &ParmInfo, &cbExtra);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (RT_SUCCESS(rc))
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /*
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * Allocate the request buffer and recreate the call request.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync VMMDevHGCMCall *pHGCMCall;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync rc = VbglGRAlloc((VMMDevRequestHeader **)&pHGCMCall,
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync sizeof(VMMDevHGCMCall) + pCallInfo->cParms * sizeof(HGCMFunctionParameter) + cbExtra,
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync VMMDevReq_HGCMCall);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (RT_SUCCESS(rc))
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync bool fLeakIt;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync vbglR0HGCMInternalInitCall(pHGCMCall, pCallInfo, cbCallInfo, fIsUser, &ParmInfo);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /*
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * Perform the call.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync rc = vbglR0HGCMInternalDoCall(pHGCMCall, pfnAsyncCallback, pvAsyncData, u32AsyncData, &fLeakIt);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (RT_SUCCESS(rc))
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /*
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * Copy back the result (parameters and buffers that changed).
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync rc = vbglR0HGCMInternalCopyBackResult(pCallInfo, pHGCMCall, &ParmInfo, fIsUser, rc);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync else
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if ( rc != VERR_INTERRUPTED
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync && rc != VERR_TIMEOUT)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync static unsigned s_cErrors = 0;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (s_cErrors++ < 32)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync LogRel(("VbglR0HGCMInternalCall: vbglR0HGCMInternalDoCall failed. rc=%Rrc\n", rc));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (!fLeakIt)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync VbglGRFree(&pHGCMCall->header.header);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync else
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync LogRel(("VbglR0HGCMInternalCall: vbglR0HGCMInternalPreprocessCall failed. rc=%Rrc\n", rc));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /*
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * Release locks and free bounce buffers.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (ParmInfo.cLockBufs)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync while (ParmInfo.cLockBufs-- > 0)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync RTR0MemObjFree(ParmInfo.aLockBufs[ParmInfo.cLockBufs].hObj, false /*fFreeMappings*/);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#ifdef USE_BOUNCE_BUFFERS
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync RTMemTmpFree(ParmInfo.aLockBufs[ParmInfo.cLockBufs].pvSmallBuf);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#endif
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync return rc;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync}
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#if ARCH_BITS == 64
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsyncDECLR0VBGL(int) VbglR0HGCMInternalCall32(VBoxGuestHGCMCallInfo *pCallInfo, uint32_t cbCallInfo, uint32_t fFlags,
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync PFNVBGLHGCMCALLBACK pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync{
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync VBoxGuestHGCMCallInfo *pCallInfo64 = NULL;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync HGCMFunctionParameter *pParm64 = NULL;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync HGCMFunctionParameter32 *pParm32 = NULL;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync uint32_t cParms = 0;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync uint32_t iParm = 0;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync int rc = VINF_SUCCESS;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /*
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * Input validation.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync AssertMsgReturn( !pCallInfo
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync || !pfnAsyncCallback
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync || pCallInfo->cParms > VBOX_HGCM_MAX_PARMS
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync || !(fFlags & ~VBGLR0_HGCMCALL_F_MODE_MASK),
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync ("pCallInfo=%p pfnAsyncCallback=%p fFlags=%#x\n", pCallInfo, pfnAsyncCallback, fFlags),
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync VERR_INVALID_PARAMETER);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync AssertReturn( cbCallInfo >= sizeof(VBoxGuestHGCMCallInfo)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync || cbCallInfo >= pCallInfo->cParms * sizeof(HGCMFunctionParameter32),
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync VERR_INVALID_PARAMETER);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /* This Assert does not work on Solaris/Windows 64/32 mixed mode, not sure why, skipping for now */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#if !defined(RT_OS_SOLARIS) && !defined(RT_OS_WINDOWS)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync AssertReturn((fFlags & VBGLR0_HGCMCALL_F_MODE_MASK) == VBGLR0_HGCMCALL_F_KERNEL, VERR_WRONG_ORDER);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#endif
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync cParms = pCallInfo->cParms;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync Log(("VbglR0HGCMInternalCall32: cParms=%d, u32Function=%d, fFlags=%#x\n", cParms, pCallInfo->u32Function, fFlags));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /*
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * The simple approach, allocate a temporary request and convert the parameters.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pCallInfo64 = (VBoxGuestHGCMCallInfo *)RTMemTmpAllocZ(sizeof(*pCallInfo64) + cParms * sizeof(HGCMFunctionParameter));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (!pCallInfo64)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync return VERR_NO_TMP_MEMORY;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync *pCallInfo64 = *pCallInfo;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pParm32 = VBOXGUEST_HGCM_CALL_PARMS32(pCallInfo);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pParm64 = VBOXGUEST_HGCM_CALL_PARMS(pCallInfo64);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync for (iParm = 0; iParm < cParms; iParm++, pParm32++, pParm64++)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync switch (pParm32->type)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_32bit:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pParm64->type = VMMDevHGCMParmType_32bit;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pParm64->u.value32 = pParm32->u.value32;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync break;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_64bit:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pParm64->type = VMMDevHGCMParmType_64bit;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pParm64->u.value64 = pParm32->u.value64;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync break;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_LinAddr_Out:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_LinAddr:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_LinAddr_In:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pParm64->type = pParm32->type;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pParm64->u.Pointer.size = pParm32->u.Pointer.size;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pParm64->u.Pointer.u.linearAddr = pParm32->u.Pointer.u.linearAddr;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync break;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync default:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync rc = VERR_INVALID_PARAMETER;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync LogRel(("VbglR0HGCMInternalCall32: pParm32 type %#x invalid.\n", pParm32->type));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync break;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (RT_FAILURE(rc))
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync break;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (RT_SUCCESS(rc))
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync rc = VbglR0HGCMInternalCall(pCallInfo64, sizeof(*pCallInfo64) + cParms * sizeof(HGCMFunctionParameter), fFlags,
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pfnAsyncCallback, pvAsyncData, u32AsyncData);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (RT_SUCCESS(rc))
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync *pCallInfo = *pCallInfo64;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync /*
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync * Copy back.
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pParm32 = VBOXGUEST_HGCM_CALL_PARMS32(pCallInfo);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pParm64 = VBOXGUEST_HGCM_CALL_PARMS(pCallInfo64);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync for (iParm = 0; iParm < cParms; iParm++, pParm32++, pParm64++)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync switch (pParm64->type)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_32bit:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pParm32->u.value32 = pParm64->u.value32;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync break;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_64bit:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pParm32->u.value64 = pParm64->u.value64;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync break;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_LinAddr_Out:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_LinAddr:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync case VMMDevHGCMParmType_LinAddr_In:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync pParm32->u.Pointer.size = pParm64->u.Pointer.size;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync break;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync default:
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync LogRel(("VbglR0HGCMInternalCall32: failed invalid pParm32 type %d\n", pParm32->type));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync rc = VERR_INTERNAL_ERROR_3;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync break;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync else
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync static unsigned s_cErrors = 0;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (s_cErrors++ < 32)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync LogRel(("VbglR0HGCMInternalCall32: VbglR0HGCMInternalCall failed. rc=%Rrc\n", rc));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync else
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync {
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync static unsigned s_cErrors = 0;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync if (s_cErrors++ < 32)
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync LogRel(("VbglR0HGCMInternalCall32: failed. rc=%Rrc\n", rc));
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync }
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync RTMemTmpFree(pCallInfo64);
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync return rc;
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync}
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#endif /* ARCH_BITS == 64 */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync#endif /* VBGL_VBOXGUEST */
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync
9c9df2b728333cb734a7cc7856568e9ea9dc4600vboxsync