VirtualBox

Changeset 15704 in vbox


Ignore:
Timestamp:
Dec 19, 2008 4:44:54 PM (16 years ago)
Author:
vboxsync
Message:

Introduced VbglHCGMCall32 for supporting 32 bits clients on 64 bits guests.

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/VBoxGuest.h

    r15699 r15704  
    916916#pragma pack()
    917917
    918 #define VMMDEV_HGCM_CALL_PARMS(a) ((HGCMFunctionParameter *)((uint8_t *)a + sizeof (VMMDevHGCMCall)))
     918#define VMMDEV_HGCM_CALL_PARMS(a)   ((HGCMFunctionParameter *)((uint8_t *)a + sizeof (VMMDevHGCMCall)))
     919#define VMMDEV_HGCM_CALL_PARMS32(a) ((HGCMFunctionParameter32 *)((uint8_t *)a + sizeof (VMMDevHGCMCall)))
    919920
    920921#ifdef VBOX_WITH_64_BITS_GUESTS
     
    14041405
    14051406# define VBOXGUEST_HGCM_CALL_PARMS(a)       ((HGCMFunctionParameter *)((uint8_t *)(a) + sizeof (VBoxGuestHGCMCallInfo)))
     1407# define VBOXGUEST_HGCM_CALL_PARMS32(a)     ((HGCMFunctionParameter32 *)((uint8_t *)(a) + sizeof (VBoxGuestHGCMCallInfo)))
    14061408
    14071409#endif /* VBOX_WITH_HGCM */
  • trunk/include/VBox/VBoxGuestLib.h

    r14352 r15704  
    200200DECLVBGL(int) VbglHGCMCall (VBoxGuestHGCMCallInfo *pCallInfo,
    201201                            VBGLHGCMCALLBACK *pAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData);
     202
     203/** Call a HGCM service. (32 bits packet structure in a 64 bits guest)
     204 *
     205 * @note This function can deal with cancelled requests.
     206 *
     207 * @param pCallInfo       The request data.
     208 * @param pAsyncCallback  Required pointer to function that is called when
     209 *                        host returns VINF_HGCM_ASYNC_EXECUTE. VBoxGuest
     210 *                        implements waiting for an IRQ in this function.
     211 * @param pvAsyncData     An arbitrary VBoxGuest pointer to be passed to callback.
     212 * @param u32AsyncData    An arbitrary VBoxGuest 32 bit value to be passed to callback.
     213 *
     214 * @return VBox status code.
     215 */
     216DECLVBGL(int) VbglHGCMCall32 (VBoxGuestHGCMCallInfo *pCallInfo,
     217                              VBGLHGCMCALLBACK *pAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData);
    202218
    203219#else /* !VBGL_VBOXGUEST */
  • trunk/src/VBox/Additions/WINNT/VBoxGuest/VBoxGuest.cpp

    r15703 r15704  
    993993        case VBOXGUEST_IOCTL_HGCM_CALL(0): /* (The size isn't relevant on NT.) */
    994994        {
     995            int rc;
     996
    995997            dprintf(("VBoxGuest::VBoxGuestDeviceControl: VBOXGUEST_IOCTL_HGCM_CALL\n"));
    996998
     
    10061008            VBoxGuestHGCMCallInfo *ptr = (VBoxGuestHGCMCallInfo *)pBuf;
    10071009
    1008             int rc = VbglHGCMCall (ptr, VBoxHGCMCallback, pDevExt, RT_INDEFINITE_WAIT);
     1010# if ARCH_BITS == 64
     1011            if (IoIs32bitProcess(pIrp))
     1012                rc = VbglHGCMCall32(ptr, VBoxHGCMCallback, pDevExt, RT_INDEFINITE_WAIT);
     1013            else
     1014# endif
     1015                rc = VbglHGCMCall (ptr, VBoxHGCMCallback, pDevExt, RT_INDEFINITE_WAIT);
    10091016
    10101017            if (RT_FAILURE(rc))
     
    10191026
    10201027        } break;
    1021 
    1022 #if defined(VBOX_WITH_64_BITS_GUESTS) && ARCH_BITS == 64
    1023         case VBOXGUEST_IOCTL_HGCM_CALL_32(0): /* (The size isn't relevant on NT.) */
    1024         {
    1025             dprintf(("VBoxGuest::VBoxGuestDeviceControl: VBOXGUEST_IOCTL_HGCM_CALL_32\n"));
    1026 
    1027             Status = vboxHGCMVerifyIOBuffers (pStack,
    1028                                               sizeof (VBoxGuestHGCMCallInfo));
    1029 
    1030             if (Status != STATUS_SUCCESS)
    1031             {
    1032                 dprintf(("VBoxGuest::VBoxGuestDeviceControl: invalid parameter. Status: %p\n", Status));
    1033                 break;
    1034             }
    1035 
    1036             VBoxGuestHGCMCallInfo *ptr32 = (VBoxGuestHGCMCallInfo *)pBuf;
    1037             VBoxGuestHGCMCallInfo *ptr64;
    1038 
    1039             unsigned cbPtr32 = sizeof(*ptr32)+ptr32->cParms*sizeof(HGCMFunctionParameter32);
    1040             unsigned cbPtr64 = sizeof(*ptr32)+ptr32->cParms*sizeof(HGCMFunctionParameter);
    1041 
    1042             /*@todo r=Leonid, same should be applied to case VBOXGUEST_IOCTL_HGCM_CALL(0) as well,
    1043              * because vboxHGCMVerifyIOBuffers, checks for sizeof (VBoxGuestHGCMCallInfo) only.
    1044              */
    1045             if (pStack->Parameters.DeviceIoControl.InputBufferLength < cbPtr32)
    1046             {
    1047                 dprintf(("VBoxGuest::vboxHGCMVerifyIOBuffers: InputBufferLength %d < %d\n",
    1048                         pStack->Parameters.DeviceIoControl.InputBufferLength, cbPtr32));
    1049                 Status = STATUS_INVALID_PARAMETER;
    1050                 break;
    1051             }
    1052 
    1053             ptr64 = (VBoxGuestHGCMCallInfo *) RTMemTmpAlloc(cbPtr64);
    1054 
    1055             if (!ptr64)
    1056             {
    1057                 dprintf(("VBoxGuest::VBoxGuestDeviceControl: No memory\n"));
    1058                 Status = STATUS_UNSUCCESSFUL;
    1059                 break;     
    1060             }
    1061 
    1062             /*copy 32bit call info into 64bit*/
    1063             {
    1064                 unsigned iParm;
    1065                 HGCMFunctionParameter   *pParm64;
    1066                 HGCMFunctionParameter32 *pParm32;
    1067 
    1068                 /*copy header*/
    1069                 memcpy(ptr64, ptr32, sizeof(VBoxGuestHGCMCallInfo));
    1070 
    1071                 pParm64 = VBOXGUEST_HGCM_CALL_PARMS(ptr64);
    1072                 pParm32 = (HGCMFunctionParameter32*) VBOXGUEST_HGCM_CALL_PARMS(ptr32);
    1073 
    1074                 for (iParm = 0; iParm < ptr32->cParms; ++iParm)
    1075                 {
    1076                     pParm64->type = pParm32->type;
    1077                    
    1078                     switch(pParm64->type)
    1079                     {
    1080                         case VMMDevHGCMParmType_PhysAddr:
    1081                             pParm64->u.Pointer.size = pParm32->u.Pointer.size;
    1082                             pParm64->u.Pointer.u.physAddr = pParm32->u.Pointer.u.physAddr;
    1083                             break;
    1084                         case VMMDevHGCMParmType_LinAddr:
    1085                         case VMMDevHGCMParmType_LinAddr_In:
    1086                         case VMMDevHGCMParmType_LinAddr_Out:
    1087                         case VMMDevHGCMParmType_LinAddr_Locked:
    1088                         case VMMDevHGCMParmType_LinAddr_Locked_In:
    1089                         case VMMDevHGCMParmType_LinAddr_Locked_Out:
    1090                             pParm64->u.Pointer.size = pParm32->u.Pointer.size;
    1091                             pParm64->u.Pointer.u.linearAddr = pParm32->u.Pointer.u.linearAddr;
    1092                             break;
    1093                         case VMMDevHGCMParmType_32bit:
    1094                             pParm64->u.value32 = pParm32->u.value32;
    1095                             break;
    1096                         case VMMDevHGCMParmType_64bit:
    1097                             pParm64->u.value64 = pParm32->u.value64;
    1098                             break;
    1099                         default:
    1100                             Status = STATUS_UNSUCCESSFUL;
    1101                             break;
    1102                     }
    1103 
    1104                     ++pParm32;
    1105                     ++pParm64;
    1106                 }
    1107 
    1108                 if (Status != STATUS_SUCCESS)
    1109                 {
    1110                     dprintf(("VBoxGuest::VBoxGuestDeviceControl: invalid parameter. Status: %p\n", Status));
    1111                     break;
    1112                 }
    1113             }
    1114 
    1115             int rc = VbglHGCMCall (ptr64, VBoxHGCMCallback, pDevExt, RT_INDEFINITE_WAIT);
    1116 
    1117             if (RT_FAILURE(rc))
    1118             {
    1119                 dprintf(("VBOXGUEST_IOCTL_HGCM_CALL: vbox rc = %Rrc\n", rc));
    1120                 Status = STATUS_UNSUCCESSFUL;
    1121             }
    1122             else
    1123             {
    1124                 cbOut = pStack->Parameters.DeviceIoControl.OutputBufferLength;
    1125             }
    1126 
    1127             /*copy results back*/
    1128             {
    1129                 unsigned iParm;
    1130                 HGCMFunctionParameter   *pParm64;
    1131                 HGCMFunctionParameter32 *pParm32;
    1132 
    1133                 /*copy header*/
    1134                 memcpy(ptr32, ptr64, sizeof(VBoxGuestHGCMCallInfo));
    1135 
    1136                 pParm64 = VBOXGUEST_HGCM_CALL_PARMS(ptr64);
    1137                 pParm32 = (HGCMFunctionParameter32*) VBOXGUEST_HGCM_CALL_PARMS(ptr32);
    1138 
    1139                 /*@todo r=Leonid, FIXME: I think pointer values couldn't change but not sure so better play it safe*/
    1140                 for (iParm = 0; iParm < ptr32->cParms; ++iParm)
    1141                 {
    1142                     pParm32->type = pParm64->type;
    1143                    
    1144                     switch(pParm64->type)
    1145                     {
    1146                         case VMMDevHGCMParmType_PhysAddr:
    1147                             pParm32->u.Pointer.size = pParm64->u.Pointer.size;
    1148                             pParm32->u.Pointer.u.physAddr = pParm64->u.Pointer.u.physAddr;
    1149                             break;
    1150                         case VMMDevHGCMParmType_LinAddr:
    1151                         case VMMDevHGCMParmType_LinAddr_In:
    1152                         case VMMDevHGCMParmType_LinAddr_Out:
    1153                         case VMMDevHGCMParmType_LinAddr_Locked:
    1154                         case VMMDevHGCMParmType_LinAddr_Locked_In:
    1155                         case VMMDevHGCMParmType_LinAddr_Locked_Out:
    1156                             pParm32->u.Pointer.size = pParm64->u.Pointer.size;
    1157                             pParm32->u.Pointer.u.linearAddr = pParm64->u.Pointer.u.linearAddr;
    1158                             break;
    1159                         case VMMDevHGCMParmType_32bit:
    1160                             pParm32->u.value32 = pParm64->u.value32;
    1161                             break;
    1162                         case VMMDevHGCMParmType_64bit:
    1163                             pParm32->u.value64 = pParm64->u.value64;
    1164                             break;
    1165                         default:
    1166                             Status = STATUS_UNSUCCESSFUL;
    1167                             break;
    1168                     }
    1169 
    1170                     ++pParm32;
    1171                     ++pParm64;
    1172                 }
    1173 
    1174                 if (Status != STATUS_SUCCESS)
    1175                 {
    1176                     dprintf(("VBoxGuest::VBoxGuestDeviceControl: invalid parameter. Status: %p\n", Status));
    1177                     break;
    1178                 }
    1179             }
    1180 
    1181             RTMemTmpFree(ptr64);
    1182 
    1183         } break;
    1184 #endif
    11851028
    11861029        case VBOXGUEST_IOCTL_HGCM_CALL_TIMED(0): /* (The size isn't relevant on NT.) */
  • trunk/src/VBox/Additions/common/VBoxGuestLib/HGCMInternal.cpp

    r14217 r15704  
    286286    return rc;
    287287}
     288# if ARCH_BITS == 64
     289DECLVBGL(int) VbglHGCMCall32 (VBoxGuestHGCMCallInfo *pCallInfo,
     290                              VBGLHGCMCALLBACK *pAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData)
     291{
     292    VMMDevHGCMCall *pHGCMCall;
     293    uint32_t cbParms;
     294    HGCMFunctionParameter32 *pParm;
     295    unsigned iParm;
     296    int rc;
     297
     298    if (!pCallInfo || !pAsyncCallback || pCallInfo->cParms > VBOX_HGCM_MAX_PARMS)
     299    {
     300        AssertFailed();
     301        return VERR_INVALID_PARAMETER;
     302    }
     303
     304    Log (("VbglHGCMCall: pCallInfo->cParms = %d, pHGCMCall->u32Function = %d\n", pCallInfo->cParms, pCallInfo->u32Function));
     305
     306    pHGCMCall = NULL;
     307
     308    cbParms = pCallInfo->cParms * sizeof (HGCMFunctionParameter32);
     309
     310    /* Allocate request */
     311    rc = VbglGRAlloc ((VMMDevRequestHeader **)&pHGCMCall, sizeof (VMMDevHGCMCall) + cbParms, VMMDevReq_HGCMCall32);
     312
     313    Log (("VbglHGCMCall Allocated gr %p, rc = %Rrc, cbParms = %d\n", pHGCMCall, rc, cbParms));
     314
     315    if (RT_SUCCESS(rc))
     316    {
     317        void *apvCtx[VBOX_HGCM_MAX_PARMS];
     318        memset (apvCtx, 0, sizeof(void *) * pCallInfo->cParms);
     319
     320        /* Initialize request memory */
     321        pHGCMCall->header.fu32Flags = 0;
     322        pHGCMCall->header.result    = VINF_SUCCESS;
     323
     324        pHGCMCall->u32ClientID = pCallInfo->u32ClientID;
     325        pHGCMCall->u32Function = pCallInfo->u32Function;
     326        pHGCMCall->cParms      = pCallInfo->cParms;
     327
     328        if (cbParms)
     329        {
     330            /* Lock user buffers. */
     331            pParm = VBOXGUEST_HGCM_CALL_PARMS32(pCallInfo);
     332
     333            for (iParm = 0; iParm < pCallInfo->cParms; iParm++, pParm++)
     334            {
     335                switch (pParm->type)
     336                {
     337                case VMMDevHGCMParmType_LinAddr_Locked_In:
     338                    pParm->type = VMMDevHGCMParmType_LinAddr_In;
     339                    break;
     340                case VMMDevHGCMParmType_LinAddr_Locked_Out:
     341                    pParm->type = VMMDevHGCMParmType_LinAddr_Out;
     342                    break;
     343                case VMMDevHGCMParmType_LinAddr_Locked:
     344                    pParm->type = VMMDevHGCMParmType_LinAddr;
     345                    break;
     346
     347                case VMMDevHGCMParmType_LinAddr_In:
     348                case VMMDevHGCMParmType_LinAddr_Out:
     349                case VMMDevHGCMParmType_LinAddr:
     350                    /* PORTME: When porting this to Darwin and other systems where the entire kernel isn't mapped
     351                       into every process, all linear address will have to be converted to physical SG lists at
     352                       this point. Care must also be taken on these guests to not mix kernel and user addresses
     353                       in HGCM calls, or we'll end up locking the wrong memory. If VMMDev/HGCM gets a linear address
     354                       it will assume that it's in the current memory context (i.e. use CR3 to translate it).
     355
     356                       These kind of problems actually applies to some patched linux kernels too, including older
     357                       fedora releases. (The patch is the infamous 4G/4G patch, aka 4g4g, by Ingo Molnar.) */
     358                    rc = vbglLockLinear (&apvCtx[iParm], (void *)pParm->u.Pointer.u.linearAddr, pParm->u.Pointer.size, (pParm->type == VMMDevHGCMParmType_LinAddr_In) ? false : true /* write access */);
     359                    break;
     360                default:
     361                    /* make gcc happy */
     362                    break;
     363                }
     364                if (RT_FAILURE (rc))
     365                    break;
     366            }
     367            memcpy (VMMDEV_HGCM_CALL_PARMS32(pHGCMCall), VBOXGUEST_HGCM_CALL_PARMS32(pCallInfo), cbParms);
     368        }
     369
     370        /* Check that the parameter locking was ok. */
     371        if (RT_SUCCESS(rc))
     372        {
     373            Log (("calling VbglGRPerform\n"));
     374
     375            /* Issue request */
     376            rc = VbglGRPerform (&pHGCMCall->header.header);
     377
     378            Log (("VbglGRPerform rc = %Rrc (header rc=%d)\n", rc, pHGCMCall->header.result));
     379
     380            /** If the call failed, but as a result of the request itself, then pretend success
     381             *  Upper layers will interpret the result code in the packet.
     382             */
     383            if (RT_FAILURE(rc) && rc == pHGCMCall->header.result)
     384            {
     385                Assert(pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_DONE);
     386                rc = VINF_SUCCESS;
     387            }
     388
     389            if (RT_SUCCESS(rc))
     390            {
     391                /* Check if host decides to process the request asynchronously. */
     392                if (rc == VINF_HGCM_ASYNC_EXECUTE)
     393                {
     394                    /* Wait for request completion interrupt notification from host */
     395                    Log (("Processing HGCM call asynchronously\n"));
     396                    pAsyncCallback (&pHGCMCall->header, pvAsyncData, u32AsyncData);
     397                }
     398
     399                if (pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_DONE)
     400                {
     401                    if (cbParms)
     402                        memcpy (VBOXGUEST_HGCM_CALL_PARMS32(pCallInfo), VMMDEV_HGCM_CALL_PARMS32(pHGCMCall), cbParms);
     403
     404                    pCallInfo->result = pHGCMCall->header.result;
     405                }
     406                else
     407                {
     408                    /* The callback returns without completing the request,
     409                     * that means the wait was interrrupted. That can happen
     410                     * if the request times out, the system reboots or the
     411                     * VBoxService ended abnormally.
     412                     *
     413                     * Cancel the request, the host will not write to the
     414                     * memory related to the cancelled request.
     415                     */
     416                    Log (("Cancelling HGCM call\n"));
     417                    pHGCMCall->header.fu32Flags |= VBOX_HGCM_REQ_CANCELLED;
     418
     419                    pHGCMCall->header.header.requestType = VMMDevReq_HGCMCancel;
     420                    VbglGRPerform (&pHGCMCall->header.header);
     421                }
     422            }
     423        }
     424
     425        /* Unlock user buffers. */
     426        pParm = VBOXGUEST_HGCM_CALL_PARMS32(pCallInfo);
     427
     428        for (iParm = 0; iParm < pCallInfo->cParms; iParm++, pParm++)
     429        {
     430            if (   pParm->type == VMMDevHGCMParmType_LinAddr_In
     431                || pParm->type == VMMDevHGCMParmType_LinAddr_Out
     432                || pParm->type == VMMDevHGCMParmType_LinAddr)
     433            {
     434                if (apvCtx[iParm] != NULL)
     435                {
     436                    vbglUnlockLinear (apvCtx[iParm], (void *)pParm->u.Pointer.u.linearAddr, pParm->u.Pointer.size);
     437                }
     438            }
     439            else
     440                Assert(!apvCtx[iParm]);
     441        }
     442
     443        if ((pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_CANCELLED) == 0)
     444            VbglGRFree (&pHGCMCall->header.header);
     445        else
     446            rc = VERR_INTERRUPTED;
     447    }
     448
     449    return rc;
     450}
     451# endif /* ARCH_BITS == 64 */
    288452
    289453#endif /* VBGL_VBOXGUEST */
Note: See TracChangeset for help on using the changeset viewer.

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