Changeset 71604 in vbox
- Timestamp:
- Apr 1, 2018 6:11:34 PM (6 years ago)
- File:
-
- 1 edited
-
trunk/src/VBox/Devices/Graphics/DevVGA_VDMA.cpp (modified) (13 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Graphics/DevVGA_VDMA.cpp
r71603 r71604 2393 2393 2394 2394 /** 2395 * Check if this is an external command to be passed to the chromium backend.2396 *2397 * @retval VINF_NOT_SUPPORTED if not chromium command.2398 *2399 * @note cbCmdDr is at least sizeof(VBOXVDMACBUF_DR).2400 */2401 static int vboxVDMACmdCheckCrCmd(struct VBOXVDMAHOST *pVdma, VBOXVDMACBUF_DR RT_UNTRUSTED_VOLATILE_GUEST *pCmdDr, uint32_t cbCmdDr)2402 {2403 /*2404 * A chromium command has a VBOXVDMACMD part, so get that first.2405 */2406 uint32_t cbDmaCmd = pCmdDr->cbBuf;2407 uint16_t fDmaCmd = pCmdDr->fFlags;2408 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();2409 2410 VBOXVDMACMD RT_UNTRUSTED_VOLATILE_GUEST *pDmaCmd;2411 if (fDmaCmd & VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR)2412 {2413 AssertReturn(cbCmdDr >= sizeof(*pCmdDr) + VBOXVDMACMD_HEADER_SIZE(), VERR_INVALID_PARAMETER);2414 AssertReturn(cbDmaCmd >= cbCmdDr - sizeof(*pCmdDr) - VBOXVDMACMD_HEADER_SIZE(), VERR_INVALID_PARAMETER);2415 2416 pDmaCmd = VBOXVDMACBUF_DR_TAIL(pCmdDr, VBOXVDMACMD);2417 }2418 else if (fDmaCmd & VBOXVDMACBUF_FLAG_BUF_VRAM_OFFSET)2419 {2420 VBOXVIDEOOFFSET offBuf = pCmdDr->Location.offVramBuf;2421 AssertReturn( cbDmaCmd <= pVdma->pVGAState->vram_size2422 && offBuf <= pVdma->pVGAState->vram_size - cbDmaCmd, VERR_INVALID_PARAMETER);2423 uint8_t *pbRam = pVdma->pVGAState->vram_ptrR3;2424 pDmaCmd = (VBOXVDMACMD RT_UNTRUSTED_VOLATILE_GUEST *)(pbRam + offBuf);2425 }2426 else2427 return VINF_NOT_SUPPORTED;2428 Assert(cbDmaCmd >= VBOXVDMACMD_HEADER_SIZE()); /* checked by vbvaChannelHandler already */2429 2430 /*2431 * Check if command type is a chromium one.2432 */2433 int rc = VINF_NOT_SUPPORTED;2434 VBOXVDMACMD_TYPE const enmType = pDmaCmd->enmType;2435 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();2436 if ( enmType == VBOXVDMACMD_TYPE_CHROMIUM_CMD2437 || enmType == VBOXVDMACMD_TYPE_DMA_BPB_TRANSFER)2438 {2439 RT_UNTRUSTED_VALIDATED_FENCE();2440 2441 /*2442 * Process the Cr command.2443 */2444 uint32_t cbBody = VBOXVDMACMD_BODY_SIZE(cbDmaCmd);2445 if (enmType == VBOXVDMACMD_TYPE_CHROMIUM_CMD)2446 {2447 VBOXVDMACMD_CHROMIUM_CMD RT_UNTRUSTED_VOLATILE_GUEST *pCrCmd = VBOXVDMACMD_BODY(pDmaCmd, VBOXVDMACMD_CHROMIUM_CMD);2448 AssertReturn(cbBody >= sizeof(*pCrCmd), VERR_INVALID_PARAMETER);2449 2450 PVGASTATE pVGAState = pVdma->pVGAState;2451 if (pVGAState->pDrv->pfnCrHgsmiCommandProcess)2452 {2453 VBoxSHGSMICommandMarkAsynchCompletion(pCmdDr);2454 pVGAState->pDrv->pfnCrHgsmiCommandProcess(pVGAState->pDrv, pCrCmd, cbBody);2455 }2456 else2457 {2458 AssertFailed();2459 rc = VBoxSHGSMICommandComplete(pVdma->pHgsmi, pCmdDr);2460 AssertRC(rc);2461 }2462 rc = VINF_SUCCESS;2463 }2464 else2465 {2466 VBOXVDMACMD_DMA_BPB_TRANSFER RT_UNTRUSTED_VOLATILE_GUEST *pTransfer2467 = VBOXVDMACMD_BODY(pDmaCmd, VBOXVDMACMD_DMA_BPB_TRANSFER);2468 AssertReturn(cbBody >= sizeof(*pTransfer), VERR_INVALID_PARAMETER);2469 2470 rc = vboxVDMACmdExecBpbTransfer(pVdma, pTransfer, sizeof(*pTransfer));2471 AssertRC(rc);2472 if (RT_SUCCESS(rc))2473 {2474 pCmdDr->rc = VINF_SUCCESS;2475 rc = VBoxSHGSMICommandComplete(pVdma->pHgsmi, pCmdDr);2476 AssertRC(rc);2477 rc = VINF_SUCCESS;2478 }2479 }2480 }2481 return rc;2482 }2483 2484 /**2485 2395 * @interface_method_impl{PDMIDISPLAYVBVACALLBACKS,pfnCrHgsmiControlCompleteAsync, 2486 2396 * Some indirect completion magic, you gotta love this code! } … … 2538 2448 && (uintptr_t)(pbDstSurf + offBoth) - (uintptr_t)pbRam <= cbVRamSize - cbToCopy 2539 2449 && (uintptr_t)(pbSrcSurf + offBoth) - (uintptr_t)pbRam <= cbVRamSize - cbToCopy) 2450 { 2451 RT_UNTRUSTED_VALIDATED_FENCE(); 2540 2452 memcpy(pbDstSurf + offBoth, pbSrcSurf + offBoth, cbToCopy); 2453 } 2541 2454 else 2542 2455 return VERR_INVALID_PARAMETER; … … 2569 2482 && (uintptr_t)pbDstStart - (uintptr_t)pbRam <= cbVRamSize - cbDstLine 2570 2483 && (uintptr_t)pbSrcStart - (uintptr_t)pbRam <= cbVRamSize - cbDstLine) 2484 { 2485 RT_UNTRUSTED_VALIDATED_FENCE(); /** @todo this could potentially be buzzkiller. */ 2571 2486 memcpy(pbDstStart, pbSrcStart, cbDstLine); 2487 } 2572 2488 else 2573 2489 return VERR_INVALID_PARAMETER; … … 2631 2547 VBOXVDMACMD_DMA_PRESENT_BLT BltSafe; 2632 2548 memcpy(&BltSafe, (void const *)pBlt, RT_UOFFSETOF(VBOXVDMACMD_DMA_PRESENT_BLT, aDstSubRects)); 2633 ASMCompilerBarrier();2549 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); 2634 2550 2635 2551 AssertReturn(BltSafe.cDstSubRects < _8M, VERR_INVALID_PARAMETER); 2636 2552 uint32_t const cbBlt = RT_UOFFSETOF(VBOXVDMACMD_DMA_PRESENT_BLT, aDstSubRects[BltSafe.cDstSubRects]); 2637 2553 AssertReturn(cbBuffer >= cbBlt, VERR_INVALID_PARAMETER); 2638 2639 2554 2640 2555 /* … … 2646 2561 Assert(BltSafe.cDstSubRects); 2647 2562 2563 RT_UNTRUSTED_VALIDATED_FENCE(); 2564 2565 /* 2566 * Do the work. 2567 */ 2648 2568 //VBOXVDMA_RECTL updateRectl = {0, 0, 0, 0}; - pointless 2649 2650 2569 if (BltSafe.cDstSubRects) 2651 2570 { … … 2657 2576 dstSubRectl.width = pBlt->aDstSubRects[i].width; 2658 2577 dstSubRectl.height = pBlt->aDstSubRects[i].height; 2659 ASMCompilerBarrier();2578 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); 2660 2579 2661 2580 VBOXVDMA_RECTL srcSubRectl = dstSubRectl; … … 2708 2627 VBOXVDMACMD_DMA_BPB_TRANSFER TransferSafeCopy; 2709 2628 memcpy(&TransferSafeCopy, (void const *)pTransfer, sizeof(TransferSafeCopy)); 2710 ASMCompilerBarrier();2629 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); 2711 2630 2712 2631 PVGASTATE pVGAState = pVdma->pVGAState; … … 2727 2646 && TransferSafeCopy.Dst.offVramBuf <= pVGAState->vram_size - cbTransfer, 2728 2647 VERR_INVALID_PARAMETER); 2648 RT_UNTRUSTED_VALIDATED_FENCE(); 2729 2649 2730 2650 /* … … 2799 2719 * @param pbBuffer Command buffer, considered volatile. 2800 2720 * @param cbBuffer The number of bytes at @a pbBuffer. 2801 */ 2802 static int vboxVDMACmdExec(PVBOXVDMAHOST pVdma, const uint8_t *pbBuffer, uint32_t cbBuffer) 2721 * @param pCmdDr The command. For setting the async flag on chromium 2722 * requests. 2723 * @param pfAsyncCmd Flag to set if async command completion on chromium 2724 * requests. Input stat is false, so it only ever need to 2725 * be set to true. 2726 */ 2727 static int vboxVDMACmdExec(PVBOXVDMAHOST pVdma, const uint8_t *pbBuffer, uint32_t cbBuffer, 2728 VBOXVDMACBUF_DR RT_UNTRUSTED_VOLATILE_GUEST *pCmdDr, bool *pfAsyncCmd) 2803 2729 { 2804 2730 AssertReturn(pbBuffer, VERR_INVALID_POINTER); … … 2815 2741 case VBOXVDMACMD_TYPE_CHROMIUM_CMD: 2816 2742 { 2817 # ifdef VBOXWDDM_TEST_UHGSMI 2818 static int count = 0; 2819 static uint64_t start, end; 2820 if (count==0) 2821 { 2822 start = RTTimeNanoTS(); 2823 } 2824 ++count; 2825 if (count==100000) 2826 { 2827 end = RTTimeNanoTS(); 2828 float ems = (end-start)/1000000.f; 2829 LogRel(("100000 calls took %i ms, %i cps\n", (int)ems, (int)(100000.f*1000.f/ems) )); 2830 } 2831 # endif 2832 /** @todo post the buffer to chromium */ 2743 VBOXVDMACMD_CHROMIUM_CMD RT_UNTRUSTED_VOLATILE_GUEST *pCrCmd = VBOXVDMACMD_BODY(pCmd, VBOXVDMACMD_CHROMIUM_CMD); 2744 uint32_t const cbBody = VBOXVDMACMD_BODY_SIZE(cbBuffer); 2745 AssertReturn(cbBody >= sizeof(*pCrCmd), VERR_INVALID_PARAMETER); 2746 2747 PVGASTATE pVGAState = pVdma->pVGAState; 2748 AssertReturn(pVGAState->pDrv->pfnCrHgsmiCommandProcess, VERR_NOT_SUPPORTED); 2749 2750 VBoxSHGSMICommandMarkAsynchCompletion(pCmdDr); 2751 pVGAState->pDrv->pfnCrHgsmiCommandProcess(pVGAState->pDrv, pCrCmd, cbBody); 2752 *pfAsyncCmd = true; 2833 2753 return VINF_SUCCESS; 2834 2754 } … … 2876 2796 } 2877 2797 else 2798 { 2799 RT_UNTRUSTED_VALIDATED_FENCE(); 2878 2800 return cbProcessed; /* error status */ 2879 2801 } 2880 2802 } 2881 2803 } … … 2943 2865 * Worker for vboxVDMACommand. 2944 2866 * 2867 * @returns VBox status code of the operation. 2868 * @param pVdma VDMA instance data. 2945 2869 * @param pCmd The command to process. Consider content volatile. 2946 2870 * @param cbCmd Number of valid bytes at @a pCmd. This is at least 2947 2871 * sizeof(VBOXVDMACBUF_DR). 2872 * @param pfAsyncCmd Flag to set if async command completion on chromium 2873 * requests. Input stat is false, so it only ever need to 2874 * be set to true. 2948 2875 * @thread VDMA 2949 2876 */ 2950 static void vboxVDMACommandProcess(PVBOXVDMAHOST pVdma, VBOXVDMACBUF_DR RT_UNTRUSTED_VOLATILE_GUEST *pCmd, uint32_t cbCmd) 2951 { 2952 PHGSMIINSTANCE pHgsmi = pVdma->pHgsmi; 2953 int rc; 2954 2955 do /* break loop */ 2956 { 2957 /* 2958 * Get the command buffer (volatile). 2959 */ 2960 uint16_t const cbCmdBuf = pCmd->cbBuf; 2961 uint16_t const fCmdFlags = pCmd->fFlags; 2962 uint64_t const offVramBuf_or_GCPhysBuf = pCmd->Location.offVramBuf; 2963 AssertCompile(sizeof(pCmd->Location.offVramBuf) == sizeof(pCmd->Location.phBuf)); 2964 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); 2965 2966 const uint8_t RT_UNTRUSTED_VOLATILE_GUEST *pbCmdBuf; 2967 PGMPAGEMAPLOCK Lock; 2968 bool fReleaseLocked = false; 2969 if (fCmdFlags & VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR) 2970 { 2971 pbCmdBuf = VBOXVDMACBUF_DR_TAIL(pCmd, const uint8_t); 2972 AssertBreakStmt((uintptr_t)&pbCmdBuf[cbCmdBuf] <= (uintptr_t)&((uint8_t *)pCmd)[cbCmd], 2973 rc = VERR_INVALID_PARAMETER); 2974 RT_UNTRUSTED_VALIDATED_FENCE(); 2975 } 2976 else if (fCmdFlags & VBOXVDMACBUF_FLAG_BUF_VRAM_OFFSET) 2977 { 2978 AssertBreakStmt( offVramBuf_or_GCPhysBuf <= pVdma->pVGAState->vram_size 2979 && offVramBuf_or_GCPhysBuf + cbCmdBuf <= pVdma->pVGAState->vram_size, 2980 rc = VERR_INVALID_PARAMETER); 2981 RT_UNTRUSTED_VALIDATED_FENCE(); 2982 pbCmdBuf = (uint8_t const RT_UNTRUSTED_VOLATILE_GUEST *)pVdma->pVGAState->vram_ptrR3 + offVramBuf_or_GCPhysBuf; 2983 } 2984 else 2985 { 2986 /* Make sure it doesn't cross a page. */ 2987 AssertBreakStmt((uint32_t)(offVramBuf_or_GCPhysBuf & X86_PAGE_OFFSET_MASK) + cbCmdBuf <= (uint32_t)X86_PAGE_SIZE, 2988 rc = VERR_INVALID_PARAMETER); 2989 RT_UNTRUSTED_VALIDATED_FENCE(); 2990 2991 rc = PDMDevHlpPhysGCPhys2CCPtrReadOnly(pVdma->pVGAState->pDevInsR3, offVramBuf_or_GCPhysBuf, 0 /*fFlags*/, 2877 static int vboxVDMACommandProcess(PVBOXVDMAHOST pVdma, VBOXVDMACBUF_DR RT_UNTRUSTED_VOLATILE_GUEST *pCmd, 2878 uint32_t cbCmd, bool *pfAsyncCmd) 2879 { 2880 /* 2881 * Get the command buffer (volatile). 2882 */ 2883 uint16_t const cbCmdBuf = pCmd->cbBuf; 2884 uint16_t const fCmdFlags = pCmd->fFlags; 2885 uint64_t const offVramBuf_or_GCPhysBuf = pCmd->Location.offVramBuf; 2886 AssertCompile(sizeof(pCmd->Location.offVramBuf) == sizeof(pCmd->Location.phBuf)); 2887 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); 2888 2889 const uint8_t RT_UNTRUSTED_VOLATILE_GUEST *pbCmdBuf; 2890 PGMPAGEMAPLOCK Lock; 2891 bool fReleaseLocked = false; 2892 if (fCmdFlags & VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR) 2893 { 2894 pbCmdBuf = VBOXVDMACBUF_DR_TAIL(pCmd, const uint8_t); 2895 AssertReturn((uintptr_t)&pbCmdBuf[cbCmdBuf] <= (uintptr_t)&((uint8_t *)pCmd)[cbCmd], 2896 VERR_INVALID_PARAMETER); 2897 RT_UNTRUSTED_VALIDATED_FENCE(); 2898 } 2899 else if (fCmdFlags & VBOXVDMACBUF_FLAG_BUF_VRAM_OFFSET) 2900 { 2901 AssertReturn( offVramBuf_or_GCPhysBuf <= pVdma->pVGAState->vram_size 2902 && offVramBuf_or_GCPhysBuf + cbCmdBuf <= pVdma->pVGAState->vram_size, 2903 VERR_INVALID_PARAMETER); 2904 RT_UNTRUSTED_VALIDATED_FENCE(); 2905 2906 pbCmdBuf = (uint8_t const RT_UNTRUSTED_VOLATILE_GUEST *)pVdma->pVGAState->vram_ptrR3 + offVramBuf_or_GCPhysBuf; 2907 } 2908 else 2909 { 2910 /* Make sure it doesn't cross a page. */ 2911 AssertReturn((uint32_t)(offVramBuf_or_GCPhysBuf & X86_PAGE_OFFSET_MASK) + cbCmdBuf <= (uint32_t)X86_PAGE_SIZE, 2912 VERR_INVALID_PARAMETER); 2913 RT_UNTRUSTED_VALIDATED_FENCE(); 2914 2915 int rc = PDMDevHlpPhysGCPhys2CCPtrReadOnly(pVdma->pVGAState->pDevInsR3, offVramBuf_or_GCPhysBuf, 0 /*fFlags*/, 2992 2916 (const void **)&pbCmdBuf, &Lock); 2993 AssertRCBreak(rc); /* if (rc == VERR_PGM_PHYS_PAGE_RESERVED) -> fall back on using PGMPhysRead ?? */ 2994 fReleaseLocked = true; 2995 } 2996 2997 /* 2998 * Process the command. 2999 */ 3000 rc = vboxVDMACmdExec(pVdma, (uint8_t const *)pbCmdBuf, cbCmdBuf); /** @todo fixme later */ 3001 AssertRC(rc); 3002 3003 /* Clean up comand buffer. */ 3004 if (fReleaseLocked) 3005 PDMDevHlpPhysReleasePageMappingLock(pVdma->pVGAState->pDevInsR3, &Lock); 3006 3007 } while (0); 2917 AssertRCReturn(rc, rc); /* if (rc == VERR_PGM_PHYS_PAGE_RESERVED) -> fall back on using PGMPhysRead ?? */ 2918 fReleaseLocked = true; 2919 } 3008 2920 3009 2921 /* 3010 * Completethe command.2922 * Process the command. 3011 2923 */ 3012 pCmd->rc = rc; 3013 rc = VBoxSHGSMICommandComplete(pHgsmi, pCmd); 2924 int rc = vboxVDMACmdExec(pVdma, (uint8_t const *)pbCmdBuf, cbCmdBuf, pCmd, pfAsyncCmd); /** @todo fixme later */ 3014 2925 AssertRC(rc); 2926 2927 /* Clean up comand buffer. */ 2928 if (fReleaseLocked) 2929 PDMDevHlpPhysReleasePageMappingLock(pVdma->pVGAState->pDevInsR3, &Lock); 2930 return rc; 3015 2931 } 3016 2932 … … 3222 3138 void vboxVDMACommand(struct VBOXVDMAHOST *pVdma, VBOXVDMACBUF_DR RT_UNTRUSTED_VOLATILE_GUEST *pCmd, uint32_t cbCmd) 3223 3139 { 3140 /* 3141 * Process the command. 3142 */ 3143 bool fAsyncCmd = false; 3224 3144 #ifdef VBOX_WITH_CRHGSMI 3225 /** @todo r=bird: This detour to vboxVDMACmdCheckCrCmd is inefficient and 3226 * utterly confusing. It should instead have been added to vboxVDMACmdExec or 3227 * maybe vboxVDMACommandProcess. Try reverse engineer wtf vboxVDMACmdExec 3228 * does handle VBOXVDMACMD_TYPE_DMA_BPB_TRANSFER. Is it because of the case 3229 * where neither VBOXVDMACBUF_FLAG_BUF_VRAM_OFFSET or 3230 * VBOXVDMACMD_TYPE_DMA_BPB_TRANSFER is set? This code is certifiable!! */ 3231 3232 /* chromium commands are processed by crhomium hgcm thread independently from our internal cmd processing pipeline 3233 * this is why we process them specially */ 3234 int rc = vboxVDMACmdCheckCrCmd(pVdma, pCmd, cbCmd); 3235 if (rc == VINF_SUCCESS) 3236 return; 3237 3238 if (RT_SUCCESS(rc)) 3239 vboxVDMACommandProcess(pVdma, pCmd, cbCmd); 3240 else 3241 { 3242 pCmd->rc = rc; 3243 rc = VBoxSHGSMICommandComplete(pVdma->pHgsmi, pCmd); 3244 AssertRC(rc); 3245 } 3145 int rc = vboxVDMACommandProcess(pVdma, pCmd, cbCmd, &fAsyncCmd); 3246 3146 #else 3247 3147 RT_NOREF(cbCmd); 3248 pCmd->rc = VERR_NOT_IMPLEMENTED; 3249 int rc = VBoxSHGSMICommandComplete(pVdma->pHgsmi, pCmd); 3250 AssertRC(rc); 3148 int rc = VERR_NOT_IMPLEMENTED; 3251 3149 #endif 3150 3151 /* 3152 * Complete the command unless it's asynchronous (e.g. chromium). 3153 */ 3154 if (!fAsyncCmd) 3155 { 3156 pCmd->rc = rc; 3157 int rc2 = VBoxSHGSMICommandComplete(pVdma->pHgsmi, pCmd); 3158 AssertRC(rc2); 3159 } 3252 3160 } 3253 3161
Note:
See TracChangeset
for help on using the changeset viewer.

