VirtualBox

Changeset 29952 in vbox


Ignore:
Timestamp:
Jun 1, 2010 3:02:07 PM (15 years ago)
Author:
vboxsync
Message:

Preliminary code for sharing kernel memory

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServicePageSharing.cpp

    r29939 r29952  
    4545#include <tlhelp32.h>
    4646#include <psapi.h>
     47#include <winternl.h>
    4748
    4849typedef struct
     
    5455} KNOWN_MODULE, *PKNOWN_MODULE;
    5556
     57#define SystemModuleInformation     11
     58
     59typedef struct _RTL_PROCESS_MODULE_INFORMATION
     60{
     61    ULONG Section;
     62    PVOID MappedBase;
     63    PVOID ImageBase;
     64    ULONG ImageSize;
     65    ULONG Flags;
     66    USHORT LoadOrderIndex;
     67    USHORT InitOrderIndex;
     68    USHORT LoadCount;
     69    USHORT OffsetToFileName;
     70    CHAR FullPathName[256];
     71} RTL_PROCESS_MODULE_INFORMATION, *PRTL_PROCESS_MODULE_INFORMATION;
     72
     73typedef struct _RTL_PROCESS_MODULES
     74{
     75    ULONG NumberOfModules;
     76    RTL_PROCESS_MODULE_INFORMATION Modules[1];
     77} RTL_PROCESS_MODULES, *PRTL_PROCESS_MODULES;
     78
     79typedef NTSTATUS (WINAPI *PFNZWQUERYSYSTEMINFORMATION)(ULONG, PVOID, ULONG, PULONG);
     80static PFNZWQUERYSYSTEMINFORMATION ZwQuerySystemInformation = NULL;
     81static HMODULE hNtdll = 0;
     82
     83
    5684static DECLCALLBACK(int) VBoxServicePageSharingEmptyTreeCallback(PAVLPVNODECORE pNode, void *);
    5785
     
    6088/**
    6189 * Registers a new module with the VMM
    62  * @param   pModule     Module ptr
     90 * @param   pModule         Module ptr
     91 * @param   fValidateMemory Validate/touch memory pages or not
    6392 */
    64 void VBoxServicePageSharingRegisterModule(PKNOWN_MODULE pModule)
     93void VBoxServicePageSharingRegisterModule(PKNOWN_MODULE pModule, bool fValidateMemory)
    6594{
    6695    VMMDEVSHAREDREGIONDESC   aRegions[VMMDEVSHAREDREGIONDESC_MAX];
     
    128157
    129158    unsigned idxRegion = 0;
    130     do
    131     {
    132         MEMORY_BASIC_INFORMATION MemInfo;
    133 
    134         SIZE_T ret = VirtualQuery(pBaseAddress, &MemInfo, sizeof(MemInfo));
    135         Assert(ret);
    136         if (!ret)
     159
     160    if (fValidateMemory)
     161    {
     162        do
    137163        {
    138             VBoxServiceVerbose(3, "VBoxServicePageSharingRegisterModule: VirtualQueryEx failed with %d\n", GetLastError());
    139             break;
    140         }
    141 
    142         if (    MemInfo.State == MEM_COMMIT
    143             &&  MemInfo.Type == MEM_IMAGE)
    144         {
    145             switch (MemInfo.Protect)
     164            MEMORY_BASIC_INFORMATION MemInfo;
     165
     166            SIZE_T ret = VirtualQuery(pBaseAddress, &MemInfo, sizeof(MemInfo));
     167            Assert(ret);
     168            if (!ret)
    146169            {
    147             case PAGE_EXECUTE:
    148             case PAGE_EXECUTE_READ:
    149             case PAGE_READONLY:
    150             {
    151                 char *pRegion = (char *)MemInfo.BaseAddress;
    152 
    153                 /* Skip the first region as it only contains the image file header. */
    154                 if (pRegion != (char *)pModule->Info.modBaseAddr)
    155                 {
    156                     /* Touch all pages. */
    157                     while (pRegion < (char *)MemInfo.BaseAddress + MemInfo.RegionSize)
    158                     {
    159                         /* Try to trick the optimizer to leave the page touching code in place. */
    160                         ASMProbeReadByte(pRegion);
    161                         pRegion += PAGE_SIZE;
    162                     }
    163                 }
    164                 aRegions[idxRegion].GCRegionAddr = (RTGCPTR64)MemInfo.BaseAddress;
    165                 aRegions[idxRegion].cbRegion     = MemInfo.RegionSize;
    166                 idxRegion++;
    167 
     170                VBoxServiceVerbose(3, "VBoxServicePageSharingRegisterModule: VirtualQueryEx failed with %d\n", GetLastError());
    168171                break;
    169172            }
    170173
    171             default:
    172                 break; /* ignore */
     174            if (    MemInfo.State == MEM_COMMIT
     175                &&  MemInfo.Type == MEM_IMAGE)
     176            {
     177                switch (MemInfo.Protect)
     178                {
     179                case PAGE_EXECUTE:
     180                case PAGE_EXECUTE_READ:
     181                case PAGE_READONLY:
     182                {
     183                    char *pRegion = (char *)MemInfo.BaseAddress;
     184
     185                    /* Skip the first region as it only contains the image file header. */
     186                    if (pRegion != (char *)pModule->Info.modBaseAddr)
     187                    {
     188                        /* Touch all pages. */
     189                        while (pRegion < (char *)MemInfo.BaseAddress + MemInfo.RegionSize)
     190                        {
     191                            /* Try to trick the optimizer to leave the page touching code in place. */
     192                            ASMProbeReadByte(pRegion);
     193                            pRegion += PAGE_SIZE;
     194                        }
     195                    }
     196                    aRegions[idxRegion].GCRegionAddr = (RTGCPTR64)MemInfo.BaseAddress;
     197                    aRegions[idxRegion].cbRegion     = MemInfo.RegionSize;
     198                    idxRegion++;
     199
     200                    break;
     201                }
     202
     203                default:
     204                    break; /* ignore */
     205                }
    173206            }
     207
     208            pBaseAddress = (BYTE *)MemInfo.BaseAddress + MemInfo.RegionSize;
     209            if (dwModuleSize > MemInfo.RegionSize)
     210            {
     211                dwModuleSize -= MemInfo.RegionSize;
     212            }
     213            else
     214            {
     215                dwModuleSize = 0;
     216                break;
     217            }
     218
     219            if (idxRegion >= RT_ELEMENTS(aRegions))
     220                break;  /* out of room */
    174221        }
    175 
    176         pBaseAddress = (BYTE *)MemInfo.BaseAddress + MemInfo.RegionSize;
    177         if (dwModuleSize > MemInfo.RegionSize)
    178         {
    179             dwModuleSize -= MemInfo.RegionSize;
    180         }
    181         else
    182         {
    183             dwModuleSize = 0;
    184             break;
    185         }
    186 
    187         if (idxRegion >= RT_ELEMENTS(aRegions))
    188             break;  /* out of room */
    189     }
    190     while (dwModuleSize);
    191 
     222        while (dwModuleSize);
     223    }
     224    else
     225    {
     226        /* We can't probe kernel memory ranges, so pretend it's one big region. */
     227        aRegions[idxRegion].GCRegionAddr = (RTGCPTR64)pBaseAddress;
     228        aRegions[idxRegion].cbRegion     = dwModuleSize;
     229        idxRegion++;
     230    }
    192231    VBoxServiceVerbose(3, "VbglR3RegisterSharedModule %s %s base=%p size=%x cregions=%d\n", pModule->Info.szModule, pModule->szFileVersion, pModule->Info.modBaseAddr, pModule->Info.modBaseSize, idxRegion);
    193232    int rc = VbglR3RegisterSharedModule(pModule->Info.szModule, pModule->szFileVersion, (RTGCPTR64)pModule->Info.modBaseAddr,
     
    259298                pModule->hModule  = LoadLibraryEx(ModuleInfo.szExePath, 0, DONT_RESOLVE_DLL_REFERENCES);
    260299                if (pModule->hModule)
    261                     VBoxServicePageSharingRegisterModule(pModule);
     300                    VBoxServicePageSharingRegisterModule(pModule, true /* validate pages */);
     301
     302                VBoxServiceVerbose(3, "\n\n     MODULE NAME:     %s",           ModuleInfo.szModule );
     303                VBoxServiceVerbose(3, "\n     executable     = %s",             ModuleInfo.szExePath );
     304                VBoxServiceVerbose(3, "\n     process ID     = 0x%08X",         ModuleInfo.th32ProcessID );
     305                VBoxServiceVerbose(3, "\n     base address   = 0x%08X", (DWORD) ModuleInfo.modBaseAddr );
     306                VBoxServiceVerbose(3, "\n     base size      = %d",             ModuleInfo.modBaseSize );
    262307
    263308                pRec = &pModule->Core;
     
    265310            bool ret = RTAvlPVInsert(ppNewTree, pRec);
    266311            Assert(ret); NOREF(ret);
    267 
    268             VBoxServiceVerbose(3, "\n\n     MODULE NAME:     %s",           ModuleInfo.szModule );
    269             VBoxServiceVerbose(3, "\n     executable     = %s",             ModuleInfo.szExePath );
    270             VBoxServiceVerbose(3, "\n     process ID     = 0x%08X",         ModuleInfo.th32ProcessID );
    271             VBoxServiceVerbose(3, "\n     base address   = 0x%08X", (DWORD) ModuleInfo.modBaseAddr );
    272             VBoxServiceVerbose(3, "\n     base size      = %d",             ModuleInfo.modBaseSize );
    273312        }
    274313    }
     
    315354    CloseHandle(hSnapshot);
    316355
     356#if 0
     357    /* Check all loaded kernel modules. */
     358    ULONG                cbBuffer;
     359    PVOID                pBuffer = NULL;
     360    PRTL_PROCESS_MODULES pSystemModules;
     361   
     362    NTSTATUS ret = ZwQuerySystemInformation(SystemModuleInformation, (PVOID)&cbBuffer, 0, &cbBuffer);
     363    if (ret != STATUS_SUCCESS)
     364        goto skipkernelmodules;
     365       
     366    pBuffer = malloc(cbBuffer);
     367    if (!pBuffer)
     368        goto skipkernelmodules;
     369
     370    ret = ZwQuerySystemInformation(SystemModuleInformation, pBuffer, cbBuffer, &cbBuffer);
     371    if (ret != STATUS_SUCCESS)
     372        goto skipkernelmodules;
     373   
     374    pSystemModules = (PRTL_PROCESS_MODULES)pBuffer;
     375    for (unsigned i = 0; i < pSystemModules->NumberOfModules; i++)
     376    {
     377        /* Found it before? */
     378        PAVLPVNODECORE pRec = RTAvlPVGet(&pNewTree, pSystemModules->Modules[i].ImageBase);
     379        if (!pRec)
     380        {
     381            pRec = RTAvlPVRemove(&pKnownModuleTree, pSystemModules->Modules[i].ImageBase);
     382            if (!pRec)
     383            {
     384                /* New module; register it. */
     385                char          szFullFilePath[512];
     386                PKNOWN_MODULE pModule = (PKNOWN_MODULE)RTMemAllocZ(sizeof(*pModule));
     387                Assert(pModule);
     388                if (!pModule)
     389                    break;
     390
     391                strcpy(pModule->Info.szModule, &pSystemModules->Modules[i].FullPathName[pSystemModules->Modules[i].OffsetToFileName]);
     392                GetSystemDirectoryA(szFullFilePath, sizeof(szFullFilePath));
     393
     394                /* skip \Systemroot\system32 */
     395                char *lpPath = strstr(pSystemModules->Modules[i].FullPathName, "\\system32");
     396                if (!lpPath)
     397                {
     398                    VBoxServiceVerbose(1, "Unexpected kernel module name %s\n", pSystemModules->Modules[i].FullPathName);
     399                    RTMemFree(pModule);
     400                    break;
     401                }
     402
     403                lpPath = strchr(lpPath+1, '\\');
     404                if (!lpPath)
     405                {
     406                    VBoxServiceVerbose(1, "Unexpected kernel module name %s\n", pSystemModules->Modules[i].FullPathName);
     407                    RTMemFree(pModule);
     408                    break;
     409                }
     410
     411                strcat(szFullFilePath, lpPath);
     412                strcpy(pModule->Info.szExePath, szFullFilePath);
     413                pModule->Info.modBaseAddr = (BYTE *)pSystemModules->Modules[i].ImageBase;
     414                pModule->Info.modBaseSize = pSystemModules->Modules[i].ImageSize;
     415
     416                pModule->Core.Key = pSystemModules->Modules[i].ImageBase;
     417                VBoxServicePageSharingRegisterModule(pModule, false /* don't check memory pages */);
     418
     419                VBoxServiceVerbose(3, "\n\n   KERNEL  MODULE NAME:     %s",     pModule->Info.szModule );
     420                VBoxServiceVerbose(3, "\n     executable     = %s",             pModule->Info.szExePath );
     421                VBoxServiceVerbose(3, "\n     base address   = 0x%08X", (DWORD) pModule->Info.modBaseAddr );
     422                VBoxServiceVerbose(3, "\n     base size      = %d",             pModule->Info.modBaseSize );
     423
     424                pRec = &pModule->Core;
     425            }
     426            bool ret = RTAvlPVInsert(&pNewTree, pRec);
     427            Assert(ret); NOREF(ret);
     428        }
     429    }
     430
     431skipkernelmodules:
     432    if (pBuffer)
     433        free(pBuffer);
     434#endif
     435
    317436    /* Delete leftover modules in the old tree. */
    318437    RTAvlPVDestroy(&pKnownModuleTree, VBoxServicePageSharingEmptyTreeCallback, NULL);
     
    382501    int rc = RTSemEventMultiCreate(&g_PageSharingEvent);
    383502    AssertRCReturn(rc, rc);
     503
     504#if defined(RT_OS_WINDOWS) && !defined(TARGET_NT4)
     505    hNtdll = LoadLibrary("ntdll.dll");
     506   
     507    if (hNtdll)
     508        ZwQuerySystemInformation = (PFNZWQUERYSYSTEMINFORMATION)GetProcAddress(hNtdll, "ZwQuerySystemInformation");
     509#endif
    384510
    385511    /* @todo report system name and version */
     
    454580{
    455581    VBoxServiceVerbose(3, "VBoxServicePageSharingTerm\n");
     582
     583#if defined(RT_OS_WINDOWS) && !defined(TARGET_NT4)
     584    if (hNtdll)
     585        FreeLibrary(hNtdll);
     586#endif
    456587    return;
    457588}
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