VirtualBox

Changeset 71136 in vbox


Ignore:
Timestamp:
Feb 27, 2018 1:17:36 PM (7 years ago)
Author:
vboxsync
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
Files:
16 edited

Legend:

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

    r70918 r71136  
    19271927SUPR0DECL(void) SUPR0BadContext(PSUPDRVSESSION pSession, const char *pszFile, uint32_t uLine, const char *pszExpr);
    19281928
     1929/** Context structure returned by SUPR0IoCtlSetup for use with
     1930 * SUPR0IoCtlPerform and cleaned up by SUPR0IoCtlCleanup. */
     1931typedef struct SUPR0IOCTLCTX *PSUPR0IOCTLCTX;
     1932
     1933/**
     1934 * Sets up a I/O control context for the given handle.
     1935 *
     1936 * @returns VBox status code.
     1937 * @param   pSession        The support driver session.
     1938 * @param   hHandle         The handle.
     1939 * @param   fFlags          Flag, MBZ.
     1940 * @param   ppCtx           Where the context is returned.
     1941 */
     1942SUPR0DECL(int) SUPR0IoCtlSetupForHandle(PSUPDRVSESSION pSession, intptr_t hHandle, uint32_t fFlags, PSUPR0IOCTLCTX *ppCtx);
     1943
     1944/**
     1945 * Cleans up the I/O control context when done.
     1946 *
     1947 * This won't close the handle passed to SUPR0IoCtlSetupForHandle.
     1948 *
     1949 * @returns VBox status code.
     1950 * @param   pCtx            The I/O control context to cleanup.
     1951 */
     1952SUPR0DECL(int) SUPR0IoCtlCleanup(PSUPR0IOCTLCTX pCtx);
     1953
     1954/**
     1955 * Performs an I/O control operation.
     1956 *
     1957 * @returns VBox status code.
     1958 * @param   pCtx            The I/O control context returned by
     1959 *                          SUPR0IoCtlSetupForHandle.
     1960 * @param   uFunction       The I/O control function to perform.
     1961 * @param   pvInput         Pointer to input buffer (ring-0).
     1962 * @param   pvInputUser     Ring-3 pointer corresponding to @a pvInput.
     1963 * @param   cbInput         The amount of input.  If zero, both input pointers
     1964 *                          are expected to be NULL.
     1965 * @param   pvOutput        Pointer to output buffer (ring-0).
     1966 * @param   pvOutputUser    Ring-3 pointer corresponding to @a pvInput.
     1967 * @param   cbOutput        The amount of input.  If zero, both input pointers
     1968 *                          are expected to be NULL.
     1969 * @param   piNativeRc      Where to return the native return code.   When
     1970 *                          specified the VBox status code will typically be
     1971 *                          VINF_SUCCESS and the caller have to consult this for
     1972 *                          the actual result of the operation.  (This saves
     1973 *                          pointless status code conversion.)  Optional.
     1974 *
     1975 * @note    On unix systems where there is only one set of buffers possible,
     1976 *          pass the same pointers as input and output.
     1977 */
     1978SUPR0DECL(int)  SUPR0IoCtlPerform(PSUPR0IOCTLCTX pCtx, uintptr_t uFunction,
     1979                                  void *pvInput, RTR3PTR pvInputUser, size_t cbInput,
     1980                                  void *pvOutput, RTR3PTR pvOutputUser, size_t cbOutput,
     1981                                  int32_t *piNativeRc);
     1982
    19291983/**
    19301984 * Writes to the debugger and/or kernel log.
  • trunk/include/VBox/vmm/gvm.h

    r71075 r71136  
    125125        struct NEMR0PERVM   s;
    126126# endif
    127         uint8_t             padding[64];
     127        uint8_t             padding[128];
    128128    } nem;
    129129#endif
  • trunk/include/VBox/vmm/nem.h

    r71087 r71136  
    8484 * @{  */
    8585VMMR0_INT_DECL(int)  NEMR0InitVM(PGVM pGVM, PVM pVM);
     86VMMR0_INT_DECL(int)  NEMR0InitVMPart2(PGVM pGVM, PVM pVM);
    8687VMMR0_INT_DECL(void) NEMR0CleanupVM(PGVM pGVM);
    8788VMMR0_INT_DECL(int)  NEMR0MapPages(PGVM pGVM, PVM pVM, VMCPUID idCpu);
  • trunk/include/VBox/vmm/vmm.h

    r71087 r71136  
    432432    /** Call NEMR0InitVM() (host specific). */
    433433    VMMR0_DO_NEM_INIT_VM = 576,
     434    /** Call NEMR0InitVMPart2() (host specific). */
     435    VMMR0_DO_NEM_INIT_VM_PART_2,
    434436    /** Call NEMR0MapPages() (host specific). */
    435437    VMMR0_DO_NEM_MAP_PAGES,
  • trunk/include/iprt/nt/vid.h

    r71131 r71136  
    108108typedef VID_IOCTL_INPUT_MESSAGE_SLOT_HANDLE_AND_GET_NEXT const *PCVID_IOCTL_INPUT_MESSAGE_SLOT_HANDLE_AND_GET_NEXT;
    109109
    110 
    111 RT_C_DECLS_BEGIN
    112 
    113 /** Calling convention. */
    114 #ifndef WINAPI
    115 # define VIDAPI __stdcall
    116 #else
    117 # define VIDAPI WINAPI
    118 #endif
    119 
    120 /** Partition handle. */
    121 #ifndef WINAPI
    122 typedef void *VID_PARTITION_HANDLE;
    123 #else
    124 typedef HANDLE VID_PARTITION_HANDLE;
    125 #endif
    126 
    127 /**
    128  * Gets the partition ID.
    129  *
    130  * The partition ID is the numeric identifier used when making hypercalls to the
    131  * hypervisor.
    132  */
    133 DECLIMPORT(BOOL) VIDAPI VidGetHvPartitionId(VID_PARTITION_HANDLE hPartition, HV_PARTITION_ID *pidPartition);
    134 
    135 /**
    136  * Starts asynchronous execution of a virtual CPU.
    137  */
    138 DECLIMPORT(BOOL) VIDAPI VidStartVirtualProcessor(VID_PARTITION_HANDLE hPartition, HV_VP_INDEX iCpu);
    139 
    140 /**
    141  * Stops the asynchronous execution of a virtual CPU.
    142  *
    143  * @retval ERROR_VID_STOP_PENDING if busy with intercept, check messages.
    144  */
    145 DECLIMPORT(BOOL) VIDAPI VidStopVirtualProcessor(VID_PARTITION_HANDLE hPartition, HV_VP_INDEX iCpu);
    146 
    147 /**
    148  * WHvCreateVirtualProcessor boils down to a call to VidMessageSlotMap and
    149  * some internal WinHvPlatform state fiddling.
    150  *
    151  * Looks like it maps memory and returns the pointer to it.
    152  * VidMessageSlotHandleAndGetNext is later used to wait for the next message and
    153  * put (??) it into that memory mapping.
    154  *
    155  * @returns Success indicator (details in LastStatusValue and LastErrorValue).
    156  *
    157  * @param   hPartition  The partition handle.
    158  * @param   pOutput     Where to return the pointer to the message memory
    159  *                      mapping.  The CPU index is also returned here.
    160  * @param   iCpu        The CPU to wait-and-get messages for.
    161  */
    162 DECLIMPORT(BOOL) VIDAPI VidMessageSlotMap(VID_PARTITION_HANDLE hPartition, PVID_MAPPED_MESSAGE_SLOT pOutput, HV_VP_INDEX iCpu);
    163 
    164 /**
    165  * This is used by WHvRunVirtualProcessor to wait for the next exit msg.
    166  *
    167  * The message appears in the memory mapping returned by VidMessageSlotMap.
    168  *
    169  * @returns Success indicator (details only in LastErrorValue - LastStatusValue
    170  *          is not set).
    171  * @retval  STATUS_TIMEOUT for STATUS_TIMEOUT as well as STATUS_USER_APC and
    172  *          STATUS_ALERTED.
    173  *
    174  * @param   hPartition  The partition handle.
    175  * @param   iCpu        The CPU to wait-and-get messages for.
    176  * @param   fFlags      Flags. At least one of the two flags must be set:
    177  *                          - VID_MSHAGN_F_GET_NEXT_MESSAGE (bit 0)
    178  *                          - VID_MSHAGN_F_HANDLE_MESSAGE (bit 1)
    179  * @param   cMillies    The timeout, presumably in milliseconds.
    180  *
    181  * @todo    Would be awfully nice if someone at Microsoft could hit at the
    182  *          flags here.
    183  * @note
    184  */
    185 DECLIMPORT(BOOL) VIDAPI VidMessageSlotHandleAndGetNext(VID_PARTITION_HANDLE hPartition, HV_VP_INDEX iCpu,
    186                                                        uint32_t fFlags, uint32_t cMillies);
    187110/** @name VID_MSHAGN_F_GET_XXX - Flags for VidMessageSlotHandleAndGetNext
    188111 * @{ */
     
    196119/** @} */
    197120
     121
     122#ifdef IN_RING3
     123RT_C_DECLS_BEGIN
     124
     125/** Calling convention. */
     126#ifndef WINAPI
     127# define VIDAPI __stdcall
     128#else
     129# define VIDAPI WINAPI
     130#endif
     131
     132/** Partition handle. */
     133#ifndef WINAPI
     134typedef void *VID_PARTITION_HANDLE;
     135#else
     136typedef HANDLE VID_PARTITION_HANDLE;
     137#endif
     138
     139/**
     140 * Gets the partition ID.
     141 *
     142 * The partition ID is the numeric identifier used when making hypercalls to the
     143 * hypervisor.
     144 */
     145DECLIMPORT(BOOL) VIDAPI VidGetHvPartitionId(VID_PARTITION_HANDLE hPartition, HV_PARTITION_ID *pidPartition);
     146
     147/**
     148 * Starts asynchronous execution of a virtual CPU.
     149 */
     150DECLIMPORT(BOOL) VIDAPI VidStartVirtualProcessor(VID_PARTITION_HANDLE hPartition, HV_VP_INDEX iCpu);
     151
     152/**
     153 * Stops the asynchronous execution of a virtual CPU.
     154 *
     155 * @retval ERROR_VID_STOP_PENDING if busy with intercept, check messages.
     156 */
     157DECLIMPORT(BOOL) VIDAPI VidStopVirtualProcessor(VID_PARTITION_HANDLE hPartition, HV_VP_INDEX iCpu);
     158
     159/**
     160 * WHvCreateVirtualProcessor boils down to a call to VidMessageSlotMap and
     161 * some internal WinHvPlatform state fiddling.
     162 *
     163 * Looks like it maps memory and returns the pointer to it.
     164 * VidMessageSlotHandleAndGetNext is later used to wait for the next message and
     165 * put (??) it into that memory mapping.
     166 *
     167 * @returns Success indicator (details in LastStatusValue and LastErrorValue).
     168 *
     169 * @param   hPartition  The partition handle.
     170 * @param   pOutput     Where to return the pointer to the message memory
     171 *                      mapping.  The CPU index is also returned here.
     172 * @param   iCpu        The CPU to wait-and-get messages for.
     173 */
     174DECLIMPORT(BOOL) VIDAPI VidMessageSlotMap(VID_PARTITION_HANDLE hPartition, PVID_MAPPED_MESSAGE_SLOT pOutput, HV_VP_INDEX iCpu);
     175
     176/**
     177 * This is used by WHvRunVirtualProcessor to wait for the next exit msg.
     178 *
     179 * The message appears in the memory mapping returned by VidMessageSlotMap.
     180 *
     181 * @returns Success indicator (details only in LastErrorValue - LastStatusValue
     182 *          is not set).
     183 * @retval  STATUS_TIMEOUT for STATUS_TIMEOUT as well as STATUS_USER_APC and
     184 *          STATUS_ALERTED.
     185 *
     186 * @param   hPartition  The partition handle.
     187 * @param   iCpu        The CPU to wait-and-get messages for.
     188 * @param   fFlags      Flags. At least one of the two flags must be set:
     189 *                          - VID_MSHAGN_F_GET_NEXT_MESSAGE (bit 0)
     190 *                          - VID_MSHAGN_F_HANDLE_MESSAGE (bit 1)
     191 * @param   cMillies    The timeout, presumably in milliseconds.
     192 *
     193 * @todo    Would be awfully nice if someone at Microsoft could hit at the
     194 *          flags here.
     195 * @note
     196 */
     197DECLIMPORT(BOOL) VIDAPI VidMessageSlotHandleAndGetNext(VID_PARTITION_HANDLE hPartition, HV_VP_INDEX iCpu,
     198                                                       uint32_t fFlags, uint32_t cMillies);
    198199/**
    199200 * Gets the processor running status.
     
    219220
    220221RT_C_DECLS_END
     222#endif /* IN_RING3 */
    221223
    222224#endif
  • trunk/src/VBox/HostDrivers/Support/SUPDrv.cpp

    r71075 r71136  
    231231    { "SUPR0TracerUmodProbeFire",               (void *)(uintptr_t)SUPR0TracerUmodProbeFire },
    232232    { "SUPR0UnlockMem",                         (void *)(uintptr_t)SUPR0UnlockMem },
     233#ifdef RT_OS_WINDOWS
     234    { "SUPR0IoCtlSetupForHandle",               (void *)(uintptr_t)SUPR0IoCtlSetupForHandle },  /* only-windows */
     235    { "SUPR0IoCtlPerform",                      (void *)(uintptr_t)SUPR0IoCtlPerform },         /* only-windows */
     236    { "SUPR0IoCtlCleanup",                      (void *)(uintptr_t)SUPR0IoCtlCleanup },         /* only-windows */
     237#endif
    233238    { "SUPSemEventClose",                       (void *)(uintptr_t)SUPSemEventClose },
    234239    { "SUPSemEventCreate",                      (void *)(uintptr_t)SUPSemEventCreate },
  • trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h

    r71075 r71136  
    214214 * @remarks 0x002a0000 is used by 5.1. The next version number must be 0x002b0000.
    215215 */
    216 #define SUPDRV_IOC_VERSION                              0x00290002
     216#define SUPDRV_IOC_VERSION                              0x00290003
    217217
    218218/** SUP_IOCTL_COOKIE. */
  • trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h

    r70917 r71136  
    455455    uint32_t volatile               cUsage;
    456456} SUPDRVUSAGE, *PSUPDRVUSAGE;
     457
     458
     459/**
     460 * I/O control context.
     461 */
     462typedef struct SUPR0IOCTLCTX
     463{
     464    /** Magic value (SUPR0IOCTLCTX_MAGIC). */
     465    uint32_t                u32Magic;
     466    /** Reference counter. */
     467    uint32_t volatile       cRefs;
     468#ifdef RT_OS_WINDOWS
     469# ifndef SUPDRV_AGNOSTIC
     470    /** The file object, referenced. */
     471    PFILE_OBJECT            pFileObject;
     472    /** The device object, not referenced. */
     473    PDEVICE_OBJECT          pDeviceObject;
     474    /** Pointer to fast I/O routine if available. */
     475    FAST_IO_DEVICE_CONTROL *pfnFastIoDeviceControl;
     476# else
     477    void                   *apvPadding[3];
     478# endif
     479#endif
     480} SUPR0IOCTLCTX;
     481/** Magic value for SUPR0IOCTLCTX (Ahmad Jamal). */
     482#define SUPR0IOCTLCTX_MAGIC     UINT32_C(0x19300702)
    457483
    458484
  • trunk/src/VBox/HostDrivers/Support/SUPLib.cpp

    r71075 r71136  
    277277        CookieReq.u.In.u32ReqVersion = SUPDRV_IOC_VERSION;
    278278        const uint32_t uMinVersion = (SUPDRV_IOC_VERSION & 0xffff0000) == 0x00290000
    279                                    ? 0x00290002
     279                                   ? 0x00290003
    280280                                   : SUPDRV_IOC_VERSION & 0xffff0000;
    281281        CookieReq.u.In.u32MinVersion = uMinVersion;
  • trunk/src/VBox/HostDrivers/Support/SUPLibLdr.cpp

    r69500 r71136  
    167167     * Only SUPR0 and VMMR0.r0
    168168     */
    169     if (    pszModule
    170         &&  *pszModule
    171         &&  strcmp(pszModule, "VBoxDrv.sys")
    172         &&  strcmp(pszModule, "VMMR0.r0"))
    173     {
     169    if (   pszModule
     170        && *pszModule
     171        && strcmp(pszModule, "VBoxDrv.sys")
     172        && strcmp(pszModule, "VMMR0.r0"))
     173    {
     174#if defined(RT_OS_WINDOWS) && 0 /* Useful for VMMR0 hacking, not for production use.  See also SUPDrv-win.cpp */
     175        if (strcmp(pszModule, "ntoskrnl.exe") == 0)
     176        {
     177            *pValue = 42; /* Non-zero so ring-0 can find the end of the IAT and exclude it when comparing. */
     178            return VINF_SUCCESS;
     179        }
     180#endif
    174181        AssertMsgFailed(("%s is importing from %s! (expected 'SUPR0.dll' or 'VMMR0.r0', case-sensitive)\n", pArgs->pszModule, pszModule));
    175182        return RTErrInfoSetF(pArgs->pErrInfo, VERR_SYMBOL_NOT_FOUND,
  • trunk/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp

    r70917 r71136  
    21312131}
    21322132
     2133/** Image compare exclusion regions. */
     2134typedef struct SUPDRVNTEXCLREGIONS
     2135{
     2136    /** Number of regions.   */
     2137    uint32_t        cRegions;
     2138    /** The regions. */
     2139    struct SUPDRVNTEXCLREGION
     2140    {
     2141        uint32_t    uRva;
     2142        uint32_t    cb;
     2143    }               aRegions[16];
     2144} SUPDRVNTEXCLREGIONS;
     2145
     2146/**
     2147 * Adds an exclusion region to the collection.
     2148 */
     2149static bool supdrvNtAddExclRegion(SUPDRVNTEXCLREGIONS *pRegions, uint32_t uRvaRegion, uint32_t cbRegion)
     2150{
     2151    uint32_t const cRegions = pRegions->cRegions;
     2152    AssertReturn(cRegions + 1 <= RT_ELEMENTS(pRegions->aRegions), false);
     2153    uint32_t i = 0;
     2154    for (; i < cRegions; i++)
     2155        if (uRvaRegion < pRegions->aRegions[i].uRva)
     2156            break;
     2157    if (i != cRegions)
     2158        memmove(&pRegions->aRegions[i + 1], &pRegions->aRegions[i], (cRegions - i) * sizeof(pRegions->aRegions[0]));
     2159    pRegions->aRegions[i].uRva = uRvaRegion;
     2160    pRegions->aRegions[i].cb   = cbRegion;
     2161    pRegions->cRegions++;
     2162    return true;
     2163}
     2164
    21332165
    21342166int  VBOXCALL   supdrvOSLdrLoad(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const uint8_t *pbImageBits, PSUPLDRLOAD pReq)
     
    21842216            )
    21852217        {
    2186             struct MyRegion
    2187             {
    2188                 uint32_t uRva;
    2189                 uint32_t cb;
    2190             }           aExcludeRgns[16];
    2191             unsigned    cExcludeRgns = 0;
     2218            SUPDRVNTEXCLREGIONS ExcludeRegions;
     2219            ExcludeRegions.cRegions = 0;
    21922220
    21932221            /* ImageBase: */
     
    21952223                && (   pNtHdrsNtLd->OptionalHeader.ImageBase == (uintptr_t)pImage->pvImage
    21962224                    || pNtHdrsIprt->OptionalHeader.ImageBase == (uintptr_t)pImage->pvImage) )
    2197             {
    2198                 aExcludeRgns[cExcludeRgns].uRva = offImageBase;
    2199                 aExcludeRgns[cExcludeRgns].cb   = cbImageBase;
    2200                 cExcludeRgns++;
    2201             }
     2225                supdrvNtAddExclRegion(&ExcludeRegions, offImageBase, cbImageBase);
    22022226
    22032227            /* Imports: */
     
    22082232            IMAGE_IMPORT_DESCRIPTOR const *pImp = (IMAGE_IMPORT_DESCRIPTOR const *)(pbImageBits + offImps);
    22092233            while (   cImpsLeft-- > 0
    2210                    && cExcludeRgns < RT_ELEMENTS(aExcludeRgns))
     2234                   && ExcludeRegions.cRegions < RT_ELEMENTS(ExcludeRegions.aRegions))
    22112235            {
    22122236                uint32_t uRvaThunk = pImp->OriginalFirstThunk;
    2213                 if (    uRvaThunk >  sizeof(IMAGE_NT_HEADERS)
    2214                     &&  uRvaThunk <= pImage->cbImageBits - sizeof(IMAGE_THUNK_DATA)
    2215                     &&  uRvaThunk != pImp->FirstThunk)
     2237                if (   uRvaThunk >  sizeof(IMAGE_NT_HEADERS)
     2238                    && uRvaThunk <= pImage->cbImageBits - sizeof(IMAGE_THUNK_DATA)
     2239                    && uRvaThunk != pImp->FirstThunk)
    22162240                {
    22172241                    /* Find the size of the thunk table. */
     
    22212245                    while (cThunks < cMaxThunks && paThunk[cThunks].u1.Function != 0)
    22222246                        cThunks++;
    2223 
    2224                     /* Ordered table insert. */
    2225                     unsigned i = 0;
    2226                     for (; i < cExcludeRgns; i++)
    2227                         if (uRvaThunk < aExcludeRgns[i].uRva)
    2228                             break;
    2229                     if (i != cExcludeRgns)
    2230                         memmove(&aExcludeRgns[i + 1], &aExcludeRgns[i], (cExcludeRgns - i) * sizeof(aExcludeRgns[0]));
    2231                     aExcludeRgns[i].uRva = uRvaThunk;
    2232                     aExcludeRgns[i].cb   = cThunks * sizeof(IMAGE_THUNK_DATA);
    2233                     cExcludeRgns++;
     2247                    supdrvNtAddExclRegion(&ExcludeRegions, uRvaThunk, cThunks * sizeof(IMAGE_THUNK_DATA));
    22342248                }
     2249
     2250#if 0 /* Useful for VMMR0 hacking, not for production use.  See also SUPDrvLdr.cpp. */
     2251                /* Exclude the other thunk table if ntoskrnl.exe. */
     2252                uint32_t uRvaName = pImp->Name;
     2253                if (   uRvaName > sizeof(IMAGE_NT_HEADERS)
     2254                    && uRvaName < pImage->cbImageBits - sizeof("ntoskrnl.exe")
     2255                    && memcmp(&pbImageBits[uRvaName], RT_STR_TUPLE("ntoskrnl.exe")) == 0)
     2256                {
     2257                    uRvaThunk = pImp->FirstThunk;
     2258                    if (   uRvaThunk >  sizeof(IMAGE_NT_HEADERS)
     2259                        && uRvaThunk <= pImage->cbImageBits - sizeof(IMAGE_THUNK_DATA))
     2260                    {
     2261                        /* Find the size of the thunk table. */
     2262                        IMAGE_THUNK_DATA const *paThunk    = (IMAGE_THUNK_DATA const *)(pbImageBits + uRvaThunk);
     2263                        uint32_t                cMaxThunks = (pImage->cbImageBits - uRvaThunk) / sizeof(IMAGE_THUNK_DATA);
     2264                        uint32_t                cThunks    = 0;
     2265                        while (cThunks < cMaxThunks && paThunk[cThunks].u1.Function != 0)
     2266                            cThunks++;
     2267                        supdrvNtAddExclRegion(&ExcludeRegions, uRvaThunk, cThunks * sizeof(IMAGE_THUNK_DATA));
     2268                    }
     2269                }
     2270#endif
    22352271
    22362272                /* advance */
     
    22432279            int         iDiff    = 0;
    22442280            uint32_t    uRvaNext = 0;
    2245             for (unsigned i = 0; !iDiff && i < cExcludeRgns; i++)
    2246             {
    2247                 if (uRvaNext < aExcludeRgns[i].uRva)
    2248                     iDiff = supdrvNtCompare(pImage, pbImageBits, uRvaNext, aExcludeRgns[i].uRva - uRvaNext, pReq);
    2249                 uRvaNext = aExcludeRgns[i].uRva + aExcludeRgns[i].cb;
     2281            for (unsigned i = 0; !iDiff && i < ExcludeRegions.cRegions; i++)
     2282            {
     2283                if (uRvaNext < ExcludeRegions.aRegions[i].uRva)
     2284                    iDiff = supdrvNtCompare(pImage, pbImageBits, uRvaNext, ExcludeRegions.aRegions[i].uRva - uRvaNext, pReq);
     2285                uRvaNext = ExcludeRegions.aRegions[i].uRva + ExcludeRegions.aRegions[i].cb;
    22502286            }
    22512287            if (!iDiff && uRvaNext < pImage->cbImageBits)
     
    25582594{
    25592595    return 0;
     2596}
     2597
     2598
     2599SUPR0DECL(int) SUPR0IoCtlSetupForHandle(PSUPDRVSESSION pSession, intptr_t hHandle, uint32_t fFlags, PSUPR0IOCTLCTX *ppCtx)
     2600{
     2601    /*
     2602     * Validate input.
     2603     */
     2604    AssertPtrReturn(ppCtx, VERR_INVALID_POINTER);
     2605    *ppCtx = NULL;
     2606    AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
     2607    AssertReturn(!fFlags, VERR_INVALID_FLAGS);
     2608
     2609    /*
     2610     * Turn the partition handle into a file object and related device object
     2611     * so that we can issue direct I/O control calls to the pair later.
     2612     */
     2613    PFILE_OBJECT pFileObject = NULL;
     2614    OBJECT_HANDLE_INFORMATION HandleInfo = { 0, 0 };
     2615    NTSTATUS rcNt = ObReferenceObjectByHandle((HANDLE)hHandle, /*FILE_WRITE_DATA*/0, *IoFileObjectType,
     2616                                              UserMode, (void **)&pFileObject, &HandleInfo);
     2617    if (!NT_SUCCESS(rcNt))
     2618        return RTErrConvertFromNtStatus(rcNt);
     2619    AssertPtrReturn(pFileObject, VERR_INTERNAL_ERROR_3);
     2620
     2621    PDEVICE_OBJECT pDevObject = IoGetRelatedDeviceObject(pFileObject);
     2622    AssertMsgReturnStmt(RT_VALID_PTR(pDevObject), ("pDevObject=%p\n", pDevObject),
     2623                        ObDereferenceObject(pFileObject), VERR_INTERNAL_ERROR_2);
     2624
     2625    /*
     2626     * Allocate a context structure and fill it in.
     2627     */
     2628    PSUPR0IOCTLCTX pCtx = (PSUPR0IOCTLCTX)RTMemAllocZ(sizeof(*pCtx));
     2629    if (pCtx)
     2630    {
     2631        pCtx->u32Magic      = SUPR0IOCTLCTX_MAGIC;
     2632        pCtx->cRefs         = 1;
     2633        pCtx->pFileObject   = pFileObject;
     2634        pCtx->pDeviceObject = pDevObject;
     2635
     2636        PDRIVER_OBJECT pDrvObject = pDevObject->DriverObject;
     2637        if (   RT_VALID_PTR(pDrvObject->FastIoDispatch)
     2638            && RT_VALID_PTR(pDrvObject->FastIoDispatch->FastIoDeviceControl))
     2639            pCtx->pfnFastIoDeviceControl = pDrvObject->FastIoDispatch->FastIoDeviceControl;
     2640        else
     2641            pCtx->pfnFastIoDeviceControl = NULL;
     2642        *ppCtx = pCtx;
     2643        return VINF_SUCCESS;
     2644    }
     2645
     2646    ObDereferenceObject(pFileObject);
     2647    return VERR_NO_MEMORY;
     2648}
     2649
     2650
     2651/**
     2652 * I/O control destructor for NT.
     2653 *
     2654 * @param   pCtx    The context to destroy.
     2655 */
     2656static void supdrvNtIoCtlContextDestroy(PSUPR0IOCTLCTX pCtx)
     2657{
     2658    PFILE_OBJECT pFileObject = pCtx->pFileObject;
     2659    pCtx->pfnFastIoDeviceControl = NULL;
     2660    pCtx->pFileObject            = NULL;
     2661    pCtx->pDeviceObject          = NULL;
     2662    ASMAtomicWriteU32(&pCtx->u32Magic, ~SUPR0IOCTLCTX_MAGIC);
     2663
     2664    if (RT_VALID_PTR(pFileObject))
     2665        ObDereferenceObject(pFileObject);
     2666    RTMemFree(pCtx);
     2667}
     2668
     2669
     2670SUPR0DECL(int) SUPR0IoCtlCleanup(PSUPR0IOCTLCTX pCtx)
     2671{
     2672    if (pCtx != NULL)
     2673    {
     2674        AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
     2675        AssertReturn(pCtx->u32Magic == SUPR0IOCTLCTX_MAGIC, VERR_INVALID_PARAMETER);
     2676
     2677        uint32_t cRefs = ASMAtomicDecU32(&pCtx->cRefs);
     2678        Assert(cRefs < _4K);
     2679        if (cRefs == 0)
     2680            supdrvNtIoCtlContextDestroy(pCtx);
     2681    }
     2682    return VINF_SUCCESS;
     2683}
     2684
     2685
     2686SUPR0DECL(int)  SUPR0IoCtlPerform(PSUPR0IOCTLCTX pCtx, uintptr_t uFunction,
     2687                                  void *pvInput, RTR3PTR pvInputUser, size_t cbInput,
     2688                                  void *pvOutput, RTR3PTR pvOutputUser, size_t cbOutput,
     2689                                  int32_t *piNativeRc)
     2690{
     2691    AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
     2692    AssertReturn(pCtx->u32Magic == SUPR0IOCTLCTX_MAGIC, VERR_INVALID_PARAMETER);
     2693
     2694    /* Reference the context. */
     2695    uint32_t cRefs = ASMAtomicIncU32(&pCtx->cRefs);
     2696    Assert(cRefs > 1 && cRefs < _4K);
     2697
     2698    /*
     2699     * Try fast I/O control path first.
     2700     */
     2701    IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
     2702    if (pCtx->pfnFastIoDeviceControl)
     2703    {
     2704        /* Must pass user addresses here as that's what's being expected. */
     2705        BOOLEAN fHandled = pCtx->pfnFastIoDeviceControl(pCtx->pFileObject,
     2706                                                        TRUE /*Wait*/,
     2707                                                        (void *)pvInputUser,  (ULONG)cbInput,
     2708                                                        (void *)pvOutputUser, (ULONG)cbOutput,
     2709                                                        uFunction,
     2710                                                        &Ios,
     2711                                                        pCtx->pDeviceObject);
     2712        if (fHandled)
     2713        {
     2714            /* Relase the context. */
     2715            cRefs = ASMAtomicDecU32(&pCtx->cRefs);
     2716            Assert(cRefs < _4K);
     2717            if (cRefs == 0)
     2718                supdrvNtIoCtlContextDestroy(pCtx);
     2719
     2720            /* Set/convert status and return. */
     2721            if (piNativeRc)
     2722            {
     2723                *piNativeRc = Ios.Status;
     2724                return VINF_SUCCESS;
     2725            }
     2726            if (NT_SUCCESS(Ios.Status))
     2727                return VINF_SUCCESS;
     2728            return RTErrConvertFromNtStatus(Ios.Status);
     2729        }
     2730
     2731        /*
     2732         * Fall back on IRP if not handled.
     2733         *
     2734         * Note! Perhaps we should rather fail, because VID.SYS will crash getting
     2735         *       the partition ID with the code below.  It tries to zero the output
     2736         *       buffer as if it were as system buffer...
     2737         */
     2738        RTNT_IO_STATUS_BLOCK_REINIT(&Ios);
     2739    }
     2740
     2741    /*
     2742     * For directly accessed buffers we must supply user mode addresses or
     2743     * we'll fail ProbeForWrite validation.
     2744     */
     2745    switch (uFunction & 3)
     2746    {
     2747        case METHOD_BUFFERED:
     2748            /* For buffered accesses, we can supply kernel buffers. */
     2749            break;
     2750
     2751        case METHOD_IN_DIRECT:
     2752            pvInput  = (void *)pvInputUser;
     2753            break;
     2754
     2755        case METHOD_NEITHER:
     2756            pvInput  = (void *)pvInputUser;
     2757            RT_FALL_THRU();
     2758
     2759        case METHOD_OUT_DIRECT:
     2760            pvOutput = (void *)pvOutputUser;
     2761            break;
     2762    }
     2763
     2764    /*
     2765     * Build the request.
     2766     */
     2767    int rc;
     2768    KEVENT Event;
     2769    KeInitializeEvent(&Event, NotificationEvent, FALSE);
     2770
     2771    PIRP pIrp = IoBuildDeviceIoControlRequest(uFunction, pCtx->pDeviceObject,
     2772                                              pvInput, (ULONG)cbInput, pvOutput, (ULONG)cbOutput,
     2773                                              FALSE /* InternalDeviceControl */, &Event, &Ios);
     2774    if (pIrp)
     2775    {
     2776        IoGetNextIrpStackLocation(pIrp)->FileObject = pCtx->pFileObject;
     2777
     2778        /*
     2779         * Make the call.
     2780         */
     2781        NTSTATUS rcNt = IoCallDriver(pCtx->pDeviceObject, pIrp);
     2782        if (rcNt == STATUS_PENDING)
     2783        {
     2784            rcNt = KeWaitForSingleObject(&Event,            /* Object */
     2785                                         Executive,         /* WaitReason */
     2786                                         KernelMode,        /* WaitMode */
     2787                                         FALSE,             /* Alertable */
     2788                                         NULL);             /* TimeOut */
     2789            AssertMsg(rcNt == STATUS_SUCCESS, ("rcNt=%#x\n", rcNt));
     2790            rcNt = Ios.Status;
     2791        }
     2792        else if (NT_SUCCESS(rcNt) && Ios.Status != STATUS_SUCCESS)
     2793            rcNt = Ios.Status;
     2794
     2795        /* Set/convert return code. */
     2796        if (piNativeRc)
     2797        {
     2798            *piNativeRc = rcNt;
     2799            rc = VINF_SUCCESS;
     2800        }
     2801        else if (NT_SUCCESS(rcNt))
     2802            rc = VINF_SUCCESS;
     2803        else
     2804            rc = RTErrConvertFromNtStatus(rcNt);
     2805    }
     2806    else
     2807    {
     2808        if (piNativeRc)
     2809            *piNativeRc = STATUS_NO_MEMORY;
     2810        rc = VERR_NO_MEMORY;
     2811    }
     2812
     2813    /* Relase the context. */
     2814    cRefs = ASMAtomicDecU32(&pCtx->cRefs);
     2815    Assert(cRefs < _4K);
     2816    if (cRefs == 0)
     2817        supdrvNtIoCtlContextDestroy(pCtx);
     2818
     2819    return rc;
    25602820}
    25612821
  • trunk/src/VBox/VMM/Makefile.kmk

    r71129 r71136  
    830830        VMMR0/VMMR0JmpA-x86.asm
    831831
    832  if1of ($(USERNAME),bird) # experimental.
    833   VMMR0_SOURCES.win.amd64 += VMMR0/NEMR0Native-win.cpp
    834   VMMR0_DEFS.win.amd64    += VBOX_WITH_NATIVE_NEM VBOX_WITH_NEM_R0
    835  endif
    836 
    837832 VMMR0_LIBS = \
    838833        $(PATH_STAGE_LIB)/ServicesR0$(VBOX_SUFF_LIB) \
     
    842837  VMMR0_LIBS += \
    843838        $(PATH_STAGE_LIB)/SUPR0$(VBOX_SUFF_LIB)
     839 endif
     840 if1of ($(USERNAME),bird) # experimental.
     841  VMMR0_SOURCES.win.amd64 += VMMR0/NEMR0Native-win.cpp
     842  VMMR0_DEFS.win.amd64    += VBOX_WITH_NATIVE_NEM VBOX_WITH_NEM_R0
     843  VMMR0/NEMR0Native-win.cpp_SDKS.win = ReorderCompilerIncs $(VBOX_WINDDK) $(VBOX_WINPSDK)INCS
    844844 endif
    845845
  • 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)
  • trunk/src/VBox/VMM/VMMR3/NEMR3Native-win.cpp

    r71131 r71136  
    12691269    pVM->nem.s.fCreatedEmts = true;
    12701270
    1271     LogRel(("NEM: Successfully set up partition (device handle %p, partition ID %#llx)\n", hPartitionDevice, idHvPartition));
    1272     return VINF_SUCCESS;
     1271    /*
     1272     * Do some more ring-0 initialization now that we've got the partition handle.
     1273     */
     1274    int rc = VMMR3CallR0Emt(pVM, &pVM->aCpus[0], VMMR0_DO_NEM_INIT_VM_PART_2, 0, NULL);
     1275    if (RT_SUCCESS(rc))
     1276    {
     1277        LogRel(("NEM: Successfully set up partition (device handle %p, partition ID %#llx)\n", hPartitionDevice, idHvPartition));
     1278        return VINF_SUCCESS;
     1279    }
     1280    return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS, "Call to NEMR0InitVMPart2 failed: %Rrc", rc);
    12731281}
    12741282
     
    13421350    }
    13431351}
    1344 
    13451352
    13461353#ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
     
    22952302                /* ACK the stop message. */
    22962303                fWait = g_pfnVidMessageSlotHandleAndGetNext(pVM->nem.s.hPartitionDevice, pVCpu->idCpu,
    2297                                                                  VID_MSHAGN_F_HANDLE_MESSAGE, 5000);
     2304                                                            VID_MSHAGN_F_HANDLE_MESSAGE, 5000);
    22982305                AssertLogRelMsg(fWait, ("dwErr=%u (%#x) rcNt=%#x\n", RTNtLastErrorValue(), RTNtLastErrorValue(), RTNtLastStatusValue()));
    22992306
  • trunk/src/VBox/VMM/include/NEMInternal.h

    r71131 r71136  
    173173        }                       UnmapPages;
    174174    } Hypercall;
     175    /** I/O control buffer, we always use this for I/O controls. */
     176    union
     177    {
     178        uint8_t                 ab[64];
     179        HV_PARTITION_ID         idPartition;
     180    } uIoCtlBuf;
    175181#endif
    176182} NEMCPU;
     
    232238    /** The partition ID. */
    233239    uint64_t                    idHvPartition;
     240    /** I/O control context. */
     241    PSUPR0IOCTLCTX              pIoCtlCtx;
     242    /** Delta to add to convert a ring-0 pointer to a ring-3 one.   */
     243    uintptr_t                   offRing3ConversionDelta;
     244    /** Info about the VidGetHvPartitionId I/O control interface. */
     245    NEMWINIOCTL                 IoCtlGetHvPartitionId;
     246    /** Info about the VidStartVirtualProcessor I/O control interface. */
     247    NEMWINIOCTL                 IoCtlStartVirtualProcessor;
     248    /** Info about the VidStopVirtualProcessor I/O control interface. */
     249    NEMWINIOCTL                 IoCtlStopVirtualProcessor;
     250    /** Info about the VidStopVirtualProcessor I/O control interface. */
     251    NEMWINIOCTL                 IoCtlMessageSlotHandleAndGetNext;
     252
    234253# else
    235254    uint32_t                    uDummy;
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