VirtualBox

Changeset 71136 in vbox for trunk/src/VBox/VMM/VMMR0


Ignore:
Timestamp:
Feb 27, 2018 1:17:36 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
121023
Message:

SUPDrv,VMM/NEM/win: Abstracted kernel I/O control work in SUPDrv, currently only implemented & needed on windows. Made first I/O control call to VID from ring-0. bugref:9044

Location:
trunk/src/VBox/VMM/VMMR0
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR0/NEMR0Native-win.cpp

    r71130 r71136  
    2121*********************************************************************************************************************************/
    2222#define LOG_GROUP LOG_GROUP_NEM
     23#include <iprt/nt/nt.h>
    2324#include <iprt/nt/hyperv.h>
     25#include <iprt/nt/vid.h>
    2426
    2527#include <VBox/vmm/nem.h>
     
    5052*   Global Variables                                                                                                             *
    5153*********************************************************************************************************************************/
    52 static uint64_t (* g_pfnHvlInvokeHypercall)(uint64_t uCallInfo, uint64_t HCPhysInput, uint64_t HCPhysOutput);
     54static uint64_t (*g_pfnHvlInvokeHypercall)(uint64_t uCallInfo, uint64_t HCPhysInput, uint64_t HCPhysOutput);
    5355
    5456
     
    6466VMMR0_INT_DECL(int) NEMR0InitVM(PGVM pGVM, PVM pVM)
    6567{
     68    AssertCompile(sizeof(pGVM->nem.s) <= sizeof(pGVM->nem.padding));
     69    AssertCompile(sizeof(pGVM->aCpus[0].nem.s) <= sizeof(pGVM->aCpus[0].nem.padding));
     70
    6671    int rc = GVMMR0ValidateGVMandVMandEMT(pGVM, pVM, 0);
    6772    AssertRCReturn(rc, rc);
     
    112117             * So far, so good.
    113118             */
    114             /** @todo would be good if we could establish the partition ID ourselves. */
    115             /** @todo this is too EARLY!   */
    116             pGVM->nem.s.idHvPartition = pVM->nem.s.idHvPartition;
    117119            return rc;
    118120        }
     
    122124
    123125    RT_NOREF(pGVM, pVM);
     126    return rc;
     127}
     128
     129
     130/**
     131 * Perform an I/O control operation on the partition handle (VID.SYS).
     132 *
     133 * @returns NT status code.
     134 * @param   pGVM            The ring-0 VM structure.
     135 * @param   uFunction       The function to perform.
     136 * @param   pvInput         The input buffer.  This must point within the VM
     137 *                          structure so we can easily convert to a ring-3
     138 *                          pointer if necessary.
     139 * @param   cbInput         The size of the input.  @a pvInput must be NULL when
     140 *                          zero.
     141 * @param   pvOutput        The output buffer.  This must also point within the
     142 *                          VM structure for ring-3 pointer magic.
     143 * @param   cbOutput        The size of the output.  @a pvOutput must be NULL
     144 *                          when zero.
     145 */
     146DECLINLINE(NTSTATUS) nemR0NtPerformIoControl(PGVM pGVM, uint32_t uFunction, void *pvInput, uint32_t cbInput,
     147                                             void *pvOutput, uint32_t cbOutput)
     148{
     149#ifdef RT_STRICT
     150    /*
     151     * Input and output parameters are part of the VM CPU structure.
     152     */
     153    PVM          pVM  = pGVM->pVM;
     154    size_t const cbVM = RT_UOFFSETOF(VM, aCpus[pGVM->cCpus]);
     155    if (pvInput)
     156        AssertReturn(((uintptr_t)pvInput + cbInput) - (uintptr_t)pVM <= cbVM, VERR_INVALID_PARAMETER);
     157    if (pvOutput)
     158        AssertReturn(((uintptr_t)pvOutput + cbOutput) - (uintptr_t)pVM <= cbVM, VERR_INVALID_PARAMETER);
     159#endif
     160
     161    int32_t rcNt = STATUS_UNSUCCESSFUL;
     162    int rc = SUPR0IoCtlPerform(pGVM->nem.s.pIoCtlCtx, uFunction,
     163                               pvInput,
     164                               pvInput  ? (uintptr_t)pvInput  + pGVM->nem.s.offRing3ConversionDelta : NIL_RTR3PTR,
     165                               cbInput,
     166                               pvOutput,
     167                               pvOutput ? (uintptr_t)pvOutput + pGVM->nem.s.offRing3ConversionDelta : NIL_RTR3PTR,
     168                               cbOutput,
     169                               &rcNt);
     170    if (RT_SUCCESS(rc) || !NT_SUCCESS((NTSTATUS)rcNt))
     171        return (NTSTATUS)rcNt;
     172    return STATUS_UNSUCCESSFUL;
     173}
     174
     175
     176/**
     177 * 2nd part of the initialization, after we've got a partition handle.
     178 *
     179 * @returns VBox status code.
     180 * @param   pGVM            The ring-0 VM handle.
     181 * @param   pVM             The cross context VM handle.
     182 * @thread  EMT(0)
     183 */
     184VMMR0_INT_DECL(int) NEMR0InitVMPart2(PGVM pGVM, PVM pVM)
     185{
     186    int rc = GVMMR0ValidateGVMandVMandEMT(pGVM, pVM, 0);
     187    AssertRCReturn(rc, rc);
     188    SUPR0Printf("NEMR0InitVMPart2\n"); LogRel(("2: NEMR0InitVMPart2\n"));
     189
     190    /*
     191     * Copy and validate the I/O control information from ring-3.
     192     */
     193    NEMWINIOCTL Copy = pVM->nem.s.IoCtlGetHvPartitionId;
     194    AssertLogRelReturn(Copy.uFunction != 0, VERR_NEM_INIT_FAILED);
     195    AssertLogRelReturn(Copy.cbInput == 0, VERR_NEM_INIT_FAILED);
     196    AssertLogRelReturn(Copy.cbOutput == sizeof(HV_PARTITION_ID), VERR_NEM_INIT_FAILED);
     197    pGVM->nem.s.IoCtlGetHvPartitionId = Copy;
     198
     199    Copy = pVM->nem.s.IoCtlStartVirtualProcessor;
     200    AssertLogRelReturn(Copy.uFunction != 0, VERR_NEM_INIT_FAILED);
     201    AssertLogRelReturn(Copy.cbInput == sizeof(HV_VP_INDEX), VERR_NEM_INIT_FAILED);
     202    AssertLogRelReturn(Copy.cbOutput == 0, VERR_NEM_INIT_FAILED);
     203    AssertLogRelReturn(Copy.uFunction != pGVM->nem.s.IoCtlGetHvPartitionId.uFunction, VERR_NEM_INIT_FAILED);
     204    pGVM->nem.s.IoCtlStartVirtualProcessor = Copy;
     205
     206    Copy = pVM->nem.s.IoCtlStopVirtualProcessor;
     207    AssertLogRelReturn(Copy.uFunction != 0, VERR_NEM_INIT_FAILED);
     208    AssertLogRelReturn(Copy.cbInput == sizeof(HV_VP_INDEX), VERR_NEM_INIT_FAILED);
     209    AssertLogRelReturn(Copy.cbOutput == 0, VERR_NEM_INIT_FAILED);
     210    AssertLogRelReturn(Copy.uFunction != pGVM->nem.s.IoCtlGetHvPartitionId.uFunction, VERR_NEM_INIT_FAILED);
     211    AssertLogRelReturn(Copy.uFunction != pGVM->nem.s.IoCtlStartVirtualProcessor.uFunction, VERR_NEM_INIT_FAILED);
     212    pGVM->nem.s.IoCtlStopVirtualProcessor = Copy;
     213
     214    Copy = pVM->nem.s.IoCtlMessageSlotHandleAndGetNext;
     215    AssertLogRelReturn(Copy.uFunction != 0, VERR_NEM_INIT_FAILED);
     216    AssertLogRelReturn(Copy.cbInput == sizeof(VID_IOCTL_INPUT_MESSAGE_SLOT_HANDLE_AND_GET_NEXT), VERR_NEM_INIT_FAILED);
     217    AssertLogRelReturn(Copy.cbOutput == 0, VERR_NEM_INIT_FAILED);
     218    AssertLogRelReturn(Copy.uFunction != pGVM->nem.s.IoCtlGetHvPartitionId.uFunction, VERR_NEM_INIT_FAILED);
     219    AssertLogRelReturn(Copy.uFunction != pGVM->nem.s.IoCtlStartVirtualProcessor.uFunction, VERR_NEM_INIT_FAILED);
     220    AssertLogRelReturn(Copy.uFunction != pGVM->nem.s.IoCtlStopVirtualProcessor.uFunction, VERR_NEM_INIT_FAILED);
     221    pGVM->nem.s.IoCtlMessageSlotHandleAndGetNext = Copy;
     222
     223    /*
     224     * Setup of an I/O control context for the partition handle for later use.
     225     */
     226    rc = SUPR0IoCtlSetupForHandle(pGVM->pSession, pVM->nem.s.hPartitionDevice, 0, &pGVM->nem.s.pIoCtlCtx);
     227    AssertLogRelRCReturn(rc, rc);
     228    pGVM->nem.s.offRing3ConversionDelta = (uintptr_t)pVM->pVMR3 - (uintptr_t)pGVM->pVM;
     229
     230    /*
     231     * Get the partition ID.
     232     */
     233    PVMCPU pVCpu = &pGVM->pVM->aCpus[0];
     234    NTSTATUS rcNt = nemR0NtPerformIoControl(pGVM, pGVM->nem.s.IoCtlGetHvPartitionId.uFunction, NULL, 0,
     235                                            &pVCpu->nem.s.uIoCtlBuf.idPartition, sizeof(pVCpu->nem.s.uIoCtlBuf.idPartition));
     236    AssertLogRelMsgReturn(NT_SUCCESS(rcNt), ("IoCtlGetHvPartitionId failed: %#x\n", rcNt), VERR_NEM_INIT_FAILED);
     237    pGVM->nem.s.idHvPartition = pVCpu->nem.s.uIoCtlBuf.idPartition;
     238    AssertLogRelMsgReturn(pGVM->nem.s.idHvPartition == pVM->nem.s.idHvPartition,
     239                          ("idHvPartition mismatch: r0=%#RX64, r3=%#RX64\n", pGVM->nem.s.idHvPartition, pVM->nem.s.idHvPartition),
     240                          VERR_NEM_INIT_FAILED);
     241
     242
    124243    return rc;
    125244}
     
    137256{
    138257    pGVM->nem.s.idHvPartition = HV_PARTITION_ID_INVALID;
     258
     259    /* Clean up I/O control context. */
     260    if (pGVM->nem.s.pIoCtlCtx)
     261    {
     262        int rc = SUPR0IoCtlCleanup(pGVM->nem.s.pIoCtlCtx);
     263        AssertRC(rc);
     264        pGVM->nem.s.pIoCtlCtx = NULL;
     265    }
    139266
    140267    /* Free the hypercall pages. */
     
    195322            AssertReturn(GCPhysSrc < _1E, VERR_OUT_OF_RANGE);
    196323        }
    197 
    198         /** @todo fix pGVM->nem.s.idHvPartition init. */
    199         if (pGVM->nem.s.idHvPartition == 0)
    200             pGVM->nem.s.idHvPartition = pVM->nem.s.idHvPartition;
    201324
    202325        /*
     
    291414        AssertMsgReturn(!(GCPhys & X86_PAGE_OFFSET_MASK), ("%RGp\n", GCPhys), VERR_OUT_OF_RANGE);
    292415        AssertReturn(GCPhys < _1E, VERR_OUT_OF_RANGE);
    293 
    294         /** @todo fix pGVM->nem.s.idHvPartition init. */
    295         if (pGVM->nem.s.idHvPartition == 0)
    296             pGVM->nem.s.idHvPartition = pVM->nem.s.idHvPartition;
    297416
    298417        /*
     
    732851        AssertReturn(g_pfnHvlInvokeHypercall, VERR_NEM_MISSING_KERNEL_API);
    733852
    734         /** @todo fix pGVM->nem.s.idHvPartition init. */
    735         if (pGVM->nem.s.idHvPartition == 0)
    736             pGVM->nem.s.idHvPartition = pVM->nem.s.idHvPartition;
    737 
    738853        /*
    739854         * Call worker.
     
    11461261        AssertReturn(g_pfnHvlInvokeHypercall, VERR_NEM_MISSING_KERNEL_API);
    11471262
    1148         /** @todo fix pGVM->nem.s.idHvPartition init. */
    1149         if (pGVM->nem.s.idHvPartition == 0)
    1150             pGVM->nem.s.idHvPartition = pVM->nem.s.idHvPartition;
    1151 
    11521263        /*
    11531264         * Call worker.
  • trunk/src/VBox/VMM/VMMR0/VMMR0.cpp

    r71087 r71136  
    19751975            break;
    19761976
     1977        case VMMR0_DO_NEM_INIT_VM_PART_2:
     1978            if (u64Arg || pReqHdr || idCpu != 0)
     1979                return VERR_INVALID_PARAMETER;
     1980            rc = NEMR0InitVMPart2(pGVM, pVM);
     1981            VMM_CHECK_SMAP_CHECK2(pVM, RT_NOTHING);
     1982            break;
     1983
    19771984        case VMMR0_DO_NEM_MAP_PAGES:
    19781985            if (u64Arg || pReqHdr || idCpu == NIL_VMCPUID)
Note: See TracChangeset for help on using the changeset viewer.

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