void Test_RtlSetAllBits(void) { RTL_BITMAP BitMapHeader; ULONG *Buffer; ULONG BufferSize = 2 * sizeof(*Buffer); Buffer = AllocateGuarded(BufferSize); RtlInitializeBitMap(&BitMapHeader, Buffer, 19); memset(Buffer, 0xcc, BufferSize); RtlSetAllBits(&BitMapHeader); ok_hex(Buffer[0], 0xffffffff); ok_hex(Buffer[1], 0xcccccccc); RtlInitializeBitMap(&BitMapHeader, Buffer, 0); memset(Buffer, 0xcc, BufferSize); RtlSetAllBits(&BitMapHeader); ok_hex(Buffer[0], 0xcccccccc); ok_hex(Buffer[1], 0xcccccccc); RtlInitializeBitMap(&BitMapHeader, Buffer, 64); memset(Buffer, 0xcc, BufferSize); RtlSetAllBits(&BitMapHeader); ok_hex(Buffer[0], 0xffffffff); ok_hex(Buffer[1], 0xffffffff); FreeGuarded(Buffer); }
// Build IO bitmaps _Use_decl_annotations_ static UCHAR *VmpBuildIoBitmaps() { PAGED_CODE(); // Allocate two IO bitmaps as one contiguous 4K+4K page const auto io_bitmaps = reinterpret_cast<UCHAR *>(ExAllocatePoolWithTag( NonPagedPool, PAGE_SIZE * 2, kHyperPlatformCommonPoolTag)); if (!io_bitmaps) { return nullptr; } const auto io_bitmap_a = io_bitmaps; // for 0x0 - 0x7fff const auto io_bitmap_b = io_bitmaps + PAGE_SIZE; // for 0x8000 - 0xffff RtlFillMemory(io_bitmap_a, PAGE_SIZE, 0); RtlFillMemory(io_bitmap_b, PAGE_SIZE, 0); // Activate VM-exit for IO port 0x10 - 0x2010 as an example RTL_BITMAP bitmap_a_header = {}; RtlInitializeBitMap(&bitmap_a_header, reinterpret_cast<PULONG>(io_bitmap_a), PAGE_SIZE * CHAR_BIT); // RtlSetBits(&bitmap_a_header, 0x10, 0x2000); RTL_BITMAP bitmap_b_header = {}; RtlInitializeBitMap(&bitmap_b_header, reinterpret_cast<PULONG>(io_bitmap_b), PAGE_SIZE * CHAR_BIT); // RtlSetBits(&bitmap_b_header, 0, 0x8000); return io_bitmaps; }
// Initialize shared processor data _Use_decl_annotations_ static SharedProcessorData *VmpInitializeSharedData() { PAGED_CODE(); const auto shared_data = reinterpret_cast<SharedProcessorData *>( ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(SharedProcessorData), kHyperPlatformCommonPoolTag)); if (!shared_data) { return nullptr; } RtlZeroMemory(shared_data, sizeof(SharedProcessorData)); HYPERPLATFORM_LOG_DEBUG("SharedData= %p", shared_data); // Set up the MSR bitmap const auto msr_bitmap = ExAllocatePoolWithTag(NonPagedPoolNx, PAGE_SIZE, kHyperPlatformCommonPoolTag); if (!msr_bitmap) { ExFreePoolWithTag(shared_data, kHyperPlatformCommonPoolTag); return nullptr; } RtlZeroMemory(msr_bitmap, PAGE_SIZE); shared_data->msr_bitmap = msr_bitmap; // Checks MSRs causing #GP and should not cause VM-exit from 0 to 0xfff. bool unsafe_msr_map[0x1000] = {}; for (auto msr = 0ul; msr < RTL_NUMBER_OF(unsafe_msr_map); ++msr) { __try { UtilReadMsr(static_cast<Msr>(msr)); } __except (EXCEPTION_EXECUTE_HANDLER) { unsafe_msr_map[msr] = true; } } // Activate VM-exit for RDMSR against all MSRs const auto bitmap_read_low = reinterpret_cast<UCHAR *>(msr_bitmap); const auto bitmap_read_high = bitmap_read_low + 1024; RtlFillMemory(bitmap_read_low, 1024, 0xff); // read 0 - 1fff RtlFillMemory(bitmap_read_high, 1024, 0xff); // read c0000000 - c0001fff // But ignore IA32_MPERF (000000e7) and IA32_APERF (000000e8) RTL_BITMAP bitmap_read_low_header = {}; RtlInitializeBitMap(&bitmap_read_low_header, reinterpret_cast<PULONG>(bitmap_read_low), 1024 * 8); RtlClearBits(&bitmap_read_low_header, 0xe7, 2); // Also ignore the unsage MSRs for (auto msr = 0ul; msr < RTL_NUMBER_OF(unsafe_msr_map); ++msr) { const auto ignore = unsafe_msr_map[msr]; if (ignore) { RtlClearBits(&bitmap_read_low_header, msr, 1); } } // But ignore IA32_GS_BASE (c0000101) and IA32_KERNEL_GS_BASE (c0000102) RTL_BITMAP bitmap_read_high_header = {}; RtlInitializeBitMap(&bitmap_read_high_header, reinterpret_cast<PULONG>(bitmap_read_high), 1024 * 8); RtlClearBits(&bitmap_read_high_header, 0x101, 2); return shared_data; }
static NTSTATUS init_msr_bitmap(struct ksm *k) { void *msr_bitmap = ExAllocatePool(NonPagedPoolNx, PAGE_SIZE); if (!msr_bitmap) return STATUS_NO_MEMORY; k->msr_bitmap = msr_bitmap; RtlZeroMemory(msr_bitmap, PAGE_SIZE); /* For all MSRs... */ u8 *bitmap_read_lo = (u8 *)msr_bitmap; u8 *bitmap_read_hi = bitmap_read_lo + 1024; memset(bitmap_read_lo, 0xff, 1024); // 0 -> 1fff memset(bitmap_read_hi, 0xff, 1024); // c0000000 - c0001fff /* ... ignore MSR_IA32_MPERF and MSR_IA32_APERF */ RTL_BITMAP bitmap_read_lo_hdr; RtlInitializeBitMap(&bitmap_read_lo_hdr, (PULONG)bitmap_read_lo, 1024 * CHAR_BIT); RtlClearBits(&bitmap_read_lo_hdr, MSR_IA32_MPERF, 2); for (u32 msr = 0; msr < PAGE_SIZE; ++msr) { __try { __readmsr(msr); } __except (EXCEPTION_EXECUTE_HANDLER) { RtlClearBits(&bitmap_read_lo_hdr, msr, 1); } } /* ... and ignore MSR_IA32_GS_BASE and MSR_IA32_KERNEL_GS_BASE */ RTL_BITMAP bitmap_read_hi_hdr; RtlInitializeBitMap(&bitmap_read_hi_hdr, (PULONG)bitmap_read_hi, 1024 * CHAR_BIT); RtlClearBits(&bitmap_read_hi_hdr, 0x101, 2); return STATUS_SUCCESS; }
void Test_RtlInitializeBitMap(void) { RTL_BITMAP BitMapHeader; ULONG Buffer[2]; BOOLEAN Exception = FALSE; _SEH2_TRY { RtlInitializeBitMap(NULL, NULL, 0); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Exception = TRUE; } _SEH2_END; ok_int(Exception, 1); memset(Buffer, 0xcc, sizeof(Buffer)); RtlInitializeBitMap(&BitMapHeader, Buffer, 0); ok_int(BitMapHeader.SizeOfBitMap, 0); ok_ptr(BitMapHeader.Buffer, Buffer); ok_hex(Buffer[0], 0xcccccccc); RtlInitializeBitMap(&BitMapHeader, Buffer, 8); ok_int(BitMapHeader.SizeOfBitMap, 8); ok_hex(Buffer[0], 0xcccccccc); }
void Test_RtlInitializeBitmap() { RTL_BITMAP Bitmap; ULONG Buffer[5]; Buffer[0] = 0x12345; Buffer[1] = 0x23456; Buffer[2] = 0x34567; Buffer[3] = 0x45678; Buffer[4] = 0x56789; RtlInitializeBitMap(&Bitmap, Buffer, 19); ok(Bitmap.Buffer == Buffer, "Buffer=%p\n", Bitmap.Buffer); ok(Bitmap.SizeOfBitMap == 19, "SizeOfBitMap=%ld\n", Bitmap.SizeOfBitMap); ok(Buffer[0] == 0x12345, "Buffer[0] == 0x%lx\n", Buffer[0]); ok(Buffer[1] == 0x23456, "Buffer[1] == 0x%lx\n", Buffer[1]); ok(Buffer[2] == 0x34567, "Buffer[2] == 0x%lx\n", Buffer[2]); ok(Buffer[3] == 0x45678, "Buffer[3] == 0x%lx\n", Buffer[3]); ok(Buffer[4] == 0x56789, "Buffer[4] == 0x%lx\n", Buffer[4]); RtlInitializeBitMap(&Bitmap, 0, -100); ok(Bitmap.Buffer == 0, "Buffer=%p\n", Bitmap.Buffer); ok(Bitmap.SizeOfBitMap == -100, "SizeOfBitMap=%ld\n", Bitmap.SizeOfBitMap); }
void Test_RtlNumberOfClearBits(void) { RTL_BITMAP BitMapHeader; ULONG *Buffer; Buffer = AllocateGuarded(2 * sizeof(*Buffer)); Buffer[0] = 0xff00fff0; Buffer[1] = 0x3F303F30; RtlInitializeBitMap(&BitMapHeader, Buffer, 0); ok_int(RtlNumberOfClearBits(&BitMapHeader), 0); RtlInitializeBitMap(&BitMapHeader, Buffer, 4); ok_int(RtlNumberOfClearBits(&BitMapHeader), 4); RtlInitializeBitMap(&BitMapHeader, Buffer, 31); ok_int(RtlNumberOfClearBits(&BitMapHeader), 12); RtlInitializeBitMap(&BitMapHeader, Buffer, 56); ok_int(RtlNumberOfClearBits(&BitMapHeader), 26); RtlInitializeBitMap(&BitMapHeader, Buffer, 64); ok_int(RtlNumberOfClearBits(&BitMapHeader), 28); FreeGuarded(Buffer); }
void Test_RtlFindNextForwardRunClear(void) { RTL_BITMAP BitMapHeader; ULONG *Buffer; ULONG Index; Buffer = AllocateGuarded(2 * sizeof(*Buffer)); Buffer[0] = 0xF9F078B2; Buffer[1] = 0x3F303F30; RtlInitializeBitMap(&BitMapHeader, Buffer, 0); ok_int(RtlFindNextForwardRunClear(&BitMapHeader, 0, &Index), 0); ok_int(Index, 0); ok_int(RtlFindNextForwardRunClear(&BitMapHeader, 1, &Index), 0); ok_int(Index, 1); Index = -1; RtlInitializeBitMap(&BitMapHeader, Buffer, 8); ok_int(RtlFindNextForwardRunClear(&BitMapHeader, 0, &Index), 1); ok_int(Index, 0); ok_int(RtlFindNextForwardRunClear(&BitMapHeader, 1, &Index), 2); ok_int(Index, 2); ok_int(RtlFindNextForwardRunClear(&BitMapHeader, 7, &Index), 0); ok_int(Index, 8); ok_int(RtlFindNextForwardRunClear(&BitMapHeader, 17, &Index), 0); ok_int(Index, 17); ok_int(RtlFindNextForwardRunClear(&BitMapHeader, 39, &Index), 0); ok_int(Index, 39); FreeGuarded(Buffer); }
void Test_RtlAreBitsSet(void) { RTL_BITMAP BitMapHeader; ULONG *Buffer; Buffer = AllocateGuarded(2 * sizeof(*Buffer)); RtlInitializeBitMap(&BitMapHeader, Buffer, 19); Buffer[0] = 0xff00ff00; Buffer[1] = 0x3F303F30; ok_hex(RtlAreBitsSet(&BitMapHeader, 0, 8), FALSE); ok_hex(RtlAreBitsSet(&BitMapHeader, 8, 8), TRUE); ok_hex(RtlAreBitsSet(&BitMapHeader, 7, 8), FALSE); ok_hex(RtlAreBitsSet(&BitMapHeader, 8, 9), FALSE); ok_hex(RtlAreBitsSet(&BitMapHeader, 24, 1), FALSE); RtlInitializeBitMap(&BitMapHeader, Buffer, 31); ok_hex(RtlAreBitsSet(&BitMapHeader, 24, 1), TRUE); ok_hex(RtlAreBitsSet(&BitMapHeader, 24, 7), TRUE); ok_hex(RtlAreBitsSet(&BitMapHeader, 24, 8), FALSE); RtlInitializeBitMap(&BitMapHeader, Buffer, 64); ok_hex(RtlAreBitsSet(&BitMapHeader, 60, 4), FALSE); FreeGuarded(Buffer); }
void Test_RtlFindClearBits(void) { RTL_BITMAP BitMapHeader; ULONG *Buffer; Buffer = AllocateGuarded(2 * sizeof(*Buffer)); Buffer[0] = 0x060F874D; Buffer[1] = 0x3F303F30; RtlInitializeBitMap(&BitMapHeader, Buffer, 0); ok_int(RtlFindClearBits(&BitMapHeader, 0, 0), 0); ok_int(RtlFindClearBits(&BitMapHeader, 0, 3), 0); ok_int(RtlFindClearBits(&BitMapHeader, 1, 0), -1); ok_int(RtlFindClearBits(&BitMapHeader, 1, 1), -1); RtlInitializeBitMap(&BitMapHeader, Buffer, 8); ok_int(RtlFindClearBits(&BitMapHeader, 0, 3), 0); ok_int(RtlFindClearBits(&BitMapHeader, 1, 0), 1); ok_int(RtlFindClearBits(&BitMapHeader, 1, 1), 1); ok_int(RtlFindClearBits(&BitMapHeader, 1, 2), 4); ok_int(RtlFindClearBits(&BitMapHeader, 2, 0), 4); ok_int(RtlFindClearBits(&BitMapHeader, 3, 0), -1); RtlInitializeBitMap(&BitMapHeader, Buffer, 32); ok_int(RtlFindClearBits(&BitMapHeader, 0, 3), 0); ok_int(RtlFindClearBits(&BitMapHeader, 0, 21), 16); ok_int(RtlFindClearBits(&BitMapHeader, 0, 12), 8); ok_int(RtlFindClearBits(&BitMapHeader, 0, 31), 24); ok_int(RtlFindClearBits(&BitMapHeader, 0, 32), 0); ok_int(RtlFindClearBits(&BitMapHeader, 0, 39), 0); ok_int(RtlFindClearBits(&BitMapHeader, 4, 0), 11); ok_int(RtlFindClearBits(&BitMapHeader, 5, 0), 20); ok_int(RtlFindClearBits(&BitMapHeader, 4, 11), 11); ok_int(RtlFindClearBits(&BitMapHeader, 4, 12), 20); ok_int(RtlFindClearBits(&BitMapHeader, 2, 11), 11); ok_int(RtlFindClearBits(&BitMapHeader, 2, 12), 12); ok_int(RtlFindClearBits(&BitMapHeader, 1, 32), 1); ok_int(RtlFindClearBits(&BitMapHeader, 4, 32), 11); ok_int(RtlFindClearBits(&BitMapHeader, 5, 32), 20); RtlInitializeBitMap(&BitMapHeader, Buffer, 64); ok_int(RtlFindClearBits(&BitMapHeader, 5, 64), 20); ok_int(RtlFindClearBits(&BitMapHeader, 9, 28), 27); ok_int(RtlFindClearBits(&BitMapHeader, 10, 0), -1); Buffer[1] = 0xFF303F30; ok_int(RtlFindClearBits(&BitMapHeader, 1, 56), 1); FreeGuarded(Buffer); }
void Test_RtlFindSetBits(void) { RTL_BITMAP BitMapHeader; ULONG *Buffer; Buffer = AllocateGuarded(2 * sizeof(*Buffer)); Buffer[0] = 0xF9F078B2; Buffer[1] = 0x3F303F30; RtlInitializeBitMap(&BitMapHeader, Buffer, 0); ok_int(RtlFindSetBits(&BitMapHeader, 0, 0), 0); ok_int(RtlFindSetBits(&BitMapHeader, 0, 3), 0); ok_int(RtlFindSetBits(&BitMapHeader, 1, 0), -1); ok_int(RtlFindSetBits(&BitMapHeader, 1, 1), -1); RtlInitializeBitMap(&BitMapHeader, Buffer, 8); ok_int(RtlFindSetBits(&BitMapHeader, 0, 3), 0); ok_int(RtlFindSetBits(&BitMapHeader, 1, 0), 1); ok_int(RtlFindSetBits(&BitMapHeader, 1, 1), 1); ok_int(RtlFindSetBits(&BitMapHeader, 1, 2), 4); ok_int(RtlFindSetBits(&BitMapHeader, 2, 0), 4); ok_int(RtlFindSetBits(&BitMapHeader, 3, 0), -1); RtlInitializeBitMap(&BitMapHeader, Buffer, 32); ok_int(RtlFindSetBits(&BitMapHeader, 0, 3), 0); ok_int(RtlFindSetBits(&BitMapHeader, 0, 21), 16); ok_int(RtlFindSetBits(&BitMapHeader, 0, 12), 8); ok_int(RtlFindSetBits(&BitMapHeader, 0, 31), 24); ok_int(RtlFindSetBits(&BitMapHeader, 0, 32), 0); ok_int(RtlFindSetBits(&BitMapHeader, 0, 39), 0); ok_int(RtlFindSetBits(&BitMapHeader, 4, 0), 11); ok_int(RtlFindSetBits(&BitMapHeader, 5, 0), 20); ok_int(RtlFindSetBits(&BitMapHeader, 4, 11), 11); ok_int(RtlFindSetBits(&BitMapHeader, 4, 12), 20); ok_int(RtlFindSetBits(&BitMapHeader, 2, 11), 11); ok_int(RtlFindSetBits(&BitMapHeader, 1, 32), 1); ok_int(RtlFindSetBits(&BitMapHeader, 4, 32), 11); ok_int(RtlFindSetBits(&BitMapHeader, 5, 32), 20); RtlInitializeBitMap(&BitMapHeader, Buffer, 64); ok_int(RtlFindSetBits(&BitMapHeader, 5, 64), 20); ok_int(RtlFindSetBits(&BitMapHeader, 6, 57), 40); ok_int(RtlFindSetBits(&BitMapHeader, 7, 0), -1); ok_int(RtlFindSetBits(&BitMapHeader, 1, 62), 1); FreeGuarded(Buffer); }
INIT_FUNCTION NTSTATUS NTAPI InitTimerImpl(VOID) { ULONG BitmapBytes; ExInitializeFastMutex(&Mutex); BitmapBytes = ROUND_UP(NUM_WINDOW_LESS_TIMERS, sizeof(ULONG) * 8) / 8; WindowLessTimersBitMapBuffer = ExAllocatePoolWithTag(NonPagedPool, BitmapBytes, TAG_TIMERBMP); if (WindowLessTimersBitMapBuffer == NULL) { return STATUS_UNSUCCESSFUL; } RtlInitializeBitMap(&WindowLessTimersBitMap, WindowLessTimersBitMapBuffer, BitmapBytes * 8); /* yes we need this, since ExAllocatePoolWithTag isn't supposed to zero out allocated memory */ RtlClearAllBits(&WindowLessTimersBitMap); ExInitializeResourceLite(&TimerLock); InitializeListHead(&TimersListHead); return STATUS_SUCCESS; }
void Test_RtlFindSetBitsAndClear(void) { RTL_BITMAP BitMapHeader; ULONG *Buffer; Buffer = AllocateGuarded(2 * sizeof(*Buffer)); Buffer[0] = 0xF9F078B2; Buffer[1] = 0x3F303F30; RtlInitializeBitMap(&BitMapHeader, Buffer, 0); ok_int(RtlFindSetBitsAndClear(&BitMapHeader, 0, 0), 0); ok_int(RtlFindSetBitsAndClear(&BitMapHeader, 0, 3), 0); ok_int(RtlFindSetBitsAndClear(&BitMapHeader, 1, 0), -1); ok_int(RtlFindSetBitsAndClear(&BitMapHeader, 1, 1), -1); ok_hex(Buffer[0], 0xF9F078B2); Buffer[0] = 0xF9F078B2; RtlInitializeBitMap(&BitMapHeader, Buffer, 8); ok_int(RtlFindSetBitsAndClear(&BitMapHeader, 1, 0), 1); ok_hex(Buffer[0], 0xf9f078b0); ok_int(RtlFindSetBitsAndClear(&BitMapHeader, 1, 1), 4); ok_hex(Buffer[0], 0xf9f078a0); ok_int(RtlFindSetBitsAndClear(&BitMapHeader, 1, 2), 5); ok_hex(Buffer[0], 0xf9f07880); ok_int(RtlFindSetBitsAndClear(&BitMapHeader, 2, 0), -1); ok_hex(Buffer[0], 0xf9f07880); Buffer[0] = 0xF9F078B2; RtlInitializeBitMap(&BitMapHeader, Buffer, 32); ok_int(RtlFindSetBitsAndClear(&BitMapHeader, 4, 0), 11); ok_hex(Buffer[0], 0xf9f000b2); ok_int(RtlFindSetBitsAndClear(&BitMapHeader, 5, 0), 20); ok_hex(Buffer[0], 0xf80000b2); ok_int(RtlFindSetBitsAndClear(&BitMapHeader, 4, 11), 27); ok_hex(Buffer[0], 0x800000b2); Buffer[0] = 0xF9F078B2; ok_int(RtlFindSetBitsAndClear(&BitMapHeader, 4, 12), 20); ok_hex(Buffer[0], 0xf90078b2); ok_int(RtlFindSetBitsAndClear(&BitMapHeader, 2, 11), 11); ok_hex(Buffer[0], 0xf90060b2); ok_int(RtlFindSetBitsAndClear(&BitMapHeader, 2, 12), 13); ok_hex(Buffer[0], 0xf90000b2); FreeGuarded(Buffer); }
void Test_RtlFindClearBitsAndSet(void) { RTL_BITMAP BitMapHeader; ULONG *Buffer; Buffer = AllocateGuarded(2 * sizeof(*Buffer)); Buffer[0] = 0x060F874D; Buffer[1] = 0x3F303F30; RtlInitializeBitMap(&BitMapHeader, Buffer, 0); ok_int(RtlFindClearBitsAndSet(&BitMapHeader, 0, 0), 0); ok_int(RtlFindClearBitsAndSet(&BitMapHeader, 0, 3), 0); ok_int(RtlFindClearBitsAndSet(&BitMapHeader, 1, 0), -1); ok_int(RtlFindClearBitsAndSet(&BitMapHeader, 1, 1), -1); ok_hex(Buffer[0], 0x060F874D); Buffer[0] = 0x060F874D; RtlInitializeBitMap(&BitMapHeader, Buffer, 8); ok_int(RtlFindClearBitsAndSet(&BitMapHeader, 1, 0), 1); ok_hex(Buffer[0], 0x60f874f); ok_int(RtlFindClearBitsAndSet(&BitMapHeader, 1, 1), 4); ok_hex(Buffer[0], 0x60f875f); ok_int(RtlFindClearBitsAndSet(&BitMapHeader, 1, 2), 5); ok_hex(Buffer[0], 0x60f877f); ok_int(RtlFindClearBitsAndSet(&BitMapHeader, 2, 0), -1); ok_hex(Buffer[0], 0x60f877f); Buffer[0] = 0x060F874D; RtlInitializeBitMap(&BitMapHeader, Buffer, 32); ok_int(RtlFindClearBitsAndSet(&BitMapHeader, 4, 0), 11); ok_hex(Buffer[0], 0x60fff4d); ok_int(RtlFindClearBitsAndSet(&BitMapHeader, 5, 0), 20); ok_hex(Buffer[0], 0x7ffff4d); ok_int(RtlFindClearBitsAndSet(&BitMapHeader, 4, 11), 27); ok_hex(Buffer[0], 0x7fffff4d); Buffer[0] = 0x060F874D; ok_int(RtlFindClearBitsAndSet(&BitMapHeader, 4, 12), 20); ok_hex(Buffer[0], 0x6ff874d); ok_int(RtlFindClearBitsAndSet(&BitMapHeader, 2, 11), 11); ok_hex(Buffer[0], 0x6ff9f4d); ok_int(RtlFindClearBitsAndSet(&BitMapHeader, 2, 12), 13); ok_hex(Buffer[0], 0x6ffff4d); FreeGuarded(Buffer); }
// Build MSR bitmap _Use_decl_annotations_ static void *VmpBuildMsrBitmap() { PAGED_CODE(); const auto msr_bitmap = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, kHyperPlatformCommonPoolTag); if (!msr_bitmap) { return nullptr; } RtlZeroMemory(msr_bitmap, PAGE_SIZE); // Activate VM-exit for RDMSR against all MSRs const auto bitmap_read_low = reinterpret_cast<UCHAR *>(msr_bitmap); const auto bitmap_read_high = bitmap_read_low + 1024; RtlFillMemory(bitmap_read_low, 1024, 0xff); // read 0 - 1fff RtlFillMemory(bitmap_read_high, 1024, 0xff); // read c0000000 - c0001fff // Ignore IA32_MPERF (000000e7) and IA32_APERF (000000e8) RTL_BITMAP bitmap_read_low_header = {}; RtlInitializeBitMap(&bitmap_read_low_header, reinterpret_cast<PULONG>(bitmap_read_low), 1024 * 8); RtlClearBits(&bitmap_read_low_header, 0xe7, 2); // Checks MSRs that cause #GP from 0 to 0xfff, and ignore all of them for (auto msr = 0ul; msr < 0x1000; ++msr) { __try { UtilReadMsr(static_cast<Msr>(msr)); } __except (EXCEPTION_EXECUTE_HANDLER) { RtlClearBits(&bitmap_read_low_header, msr, 1); } } // Ignore IA32_GS_BASE (c0000101) and IA32_KERNEL_GS_BASE (c0000102) RTL_BITMAP bitmap_read_high_header = {}; RtlInitializeBitMap(&bitmap_read_high_header, reinterpret_cast<PULONG>(bitmap_read_high), 1024 * CHAR_BIT); RtlClearBits(&bitmap_read_high_header, 0x101, 2); return msr_bitmap; }
void Test_RtlClearBits(void) { RTL_BITMAP BitMapHeader; ULONG *Buffer; ULONG BufferSize = 2 * sizeof(*Buffer); Buffer = AllocateGuarded(BufferSize); RtlInitializeBitMap(&BitMapHeader, Buffer, 19); memset(Buffer, 0xff, BufferSize); RtlClearBits(&BitMapHeader, 0, 0); ok_hex(Buffer[0], 0xffffffff); ok_hex(Buffer[1], 0xffffffff); memset(Buffer, 0xff, BufferSize); RtlClearBits(&BitMapHeader, 0, 1); ok_hex(Buffer[0], 0xfffffffe); ok_hex(Buffer[1], 0xffffffff); memset(Buffer, 0xff, BufferSize); RtlClearBits(&BitMapHeader, 21, 1); ok_hex(Buffer[0], 0xffdfffff); ok_hex(Buffer[1], 0xffffffff); memset(Buffer, 0xff, BufferSize); RtlClearBits(&BitMapHeader, 7, 9); ok_hex(Buffer[0], 0xffff007f); ok_hex(Buffer[1], 0xffffffff); memset(Buffer, 0xff, BufferSize); RtlClearBits(&BitMapHeader, 13, 22); ok_hex(Buffer[0], 0x00001fff); ok_hex(Buffer[1], 0xfffffff8); memset(Buffer, 0xff, BufferSize); RtlClearBits(&BitMapHeader, 63, 1); ok_hex(Buffer[0], 0xffffffff); ok_hex(Buffer[1], 0x7fffffff); memset(Buffer, 0xcc, BufferSize); RtlClearBits(&BitMapHeader, 3, 6); RtlClearBits(&BitMapHeader, 11, 5); RtlClearBits(&BitMapHeader, 21, 7); RtlClearBits(&BitMapHeader, 37, 4); ok_hex(Buffer[0], 0xc00c0404); ok_hex(Buffer[1], 0xcccccc0c); FreeGuarded(Buffer); }
void Test_RtlSetBits(void) { RTL_BITMAP BitMapHeader; ULONG *Buffer; ULONG BufferSize = 2 * sizeof(*Buffer); Buffer = AllocateGuarded(BufferSize); RtlInitializeBitMap(&BitMapHeader, Buffer, 19); memset(Buffer, 0x00, BufferSize); RtlSetBits(&BitMapHeader, 0, 0); ok_hex(Buffer[0], 0x00000000); ok_hex(Buffer[1], 0x00000000); memset(Buffer, 0x00, BufferSize); RtlSetBits(&BitMapHeader, 0, 1); ok_hex(Buffer[0], 0x00000001); ok_hex(Buffer[1], 0x00000000); memset(Buffer, 0x00, BufferSize); RtlSetBits(&BitMapHeader, 21, 1); ok_hex(Buffer[0], 0x00200000); ok_hex(Buffer[1], 0x00000000); memset(Buffer, 0x00, BufferSize); RtlSetBits(&BitMapHeader, 7, 9); ok_hex(Buffer[0], 0x0000ff80); ok_hex(Buffer[1], 0x00000000); memset(Buffer, 0x00, BufferSize); RtlSetBits(&BitMapHeader, 13, 22); ok_hex(Buffer[0], 0xffffe000); ok_hex(Buffer[1], 0x00000007); memset(Buffer, 0x00, BufferSize); RtlSetBits(&BitMapHeader, 63, 1); ok_hex(Buffer[0], 0x00000000); ok_hex(Buffer[1], 0x80000000); memset(Buffer, 0xcc, BufferSize); RtlSetBits(&BitMapHeader, 3, 6); RtlSetBits(&BitMapHeader, 11, 5); RtlSetBits(&BitMapHeader, 21, 7); RtlSetBits(&BitMapHeader, 37, 4); ok_hex(Buffer[0], 0xcfecfdfc); ok_hex(Buffer[1], 0xcccccdec); FreeGuarded(Buffer); }
VOID XmsInitialize(VOID) { RtlZeroMemory(HandleTable, sizeof(HandleTable)); RtlZeroMemory(BitmapBuffer, sizeof(BitmapBuffer)); RtlInitializeBitMap(&AllocBitmap, BitmapBuffer, XMS_BLOCKS); Node = DosCreateDeviceEx(DOS_DEVATTR_IOCTL | DOS_DEVATTR_CHARACTER, XMS_DEVICE_NAME, sizeof(EntryProcedure)); RegisterBop(BOP_XMS, XmsBopProcedure); /* Copy the entry routine to the device private area */ RtlMoveMemory(FAR_POINTER(DEVICE_PRIVATE_AREA(Node->Driver)), EntryProcedure, sizeof(EntryProcedure)); }
NTSTATUS PortsStartup( PPORT_SET PortSet, UINT StartingPort, UINT PortsToManage ) { PortSet->StartingPort = StartingPort; PortSet->PortsToOversee = PortsToManage; PortSet->ProtoBitBuffer = ExAllocatePoolWithTag( NonPagedPool, (PortSet->PortsToOversee + 7) / 8, PORT_SET_TAG ); if(!PortSet->ProtoBitBuffer) return STATUS_INSUFFICIENT_RESOURCES; RtlInitializeBitMap( &PortSet->ProtoBitmap, PortSet->ProtoBitBuffer, PortSet->PortsToOversee ); RtlClearAllBits( &PortSet->ProtoBitmap ); KeInitializeSpinLock( &PortSet->Lock ); return STATUS_SUCCESS; }
VOID test_bitmap() { Pool pool; ULONG Bitmap_Size, Index; PULONG Bitmap_Buffer; // Initialize Bitmap_Size = 13; // Number of bits Bitmap_Buffer = ExAllocatePoolWithTag ( NonPagedPool, (ULONG)(((Bitmap_Size/8+1)/sizeof(ULONG) + 1)* sizeof(ULONG)), BITMAP_TAG ); RtlInitializeBitMap( &pool.Bitmap, (PULONG)(Bitmap_Buffer), (ULONG)(Bitmap_Size) ); RtlClearAllBits(&pool.Bitmap); for (Index = 0; Index < 10; Index++) RtlSetBit(&pool.Bitmap, Index); if (RtlAreBitsSet(&pool.Bitmap, 0, 10) == TRUE) DbgPrint("bitmap: bit[0..9] is set\r\n"); if (RtlCheckBit(&pool.Bitmap, 10)) DbgPrint("bitmap: bit[10] is set\r\n"); if (RtlCheckBit(&pool.Bitmap, 1024)) //Warning! Return 1 here DbgPrint("bitmap: bit[1024] is set\r\n"); Index = 0; do { Index = RtlFindClearBitsAndSet ( &pool.Bitmap, 1, //NumberToFind Index //HintIndex ); DbgPrint("%d\n", Index); }while (Index != -1); // Free ExFreePoolWithTag(pool.Bitmap.Buffer, BITMAP_TAG); }
static PGDI_POOL_SECTION GdiPoolAllocateSection(PGDI_POOL pPool) { PGDI_POOL_SECTION pSection; PVOID pvBaseAddress; SIZE_T cjSize; NTSTATUS status; /* Allocate a section object */ cjSize = sizeof(GDI_POOL_SECTION) + pPool->cSlotsPerSection / sizeof(ULONG); pSection = EngAllocMem(0, cjSize, pPool->ulTag); if (!pSection) { return NULL; } /* Reserve user mode memory */ cjSize = GDI_POOL_ALLOCATION_GRANULARITY; pvBaseAddress = NULL; status = ZwAllocateVirtualMemory(NtCurrentProcess(), &pvBaseAddress, 0, &cjSize, MEM_RESERVE, PAGE_READWRITE); if (!NT_SUCCESS(status)) { EngFreeMem(pSection); return NULL; } /* Initialize the section */ pSection->pvBaseAddress = pvBaseAddress; pSection->ulCommitBitmap = 0; pSection->cAllocCount = 0; RtlInitializeBitMap(&pSection->bitmap, pSection->aulBits, pPool->cSlotsPerSection); RtlClearAllBits(&pSection->bitmap); /* Return the section */ return pSection; }
/*********************************************************************** * thread_init * * Setup the initial thread. * * NOTES: The first allocated TEB on NT is at 0x7ffde000. */ HANDLE thread_init(void) { TEB *teb; void *addr; SIZE_T size, info_size; HANDLE exe_file = 0; LARGE_INTEGER now; NTSTATUS status; struct ntdll_thread_data *thread_data; static struct debug_info debug_info; /* debug info for initial thread */ virtual_init(); /* reserve space for shared user data */ addr = (void *)0x7ffe0000; size = 0x10000; status = NtAllocateVirtualMemory( NtCurrentProcess(), &addr, 0, &size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE ); if (status) { MESSAGE( "wine: failed to map the shared user data: %08x\n", status ); exit(1); } user_shared_data = addr; /* allocate and initialize the PEB */ addr = NULL; size = sizeof(*peb); NtAllocateVirtualMemory( NtCurrentProcess(), &addr, 1, &size, MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE ); peb = addr; peb->ProcessParameters = ¶ms; peb->TlsBitmap = &tls_bitmap; peb->TlsExpansionBitmap = &tls_expansion_bitmap; peb->FlsBitmap = &fls_bitmap; peb->LdrData = &ldr; params.CurrentDirectory.DosPath.Buffer = current_dir; params.CurrentDirectory.DosPath.MaximumLength = sizeof(current_dir); params.wShowWindow = 1; /* SW_SHOWNORMAL */ ldr.Length = sizeof(ldr); RtlInitializeBitMap( &tls_bitmap, peb->TlsBitmapBits, sizeof(peb->TlsBitmapBits) * 8 ); RtlInitializeBitMap( &tls_expansion_bitmap, peb->TlsExpansionBitmapBits, sizeof(peb->TlsExpansionBitmapBits) * 8 ); RtlInitializeBitMap( &fls_bitmap, peb->FlsBitmapBits, sizeof(peb->FlsBitmapBits) * 8 ); InitializeListHead( &peb->FlsListHead ); InitializeListHead( &ldr.InLoadOrderModuleList ); InitializeListHead( &ldr.InMemoryOrderModuleList ); InitializeListHead( &ldr.InInitializationOrderModuleList ); #ifdef __APPLE__ peb->Reserved[0] = get_dyld_image_info_addr(); #endif /* allocate and initialize the initial TEB */ signal_alloc_thread( &teb ); teb->Peb = peb; teb->Tib.StackBase = (void *)~0UL; teb->StaticUnicodeString.Buffer = teb->StaticUnicodeBuffer; teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer); thread_data = (struct ntdll_thread_data *)teb->SpareBytes1; thread_data->request_fd = -1; thread_data->reply_fd = -1; thread_data->wait_fd[0] = -1; thread_data->wait_fd[1] = -1; thread_data->debug_info = &debug_info; InsertHeadList( &tls_links, &teb->TlsLinks ); signal_init_thread( teb ); virtual_init_threading(); debug_info.str_pos = debug_info.strings; debug_info.out_pos = debug_info.output; debug_init(); /* setup the server connection */ server_init_process(); info_size = server_init_thread( peb ); /* create the process heap */ if (!(peb->ProcessHeap = RtlCreateHeap( HEAP_GROWABLE, NULL, 0, 0, NULL, NULL ))) { MESSAGE( "wine: failed to create the process heap\n" ); exit(1); } /* allocate user parameters */ if (info_size) { init_user_process_params( info_size, &exe_file ); } else { if (isatty(0) || isatty(1) || isatty(2)) params.ConsoleHandle = (HANDLE)2; /* see kernel32/kernel_private.h */ if (!isatty(0)) wine_server_fd_to_handle( 0, GENERIC_READ|SYNCHRONIZE, OBJ_INHERIT, ¶ms.hStdInput ); if (!isatty(1)) wine_server_fd_to_handle( 1, GENERIC_WRITE|SYNCHRONIZE, OBJ_INHERIT, ¶ms.hStdOutput ); if (!isatty(2)) wine_server_fd_to_handle( 2, GENERIC_WRITE|SYNCHRONIZE, OBJ_INHERIT, ¶ms.hStdError ); } /* initialize time values in user_shared_data */ NtQuerySystemTime( &now ); user_shared_data->SystemTime.LowPart = now.u.LowPart; user_shared_data->SystemTime.High1Time = user_shared_data->SystemTime.High2Time = now.u.HighPart; user_shared_data->u.TickCountQuad = (now.QuadPart - server_start_time) / 10000; user_shared_data->u.TickCount.High2Time = user_shared_data->u.TickCount.High1Time; user_shared_data->TickCountLowDeprecated = user_shared_data->u.TickCount.LowPart; user_shared_data->TickCountMultiplier = 1 << 24; fill_cpu_info(); NtCreateKeyedEvent( &keyed_event, GENERIC_READ | GENERIC_WRITE, NULL, 0 ); return exe_file; }
/****************************************************************** * macho_map_file * * Maps a Mach-O file into memory (and checks it's a real Mach-O file) */ static BOOL macho_map_file(const WCHAR* filenameW, struct macho_file_map* fmap) { struct fat_header fat_header; struct stat statbuf; int i; char* filename; unsigned len; BOOL ret = FALSE; TRACE("(%s, %p)\n", debugstr_w(filenameW), fmap); fmap->fd = -1; fmap->load_commands = MACHO_NO_MAP; RtlInitializeBitMap(&fmap->sect_is_code, fmap->sect_is_code_buff, MAX_SECT + 1); len = WideCharToMultiByte(CP_UNIXCP, 0, filenameW, -1, NULL, 0, NULL, NULL); if (!(filename = HeapAlloc(GetProcessHeap(), 0, len))) return FALSE; WideCharToMultiByte(CP_UNIXCP, 0, filenameW, -1, filename, len, NULL, NULL); /* check that the file exists */ if (stat(filename, &statbuf) == -1 || S_ISDIR(statbuf.st_mode)) goto done; /* Now open the file, so that we can mmap() it. */ if ((fmap->fd = open(filename, O_RDONLY)) == -1) goto done; if (read(fmap->fd, &fat_header, sizeof(fat_header)) != sizeof(fat_header)) goto done; TRACE("... got possible fat header\n"); /* Fat header is always in big-endian order. */ if (swap_ulong_be_to_host(fat_header.magic) == FAT_MAGIC) { int narch = swap_ulong_be_to_host(fat_header.nfat_arch); for (i = 0; i < narch; i++) { struct fat_arch fat_arch; if (read(fmap->fd, &fat_arch, sizeof(fat_arch)) != sizeof(fat_arch)) goto done; if (swap_ulong_be_to_host(fat_arch.cputype) == CPU_TYPE_X86) { fmap->arch_offset = swap_ulong_be_to_host(fat_arch.offset); fmap->arch_size = swap_ulong_be_to_host(fat_arch.size); break; } } if (i >= narch) goto done; TRACE("... found x86 arch\n"); } else { fmap->arch_offset = 0; fmap->arch_size = statbuf.st_size; TRACE("... not a fat header\n"); } /* Individual architecture (standalone or within a fat file) is in its native byte order. */ lseek(fmap->fd, fmap->arch_offset, SEEK_SET); if (read(fmap->fd, &fmap->mach_header, sizeof(fmap->mach_header)) != sizeof(fmap->mach_header)) goto done; TRACE("... got possible Mach header\n"); /* and check for a Mach-O header */ if (fmap->mach_header.magic != MH_MAGIC || fmap->mach_header.cputype != CPU_TYPE_X86) goto done; /* Make sure the file type is one of the ones we expect. */ switch (fmap->mach_header.filetype) { case MH_EXECUTE: case MH_DYLIB: case MH_DYLINKER: case MH_BUNDLE: break; default: goto done; } TRACE("... verified Mach x86 header\n"); fmap->segs_size = 0; fmap->segs_start = ~0L; if (macho_enum_load_commands(fmap, LC_SEGMENT, macho_accum_segs_range, NULL) < 0) goto done; fmap->segs_size -= fmap->segs_start; TRACE("segs_start: 0x%08x, segs_size: 0x%08x\n", (unsigned)fmap->segs_start, (unsigned)fmap->segs_size); ret = TRUE; done: if (!ret) macho_unmap_file(fmap); HeapFree(GetProcessHeap(), 0, filename); return ret; }
_Use_decl_annotations_ EXTERN_C static bool VminitpSetupVMCS( const PER_PROCESSOR_DATA *ProcessorData, ULONG_PTR GuestStackPointer, ULONG_PTR GuestInstructionPointer, ULONG_PTR VmmStackPointer) { unsigned char error = 0; GDTR gdtr = {}; __sgdt(&gdtr); IDTR idtr = {}; __sidt(&idtr); VMX_VM_ENTER_CONTROLS vmEnterCtlRequested = {}; vmEnterCtlRequested.Fields.IA32eModeGuest = true; VMX_VM_ENTER_CONTROLS vmEnterCtl = { VminitpAdjustControlValue(IA32_VMX_ENTRY_CTLS, vmEnterCtlRequested.All)}; VMX_VM_EXIT_CONTROLS vmExitCtlRequested = {}; vmExitCtlRequested.Fields.AcknowledgeInterruptOnExit = true; vmExitCtlRequested.Fields.HostAddressSpaceSize = true; VMX_VM_EXIT_CONTROLS vmExitCtl = { VminitpAdjustControlValue(IA32_VMX_EXIT_CTLS, vmExitCtlRequested.All)}; VMX_PIN_BASED_CONTROLS vmPinCtlRequested = {}; VMX_PIN_BASED_CONTROLS vmPinCtl = { VminitpAdjustControlValue(IA32_VMX_PINBASED_CTLS, vmPinCtlRequested.All)}; VMX_CPU_BASED_CONTROLS vmCpuCtlRequested = {}; vmCpuCtlRequested.Fields.RDTSCExiting = true; vmCpuCtlRequested.Fields.CR3LoadExiting = true; // MOV to CR3 vmCpuCtlRequested.Fields.CR8LoadExiting = true; // MOV to CR8 vmCpuCtlRequested.Fields.MovDRExiting = true; vmCpuCtlRequested.Fields.UseMSRBitmaps = true; vmCpuCtlRequested.Fields.ActivateSecondaryControl = true; VMX_CPU_BASED_CONTROLS vmCpuCtl = {VminitpAdjustControlValue( IA32_VMX_PROCBASED_CTLS, vmCpuCtlRequested.All)}; VMX_SECONDARY_CPU_BASED_CONTROLS vmCpuCtl2Requested = {}; vmCpuCtl2Requested.Fields.EnableRDTSCP = true; vmCpuCtl2Requested.Fields.DescriptorTableExiting = true; VMX_CPU_BASED_CONTROLS vmCpuCtl2 = {VminitpAdjustControlValue( IA32_VMX_PROCBASED_CTLS2, vmCpuCtl2Requested.All)}; // Set up the MSR bitmap // Activate VM-exit for RDMSR against all MSRs const auto bitMapReadLow = reinterpret_cast<UCHAR *>(ProcessorData->MsrBitmap); const auto bitMapReadHigh = bitMapReadLow + 1024; RtlFillMemory(bitMapReadLow, 1024, 0xff); // read 0 - 1fff RtlFillMemory(bitMapReadHigh, 1024, 0xff); // read c0000000 - c0001fff // But ignore IA32_MPERF (000000e7) and IA32_APERF (000000e8) RTL_BITMAP bitMapReadLowHeader = {}; RtlInitializeBitMap(&bitMapReadLowHeader, reinterpret_cast<PULONG>(bitMapReadLow), 1024 * 8); RtlClearBits(&bitMapReadLowHeader, 0xe7, 2); // But ignore IA32_GS_BASE (c0000101) and IA32_KERNEL_GS_BASE (c0000102) RTL_BITMAP bitMapReadHighHeader = {}; RtlInitializeBitMap(&bitMapReadHighHeader, reinterpret_cast<PULONG>(bitMapReadHigh), 1024 * 8); RtlClearBits(&bitMapReadHighHeader, 0x101, 2); const auto msrBitmapPA = MmGetPhysicalAddress(ProcessorData->MsrBitmap); // Set up CR0 and CR4 bitmaps // Where a bit is masked, the shadow bit appears // Where a bit is not masked, the actual bit appears CR0_REG cr0mask = {}; cr0mask.Fields.WP = true; CR4_REG cr4mask = {}; cr4mask.Fields.PGE = true; // clang-format off /* 16-Bit Control Field */ /* 16-Bit Guest-State Fields */ error |= __vmx_vmwrite(GUEST_ES_SELECTOR, AsmReadES()); error |= __vmx_vmwrite(GUEST_CS_SELECTOR, AsmReadCS()); error |= __vmx_vmwrite(GUEST_SS_SELECTOR, AsmReadSS()); error |= __vmx_vmwrite(GUEST_DS_SELECTOR, AsmReadDS()); error |= __vmx_vmwrite(GUEST_FS_SELECTOR, AsmReadFS()); error |= __vmx_vmwrite(GUEST_GS_SELECTOR, AsmReadGS()); error |= __vmx_vmwrite(GUEST_LDTR_SELECTOR, AsmReadLDTR()); error |= __vmx_vmwrite(GUEST_TR_SELECTOR, AsmReadTR()); /* 16-Bit Host-State Fields */ error |= __vmx_vmwrite(HOST_ES_SELECTOR, AsmReadES() & 0xf8); // RPL and TI error |= __vmx_vmwrite(HOST_CS_SELECTOR, AsmReadCS() & 0xf8); // have to be 0 error |= __vmx_vmwrite(HOST_SS_SELECTOR, AsmReadSS() & 0xf8); error |= __vmx_vmwrite(HOST_DS_SELECTOR, AsmReadDS() & 0xf8); error |= __vmx_vmwrite(HOST_FS_SELECTOR, AsmReadFS() & 0xf8); error |= __vmx_vmwrite(HOST_GS_SELECTOR, AsmReadGS() & 0xf8); error |= __vmx_vmwrite(HOST_TR_SELECTOR, AsmReadTR() & 0xf8); /* 64-Bit Control Fields */ error |= __vmx_vmwrite(IO_BITMAP_A, 0); error |= __vmx_vmwrite(IO_BITMAP_B, 0); error |= __vmx_vmwrite(MSR_BITMAP, msrBitmapPA.QuadPart); error |= __vmx_vmwrite(TSC_OFFSET, 0); /* 64-Bit Guest-State Fields */ error |= __vmx_vmwrite(VMCS_LINK_POINTER, 0xffffffffffffffff); error |= __vmx_vmwrite(GUEST_IA32_DEBUGCTL, __readmsr(IA32_DEBUGCTL)); /* 32-Bit Control Fields */ error |= __vmx_vmwrite(PIN_BASED_VM_EXEC_CONTROL, vmPinCtl.All); error |= __vmx_vmwrite(CPU_BASED_VM_EXEC_CONTROL, vmCpuCtl.All); error |= __vmx_vmwrite(SECONDARY_VM_EXEC_CONTROL, vmCpuCtl2.All); error |= __vmx_vmwrite(EXCEPTION_BITMAP, 0); error |= __vmx_vmwrite(PAGE_FAULT_ERROR_CODE_MASK, 0); error |= __vmx_vmwrite(PAGE_FAULT_ERROR_CODE_MATCH, 0); error |= __vmx_vmwrite(CR3_TARGET_COUNT, 0); error |= __vmx_vmwrite(VM_EXIT_CONTROLS, vmExitCtl.All); error |= __vmx_vmwrite(VM_EXIT_MSR_STORE_COUNT, 0); error |= __vmx_vmwrite(VM_EXIT_MSR_LOAD_COUNT, 0); error |= __vmx_vmwrite(VM_ENTRY_CONTROLS, vmEnterCtl.All); error |= __vmx_vmwrite(VM_ENTRY_MSR_LOAD_COUNT, 0); error |= __vmx_vmwrite(VM_ENTRY_INTR_INFO_FIELD, 0); /* 32-Bit Guest-State Fields */ error |= __vmx_vmwrite(GUEST_ES_LIMIT, GetSegmentLimit(AsmReadES())); error |= __vmx_vmwrite(GUEST_CS_LIMIT, GetSegmentLimit(AsmReadCS())); error |= __vmx_vmwrite(GUEST_SS_LIMIT, GetSegmentLimit(AsmReadSS())); error |= __vmx_vmwrite(GUEST_DS_LIMIT, GetSegmentLimit(AsmReadDS())); error |= __vmx_vmwrite(GUEST_FS_LIMIT, GetSegmentLimit(AsmReadFS())); error |= __vmx_vmwrite(GUEST_GS_LIMIT, GetSegmentLimit(AsmReadGS())); error |= __vmx_vmwrite(GUEST_LDTR_LIMIT, GetSegmentLimit(AsmReadLDTR())); error |= __vmx_vmwrite(GUEST_TR_LIMIT, GetSegmentLimit(AsmReadTR())); error |= __vmx_vmwrite(GUEST_GDTR_LIMIT, gdtr.Limit); error |= __vmx_vmwrite(GUEST_IDTR_LIMIT, idtr.Limit); error |= __vmx_vmwrite(GUEST_ES_AR_BYTES, VminitpGetSegmentAccessRight(AsmReadES())); error |= __vmx_vmwrite(GUEST_CS_AR_BYTES, VminitpGetSegmentAccessRight(AsmReadCS())); error |= __vmx_vmwrite(GUEST_SS_AR_BYTES, VminitpGetSegmentAccessRight(AsmReadSS())); error |= __vmx_vmwrite(GUEST_DS_AR_BYTES, VminitpGetSegmentAccessRight(AsmReadDS())); error |= __vmx_vmwrite(GUEST_FS_AR_BYTES, VminitpGetSegmentAccessRight(AsmReadFS())); error |= __vmx_vmwrite(GUEST_GS_AR_BYTES, VminitpGetSegmentAccessRight(AsmReadGS())); error |= __vmx_vmwrite(GUEST_LDTR_AR_BYTES, VminitpGetSegmentAccessRight(AsmReadLDTR())); error |= __vmx_vmwrite(GUEST_TR_AR_BYTES, VminitpGetSegmentAccessRight(AsmReadTR())); error |= __vmx_vmwrite(GUEST_INTERRUPTIBILITY_INFO, 0); error |= __vmx_vmwrite(GUEST_ACTIVITY_STATE, 0); error |= __vmx_vmwrite(GUEST_SYSENTER_CS, __readmsr(IA32_SYSENTER_CS)); /* 32-Bit Host-State Field */ error |= __vmx_vmwrite(HOST_IA32_SYSENTER_CS, __readmsr(IA32_SYSENTER_CS)); /* Natural-Width Control Fields */ error |= __vmx_vmwrite(CR0_GUEST_HOST_MASK, cr0mask.All); error |= __vmx_vmwrite(CR4_GUEST_HOST_MASK, cr4mask.All); error |= __vmx_vmwrite(CR0_READ_SHADOW, __readcr0()); error |= __vmx_vmwrite(CR4_READ_SHADOW, __readcr4()); error |= __vmx_vmwrite(CR3_TARGET_VALUE0, 0); error |= __vmx_vmwrite(CR3_TARGET_VALUE1, 0); error |= __vmx_vmwrite(CR3_TARGET_VALUE2, 0); error |= __vmx_vmwrite(CR3_TARGET_VALUE3, 0); /* Natural-Width Guest-State Fields */ error |= __vmx_vmwrite(GUEST_CR0, __readcr0()); error |= __vmx_vmwrite(GUEST_CR3, __readcr3()); error |= __vmx_vmwrite(GUEST_CR4, __readcr4()); error |= __vmx_vmwrite(GUEST_ES_BASE, 0); error |= __vmx_vmwrite(GUEST_CS_BASE, 0); error |= __vmx_vmwrite(GUEST_SS_BASE, 0); error |= __vmx_vmwrite(GUEST_DS_BASE, 0); error |= __vmx_vmwrite(GUEST_FS_BASE, __readmsr(IA32_FS_BASE)); error |= __vmx_vmwrite(GUEST_GS_BASE, __readmsr(IA32_GS_BASE)); error |= __vmx_vmwrite(GUEST_LDTR_BASE, VminitpGetSegmentBase(gdtr.Address, AsmReadLDTR())); error |= __vmx_vmwrite(GUEST_TR_BASE, VminitpGetSegmentBase(gdtr.Address, AsmReadTR())); error |= __vmx_vmwrite(GUEST_GDTR_BASE, gdtr.Address); error |= __vmx_vmwrite(GUEST_IDTR_BASE, idtr.Address); error |= __vmx_vmwrite(GUEST_DR7, __readdr(7)); error |= __vmx_vmwrite(GUEST_RSP, GuestStackPointer); error |= __vmx_vmwrite(GUEST_RIP, GuestInstructionPointer); error |= __vmx_vmwrite(GUEST_RFLAGS, __readeflags()); error |= __vmx_vmwrite(GUEST_SYSENTER_ESP, __readmsr(IA32_SYSENTER_ESP)); error |= __vmx_vmwrite(GUEST_SYSENTER_EIP, __readmsr(IA32_SYSENTER_EIP)); /* Natural-Width Host-State Fields */ error |= __vmx_vmwrite(HOST_CR0, __readcr0()); error |= __vmx_vmwrite(HOST_CR3, __readcr3()); error |= __vmx_vmwrite(HOST_CR4, __readcr4()); error |= __vmx_vmwrite(HOST_FS_BASE, __readmsr(IA32_FS_BASE)); error |= __vmx_vmwrite(HOST_GS_BASE, __readmsr(IA32_GS_BASE)); error |= __vmx_vmwrite(HOST_TR_BASE, VminitpGetSegmentBase(gdtr.Address, AsmReadTR())); error |= __vmx_vmwrite(HOST_GDTR_BASE, gdtr.Address); error |= __vmx_vmwrite(HOST_IDTR_BASE, idtr.Address); error |= __vmx_vmwrite(HOST_IA32_SYSENTER_ESP, __readmsr(IA32_SYSENTER_ESP)); error |= __vmx_vmwrite(HOST_IA32_SYSENTER_EIP, __readmsr(IA32_SYSENTER_EIP)); error |= __vmx_vmwrite(HOST_RSP, VmmStackPointer); error |= __vmx_vmwrite(HOST_RIP, reinterpret_cast<size_t>(AsmVmmEntryPoint)); // clang-format on const auto vmxStatus = static_cast<VMX_STATUS>(error); return vmxStatus == VMX_OK; }
VOID D3DKMTInitialize() { VOID *gdi32 = NULL; VOID *deviceInfoSet; UINT32 result; UINT32 memberIndex; UINT32 detailDataSize; SP_DEVICE_INTERFACE_DATA deviceInterfaceData; SP_DEVICE_INTERFACE_DETAIL_DATA_W *detailData; SP_DEVINFO_DATA deviceInfoData; //D3DKMT_OPENADAPTERFROMDEVICENAME openAdapterFromDeviceName; D3DKMT_QUERYSTATISTICS queryStatistics; gdi32 = Module::Load(L"gdi32.dll"); if (!gdi32) { return; } D3DKMTOpenAdapterFromDeviceName = (TYPE_D3DKMTOpenAdapterFromDeviceName) Module::GetProcedureAddress( gdi32, "D3DKMTOpenAdapterFromDeviceName" ); D3DKMTQueryStatistics = (TYPE_D3DKMTQueryStatistics) Module::GetProcedureAddress(gdi32, "D3DKMTQueryStatistics"); if (!D3DKMTOpenAdapterFromDeviceName || !D3DKMTQueryStatistics) { return; } deviceInfoSet = SetupDiGetClassDevsW(&GUID_DISPLAY_DEVICE_ARRIVAL_I, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); if (!deviceInfoSet) { return; } memberIndex = 0; deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); while (SetupDiEnumDeviceInterfaces(deviceInfoSet, NULL, &GUID_DISPLAY_DEVICE_ARRIVAL_I, memberIndex, &deviceInterfaceData)) { detailDataSize = 0x100; detailData = (SP_DEVICE_INTERFACE_DETAIL_DATA_W*) Memory::Allocate(detailDataSize); detailData->cbSize = 6; /*sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W)*/ deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); result = SetupDiGetDeviceInterfaceDetailW( deviceInfoSet, &deviceInterfaceData, detailData, detailDataSize, &detailDataSize, &deviceInfoData ); if (result) { openAdapterFromDeviceName.pDeviceName = detailData->DevicePath; if (NT_SUCCESS(D3DKMTOpenAdapterFromDeviceName(&openAdapterFromDeviceName))) { memset(&queryStatistics, 0, sizeof(D3DKMT_QUERYSTATISTICS)); queryStatistics.Type = D3DKMT_QUERYSTATISTICS_ADAPTER; queryStatistics.AdapterLuid = openAdapterFromDeviceName.AdapterLuid; if (NT_SUCCESS(D3DKMTQueryStatistics(&queryStatistics))) { UINT32 i; D3dkmt_GpuAdapter = AllocateGpuAdapter(queryStatistics.QueryResult.AdapterInformation.NbSegments); D3dkmt_GpuAdapter->AdapterLuid = openAdapterFromDeviceName.AdapterLuid; D3dkmt_GpuAdapter->NodeCount = queryStatistics.QueryResult.AdapterInformation.NodeCount; D3dkmt_GpuAdapter->SegmentCount = queryStatistics.QueryResult.AdapterInformation.NbSegments; RtlInitializeBitMap( &D3dkmt_GpuAdapter->ApertureBitMap, D3dkmt_GpuAdapter->ApertureBitMapBuffer, queryStatistics.QueryResult.AdapterInformation.NbSegments ); EtGpuTotalNodeCount += D3dkmt_GpuAdapter->NodeCount; EtGpuTotalSegmentCount += D3dkmt_GpuAdapter->SegmentCount; D3dkmt_GpuAdapter->FirstNodeIndex = EtGpuNextNodeIndex; EtGpuNextNodeIndex += D3dkmt_GpuAdapter->NodeCount; for (i = 0; i < D3dkmt_GpuAdapter->SegmentCount; i++) { memset(&queryStatistics, 0, sizeof(D3DKMT_QUERYSTATISTICS)); queryStatistics.Type = D3DKMT_QUERYSTATISTICS_SEGMENT; queryStatistics.AdapterLuid = D3dkmt_GpuAdapter->AdapterLuid; queryStatistics.QuerySegment.SegmentId = i; if (NT_SUCCESS(D3DKMTQueryStatistics(&queryStatistics))) { UINT64 commitLimit; UINT32 aperature; commitLimit = queryStatistics.QueryResult.SegmentInformationV1.CommitLimit; aperature = queryStatistics.QueryResult.SegmentInformationV1.Aperture; if (aperature) RtlSetBits(&D3dkmt_GpuAdapter->ApertureBitMap, i, 1); else EtGpuDedicatedLimit += commitLimit; } } } } } Memory::Free(detailData); memberIndex++; } SetupDiDestroyDeviceInfoList(deviceInfoSet); EtGpuNodeBitMapBuffer = (UINT32*) Memory::Allocate(BYTES_NEEDED_FOR_BITS(EtGpuTotalNodeCount)); RtlInitializeBitMap(&EtGpuNodeBitMap, EtGpuNodeBitMapBuffer, EtGpuTotalNodeCount); EtGpuNodesTotalRunningTimeDelta = (PPH_UINT64_DELTA) Memory::Allocate(sizeof(PH_UINT64_DELTA) * EtGpuTotalNodeCount); memset(EtGpuNodesTotalRunningTimeDelta, 0, sizeof(PH_UINT64_DELTA) * EtGpuTotalNodeCount); }
/*********************************************************************** * thread_init * * Setup the initial thread. * * NOTES: The first allocated TEB on NT is at 0x7ffde000. */ HANDLE thread_init(void) { TEB *teb; void *addr; SIZE_T size, info_size; HANDLE exe_file = 0; NTSTATUS status; struct ntdll_thread_data *thread_data; static struct debug_info debug_info; /* debug info for initial thread */ #ifdef __APPLE__ ULONG64 dyld_image_info; #endif virtual_init(); signal_init_early(); /* reserve space for shared user data */ addr = (void *)0x7ffe0000; size = 0x10000; status = NtAllocateVirtualMemory( NtCurrentProcess(), &addr, 0, &size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE ); if (status) { MESSAGE( "wine: failed to map the shared user data: %08x\n", status ); exit(1); } user_shared_data = addr; /* allocate and initialize the PEB */ addr = NULL; size = sizeof(*peb); NtAllocateVirtualMemory( NtCurrentProcess(), &addr, 1, &size, MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE ); peb = addr; peb->ProcessParameters = ¶ms; peb->TlsBitmap = &tls_bitmap; peb->TlsExpansionBitmap = &tls_expansion_bitmap; peb->FlsBitmap = &fls_bitmap; peb->LdrData = &ldr; peb->OSMajorVersion = 5; peb->OSMinorVersion = 1; peb->OSBuildNumber = 0xA28; peb->OSPlatformId = VER_PLATFORM_WIN32_NT; params.CurrentDirectory.DosPath.Buffer = current_dir; params.CurrentDirectory.DosPath.MaximumLength = sizeof(current_dir); params.wShowWindow = 1; /* SW_SHOWNORMAL */ ldr.Length = sizeof(ldr); RtlInitializeBitMap( &tls_bitmap, peb->TlsBitmapBits, sizeof(peb->TlsBitmapBits) * 8 ); RtlInitializeBitMap( &tls_expansion_bitmap, peb->TlsExpansionBitmapBits, sizeof(peb->TlsExpansionBitmapBits) * 8 ); RtlInitializeBitMap( &fls_bitmap, peb->FlsBitmapBits, sizeof(peb->FlsBitmapBits) * 8 ); RtlSetBits( peb->TlsBitmap, 0, 1 ); /* TLS index 0 is reserved and should be initialized to NULL. */ RtlSetBits( peb->FlsBitmap, 0, 1 ); InitializeListHead( &peb->FlsListHead ); InitializeListHead( &ldr.InLoadOrderModuleList ); InitializeListHead( &ldr.InMemoryOrderModuleList ); InitializeListHead( &ldr.InInitializationOrderModuleList ); #ifdef __APPLE__ dyld_image_info = get_dyld_image_info_addr(); #ifdef __LP64__ #ifdef WORDS_BIGENDIAN peb->Reserved[1] = dyld_image_info & 0xFFFFFFFF; peb->Reserved[0] = dyld_image_info >> 32; #else peb->Reserved[0] = dyld_image_info & 0xFFFFFFFF; peb->Reserved[1] = dyld_image_info >> 32; #endif #else peb->Reserved[0] = dyld_image_info & 0xFFFFFFFF; #endif #endif /* * Starting with Vista, the first user to log on has session id 1. * Session id 0 is for processes that don't interact with the user (like services). */ peb->SessionId = 1; /* allocate and initialize the initial TEB */ signal_alloc_thread( &teb ); teb->Peb = peb; teb->Tib.StackBase = (void *)~0UL; teb->StaticUnicodeString.Buffer = teb->StaticUnicodeBuffer; teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer); thread_data = (struct ntdll_thread_data *)teb->SpareBytes1; thread_data->request_fd = -1; thread_data->reply_fd = -1; thread_data->wait_fd[0] = -1; thread_data->wait_fd[1] = -1; thread_data->debug_info = &debug_info; InsertHeadList( &tls_links, &teb->TlsLinks ); signal_init_thread( teb ); virtual_init_threading(); debug_info.str_pos = debug_info.strings; debug_info.out_pos = debug_info.output; debug_init(); /* setup the server connection */ server_init_process(); info_size = server_init_thread( peb ); /* create the process heap */ if (!(peb->ProcessHeap = RtlCreateHeap( HEAP_GROWABLE, NULL, 0, 0, NULL, NULL ))) { MESSAGE( "wine: failed to create the process heap\n" ); exit(1); } /* allocate user parameters */ if (info_size) { init_user_process_params( info_size, &exe_file ); } else { if (isatty(0) || isatty(1) || isatty(2)) params.ConsoleHandle = (HANDLE)2; /* see kernel32/kernel_private.h */ if (!isatty(0)) wine_server_fd_to_handle( 0, GENERIC_READ|SYNCHRONIZE, OBJ_INHERIT, ¶ms.hStdInput ); if (!isatty(1)) wine_server_fd_to_handle( 1, GENERIC_WRITE|SYNCHRONIZE, OBJ_INHERIT, ¶ms.hStdOutput ); if (!isatty(2)) wine_server_fd_to_handle( 2, GENERIC_WRITE|SYNCHRONIZE, OBJ_INHERIT, ¶ms.hStdError ); } /* initialize user_shared_data */ __wine_user_shared_data(); fill_cpu_info(); NtCreateKeyedEvent( &keyed_event, GENERIC_READ | GENERIC_WRITE, NULL, 0 ); return exe_file; }
/// <summary> /// Setup VMCS fields /// </summary> /// <param name="VpData">Virtual CPU data</param> VOID VmxSetupVMCS( IN PVCPU VpData ) { PKPROCESSOR_STATE state = &VpData->HostState; VMX_GDTENTRY64 vmxGdtEntry = { 0 }; VMX_VM_ENTER_CONTROLS vmEnterCtlRequested = { 0 }; VMX_VM_EXIT_CONTROLS vmExitCtlRequested = { 0 }; VMX_PIN_BASED_CONTROLS vmPinCtlRequested = { 0 }; VMX_CPU_BASED_CONTROLS vmCpuCtlRequested = { 0 }; VMX_SECONDARY_CPU_BASED_CONTROLS vmCpuCtl2Requested = { 0 }; // As we exit back into the guest, make sure to exist in x64 mode as well. vmEnterCtlRequested.Fields.IA32eModeGuest = TRUE; // If any interrupts were pending upon entering the hypervisor, acknowledge // them when we're done. And make sure to enter us in x64 mode at all times vmExitCtlRequested.Fields.AcknowledgeInterruptOnExit = TRUE; vmExitCtlRequested.Fields.HostAddressSpaceSize = TRUE; // In order for our choice of supporting RDTSCP and XSAVE/RESTORES above to // actually mean something, we have to request secondary controls. We also // want to activate the MSR bitmap in order to keep them from being caught. vmCpuCtlRequested.Fields.UseMSRBitmaps = TRUE; vmCpuCtlRequested.Fields.ActivateSecondaryControl = TRUE; //vmCpuCtlRequested.Fields.UseTSCOffseting = TRUE; //vmCpuCtlRequested.Fields.RDTSCExiting = TRUE; // VPID caches must be invalidated on CR3 change if(g_Data->Features.VPID) vmCpuCtlRequested.Fields.CR3LoadExiting = TRUE; // Enable support for RDTSCP and XSAVES/XRESTORES in the guest. Windows 10 // makes use of both of these instructions if the CPU supports it. By using // VmxpAdjustMsr, these options will be ignored if this processor does // not actually support the instructions to begin with. vmCpuCtl2Requested.Fields.EnableRDTSCP = TRUE; vmCpuCtl2Requested.Fields.EnableXSAVESXSTORS = TRUE; // Begin by setting the link pointer to the required value for 4KB VMCS. __vmx_vmwrite( VMCS_LINK_POINTER, MAXULONG64 ); __vmx_vmwrite( PIN_BASED_VM_EXEC_CONTROL, VmxpAdjustMsr( VpData->MsrData[VMX_MSR( MSR_IA32_VMX_TRUE_PINBASED_CTLS )], vmPinCtlRequested.All ) ); __vmx_vmwrite( CPU_BASED_VM_EXEC_CONTROL, VmxpAdjustMsr( VpData->MsrData[VMX_MSR( MSR_IA32_VMX_TRUE_PROCBASED_CTLS )], vmCpuCtlRequested.All ) ); __vmx_vmwrite( SECONDARY_VM_EXEC_CONTROL, VmxpAdjustMsr( VpData->MsrData[VMX_MSR( MSR_IA32_VMX_PROCBASED_CTLS2 )], vmCpuCtl2Requested.All ) ); __vmx_vmwrite( VM_EXIT_CONTROLS, VmxpAdjustMsr( VpData->MsrData[VMX_MSR( MSR_IA32_VMX_TRUE_EXIT_CTLS )], vmExitCtlRequested.All ) ); __vmx_vmwrite( VM_ENTRY_CONTROLS, VmxpAdjustMsr( VpData->MsrData[VMX_MSR( MSR_IA32_VMX_TRUE_ENTRY_CTLS )], vmEnterCtlRequested.All ) ); // Load the MSR bitmap. Unlike other bitmaps, not having an MSR bitmap will // trap all MSRs, so have to allocate an empty one. PUCHAR bitMapReadLow = g_Data->MSRBitmap; // 0x00000000 - 0x00001FFF PUCHAR bitMapReadHigh = bitMapReadLow + 1024; // 0xC0000000 - 0xC0001FFF RTL_BITMAP bitMapReadLowHeader = { 0 }; RTL_BITMAP bitMapReadHighHeader = { 0 }; RtlInitializeBitMap( &bitMapReadLowHeader, (PULONG)bitMapReadLow, 1024 * 8 ); RtlInitializeBitMap( &bitMapReadHighHeader, (PULONG)bitMapReadHigh, 1024 * 8 ); RtlSetBit( &bitMapReadLowHeader, MSR_IA32_FEATURE_CONTROL ); // MSR_IA32_FEATURE_CONTROL RtlSetBit( &bitMapReadLowHeader, MSR_IA32_DEBUGCTL ); // MSR_DEBUGCTL RtlSetBit( &bitMapReadHighHeader, MSR_LSTAR - 0xC0000000 ); // MSR_LSTAR // VMX MSRs for (ULONG i = MSR_IA32_VMX_BASIC; i <= MSR_IA32_VMX_VMFUNC; i++) RtlSetBit( &bitMapReadLowHeader, i ); __vmx_vmwrite( MSR_BITMAP, MmGetPhysicalAddress( g_Data->MSRBitmap ).QuadPart ); // Exception bitmap ULONG ExceptionBitmap = 0; //ExceptionBitmap |= 1 << VECTOR_DEBUG_EXCEPTION; ExceptionBitmap |= 1 << VECTOR_BREAKPOINT_EXCEPTION; __vmx_vmwrite( EXCEPTION_BITMAP, ExceptionBitmap ); // CS (Ring 0 Code) VmxpConvertGdtEntry( state->SpecialRegisters.Gdtr.Base, state->ContextFrame.SegCs, &vmxGdtEntry ); __vmx_vmwrite( GUEST_CS_SELECTOR, vmxGdtEntry.Selector ); __vmx_vmwrite( GUEST_CS_LIMIT, vmxGdtEntry.Limit ); __vmx_vmwrite( GUEST_CS_AR_BYTES, vmxGdtEntry.AccessRights ); __vmx_vmwrite( GUEST_CS_BASE, vmxGdtEntry.Base ); __vmx_vmwrite( HOST_CS_SELECTOR, state->ContextFrame.SegCs & ~RPL_MASK ); // SS (Ring 0 Data) VmxpConvertGdtEntry( state->SpecialRegisters.Gdtr.Base, state->ContextFrame.SegSs, &vmxGdtEntry ); __vmx_vmwrite( GUEST_SS_SELECTOR, vmxGdtEntry.Selector ); __vmx_vmwrite( GUEST_SS_LIMIT, vmxGdtEntry.Limit ); __vmx_vmwrite( GUEST_SS_AR_BYTES, vmxGdtEntry.AccessRights ); __vmx_vmwrite( GUEST_SS_BASE, vmxGdtEntry.Base ); __vmx_vmwrite( HOST_SS_SELECTOR, state->ContextFrame.SegSs & ~RPL_MASK ); // DS (Ring 3 Data) VmxpConvertGdtEntry( state->SpecialRegisters.Gdtr.Base, state->ContextFrame.SegDs, &vmxGdtEntry ); __vmx_vmwrite( GUEST_DS_SELECTOR, vmxGdtEntry.Selector ); __vmx_vmwrite( GUEST_DS_LIMIT, vmxGdtEntry.Limit ); __vmx_vmwrite( GUEST_DS_AR_BYTES, vmxGdtEntry.AccessRights ); __vmx_vmwrite( GUEST_DS_BASE, vmxGdtEntry.Base ); __vmx_vmwrite( HOST_DS_SELECTOR, state->ContextFrame.SegDs & ~RPL_MASK ); // ES (Ring 3 Data) VmxpConvertGdtEntry( state->SpecialRegisters.Gdtr.Base, state->ContextFrame.SegEs, &vmxGdtEntry ); __vmx_vmwrite( GUEST_ES_SELECTOR, vmxGdtEntry.Selector ); __vmx_vmwrite( GUEST_ES_LIMIT, vmxGdtEntry.Limit ); __vmx_vmwrite( GUEST_ES_AR_BYTES, vmxGdtEntry.AccessRights ); __vmx_vmwrite( GUEST_ES_BASE, vmxGdtEntry.Base ); __vmx_vmwrite( HOST_ES_SELECTOR, state->ContextFrame.SegEs & ~RPL_MASK ); // FS (Ring 3 Compatibility-Mode TEB) VmxpConvertGdtEntry( state->SpecialRegisters.Gdtr.Base, state->ContextFrame.SegFs, &vmxGdtEntry ); __vmx_vmwrite( GUEST_FS_SELECTOR, vmxGdtEntry.Selector ); __vmx_vmwrite( GUEST_FS_LIMIT, vmxGdtEntry.Limit ); __vmx_vmwrite( GUEST_FS_AR_BYTES, vmxGdtEntry.AccessRights ); __vmx_vmwrite( GUEST_FS_BASE, vmxGdtEntry.Base ); __vmx_vmwrite( HOST_FS_BASE, vmxGdtEntry.Base ); __vmx_vmwrite( HOST_FS_SELECTOR, state->ContextFrame.SegFs & ~RPL_MASK ); // GS (Ring 3 Data if in Compatibility-Mode, MSR-based in Long Mode) VmxpConvertGdtEntry( state->SpecialRegisters.Gdtr.Base, state->ContextFrame.SegGs, &vmxGdtEntry ); __vmx_vmwrite( GUEST_GS_SELECTOR, vmxGdtEntry.Selector ); __vmx_vmwrite( GUEST_GS_LIMIT, vmxGdtEntry.Limit ); __vmx_vmwrite( GUEST_GS_AR_BYTES, vmxGdtEntry.AccessRights ); __vmx_vmwrite( GUEST_GS_BASE, state->SpecialRegisters.MsrGsBase ); __vmx_vmwrite( HOST_GS_BASE, state->SpecialRegisters.MsrGsBase ); __vmx_vmwrite( HOST_GS_SELECTOR, state->ContextFrame.SegGs & ~RPL_MASK ); // Task Register (Ring 0 TSS) VmxpConvertGdtEntry( state->SpecialRegisters.Gdtr.Base, state->SpecialRegisters.Tr, &vmxGdtEntry ); __vmx_vmwrite( GUEST_TR_SELECTOR, vmxGdtEntry.Selector ); __vmx_vmwrite( GUEST_TR_LIMIT, vmxGdtEntry.Limit ); __vmx_vmwrite( GUEST_TR_AR_BYTES, vmxGdtEntry.AccessRights ); __vmx_vmwrite( GUEST_TR_BASE, vmxGdtEntry.Base ); __vmx_vmwrite( HOST_TR_BASE, vmxGdtEntry.Base ); __vmx_vmwrite( HOST_TR_SELECTOR, state->SpecialRegisters.Tr & ~RPL_MASK ); // LDT VmxpConvertGdtEntry( state->SpecialRegisters.Gdtr.Base, state->SpecialRegisters.Ldtr, &vmxGdtEntry ); __vmx_vmwrite( GUEST_LDTR_SELECTOR, vmxGdtEntry.Selector ); __vmx_vmwrite( GUEST_LDTR_LIMIT, vmxGdtEntry.Limit ); __vmx_vmwrite( GUEST_LDTR_AR_BYTES, vmxGdtEntry.AccessRights ); __vmx_vmwrite( GUEST_LDTR_BASE, vmxGdtEntry.Base ); // GDT __vmx_vmwrite( GUEST_GDTR_BASE, (ULONG_PTR)state->SpecialRegisters.Gdtr.Base ); __vmx_vmwrite( GUEST_GDTR_LIMIT, state->SpecialRegisters.Gdtr.Limit ); __vmx_vmwrite( HOST_GDTR_BASE, (ULONG_PTR)state->SpecialRegisters.Gdtr.Base ); // IDT __vmx_vmwrite( GUEST_IDTR_BASE, (ULONG_PTR)state->SpecialRegisters.Idtr.Base ); __vmx_vmwrite( GUEST_IDTR_LIMIT, state->SpecialRegisters.Idtr.Limit ); __vmx_vmwrite( HOST_IDTR_BASE, (ULONG_PTR)state->SpecialRegisters.Idtr.Base ); // CR0 __vmx_vmwrite( CR0_READ_SHADOW, state->SpecialRegisters.Cr0 ); __vmx_vmwrite( HOST_CR0, state->SpecialRegisters.Cr0 ); __vmx_vmwrite( GUEST_CR0, state->SpecialRegisters.Cr0 ); // CR3 -- do not use the current process' address space for the host, // because we may be executing in an arbitrary user-mode process right now // as part of the DPC interrupt we execute in. __vmx_vmwrite( HOST_CR3, VpData->SystemDirectoryTableBase ); __vmx_vmwrite( GUEST_CR3, state->SpecialRegisters.Cr3 ); // CR4 __vmx_vmwrite( HOST_CR4, state->SpecialRegisters.Cr4 ); __vmx_vmwrite( GUEST_CR4, state->SpecialRegisters.Cr4 ); __vmx_vmwrite( CR4_GUEST_HOST_MASK, 0x2000 ); __vmx_vmwrite( CR4_READ_SHADOW, state->SpecialRegisters.Cr4 & ~0x2000 ); // Debug MSR and DR7 __vmx_vmwrite( GUEST_IA32_DEBUGCTL, state->SpecialRegisters.DebugControl ); __vmx_vmwrite( GUEST_DR7, state->SpecialRegisters.KernelDr7 ); // Finally, load the guest stack, instruction pointer, and rflags, which // corresponds exactly to the location where RtlCaptureContext will return // to inside of VmxInitializeCPU. __vmx_vmwrite( GUEST_RSP, state->ContextFrame.Rsp ); __vmx_vmwrite( GUEST_RIP, state->ContextFrame.Rip ); __vmx_vmwrite( GUEST_RFLAGS, state->ContextFrame.EFlags ); // Load the hypervisor entrypoint and stack. We give ourselves a standard // size kernel stack (24KB) and bias for the context structure that the // hypervisor entrypoint will push on the stack, avoiding the need for RSP // modifying instructions in the entrypoint. Note that the CONTEXT pointer // and thus the stack itself, must be 16-byte aligned for ABI compatibility // with AMD64 -- specifically, XMM operations will fail otherwise, such as // the ones that RtlCaptureContext will perform. NT_ASSERT( (KERNEL_STACK_SIZE - sizeof( CONTEXT )) % 16 == 0 ); __vmx_vmwrite( HOST_RSP, (ULONG_PTR)VpData->VMMStack + KERNEL_STACK_SIZE - sizeof( CONTEXT ) ); __vmx_vmwrite( HOST_RIP, (ULONG_PTR)VmxVMEntry ); }
ULONGLONG NtfsGetFreeClusters(PDEVICE_EXTENSION DeviceExt) { NTSTATUS Status; PFILE_RECORD_HEADER BitmapRecord; PNTFS_ATTR_CONTEXT DataContext; ULONGLONG BitmapDataSize; PCHAR BitmapData; ULONGLONG FreeClusters = 0; ULONG Read = 0; RTL_BITMAP Bitmap; DPRINT1("NtfsGetFreeClusters(%p)\n", DeviceExt); BitmapRecord = ExAllocateFromNPagedLookasideList(&DeviceExt->FileRecLookasideList); if (BitmapRecord == NULL) { return 0; } Status = ReadFileRecord(DeviceExt, NTFS_FILE_BITMAP, BitmapRecord); if (!NT_SUCCESS(Status)) { ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, BitmapRecord); return 0; } Status = FindAttribute(DeviceExt, BitmapRecord, AttributeData, L"", 0, &DataContext, NULL); if (!NT_SUCCESS(Status)) { ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, BitmapRecord); return 0; } BitmapDataSize = AttributeDataLength(DataContext->pRecord); ASSERT((BitmapDataSize * 8) >= DeviceExt->NtfsInfo.ClusterCount); BitmapData = ExAllocatePoolWithTag(NonPagedPool, ROUND_UP(BitmapDataSize, DeviceExt->NtfsInfo.BytesPerSector), TAG_NTFS); if (BitmapData == NULL) { ReleaseAttributeContext(DataContext); ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, BitmapRecord); return 0; } /* FIXME: Totally underoptimized! */ for (; Read < BitmapDataSize; Read += DeviceExt->NtfsInfo.BytesPerSector) { ReadAttribute(DeviceExt, DataContext, Read, (PCHAR)((ULONG_PTR)BitmapData + Read), DeviceExt->NtfsInfo.BytesPerSector); } ReleaseAttributeContext(DataContext); DPRINT1("Total clusters: %I64x\n", DeviceExt->NtfsInfo.ClusterCount); DPRINT1("Total clusters in bitmap: %I64x\n", BitmapDataSize * 8); DPRINT1("Diff in size: %I64d B\n", ((BitmapDataSize * 8) - DeviceExt->NtfsInfo.ClusterCount) * DeviceExt->NtfsInfo.SectorsPerCluster * DeviceExt->NtfsInfo.BytesPerSector); RtlInitializeBitMap(&Bitmap, (PULONG)BitmapData, DeviceExt->NtfsInfo.ClusterCount); FreeClusters = RtlNumberOfClearBits(&Bitmap); ExFreePoolWithTag(BitmapData, TAG_NTFS); ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, BitmapRecord); return FreeClusters; }
/** * NtfsAllocateClusters * Allocates a run of clusters. The run allocated might be smaller than DesiredClusters. */ NTSTATUS NtfsAllocateClusters(PDEVICE_EXTENSION DeviceExt, ULONG FirstDesiredCluster, ULONG DesiredClusters, PULONG FirstAssignedCluster, PULONG AssignedClusters) { NTSTATUS Status; PFILE_RECORD_HEADER BitmapRecord; PNTFS_ATTR_CONTEXT DataContext; ULONGLONG BitmapDataSize; PUCHAR BitmapData; ULONGLONG FreeClusters = 0; RTL_BITMAP Bitmap; ULONG AssignedRun; ULONG LengthWritten; DPRINT1("NtfsAllocateClusters(%p, %lu, %lu, %p, %p)\n", DeviceExt, FirstDesiredCluster, DesiredClusters, FirstAssignedCluster, AssignedClusters); BitmapRecord = ExAllocateFromNPagedLookasideList(&DeviceExt->FileRecLookasideList); if (BitmapRecord == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } Status = ReadFileRecord(DeviceExt, NTFS_FILE_BITMAP, BitmapRecord); if (!NT_SUCCESS(Status)) { ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, BitmapRecord); return Status; } Status = FindAttribute(DeviceExt, BitmapRecord, AttributeData, L"", 0, &DataContext, NULL); if (!NT_SUCCESS(Status)) { ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, BitmapRecord); return Status; } BitmapDataSize = AttributeDataLength(DataContext->pRecord); BitmapDataSize = min(BitmapDataSize, 0xffffffff); ASSERT((BitmapDataSize * 8) >= DeviceExt->NtfsInfo.ClusterCount); BitmapData = ExAllocatePoolWithTag(NonPagedPool, ROUND_UP(BitmapDataSize, DeviceExt->NtfsInfo.BytesPerSector), TAG_NTFS); if (BitmapData == NULL) { ReleaseAttributeContext(DataContext); ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, BitmapRecord); return STATUS_INSUFFICIENT_RESOURCES; } DPRINT1("Total clusters: %I64x\n", DeviceExt->NtfsInfo.ClusterCount); DPRINT1("Total clusters in bitmap: %I64x\n", BitmapDataSize * 8); DPRINT1("Diff in size: %I64d B\n", ((BitmapDataSize * 8) - DeviceExt->NtfsInfo.ClusterCount) * DeviceExt->NtfsInfo.SectorsPerCluster * DeviceExt->NtfsInfo.BytesPerSector); ReadAttribute(DeviceExt, DataContext, 0, (PCHAR)BitmapData, (ULONG)BitmapDataSize); RtlInitializeBitMap(&Bitmap, (PULONG)BitmapData, DeviceExt->NtfsInfo.ClusterCount); FreeClusters = RtlNumberOfClearBits(&Bitmap); if (FreeClusters < DesiredClusters) { ReleaseAttributeContext(DataContext); ExFreePoolWithTag(BitmapData, TAG_NTFS); ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, BitmapRecord); return STATUS_DISK_FULL; } // TODO: Observe MFT reservation zone // Can we get one contiguous run? AssignedRun = RtlFindClearBitsAndSet(&Bitmap, DesiredClusters, FirstDesiredCluster); if (AssignedRun != 0xFFFFFFFF) { *FirstAssignedCluster = AssignedRun; *AssignedClusters = DesiredClusters; } else { // we can't get one contiguous run *AssignedClusters = RtlFindNextForwardRunClear(&Bitmap, FirstDesiredCluster, FirstAssignedCluster); if (*AssignedClusters == 0) { // we couldn't find any runs starting at DesiredFirstCluster *AssignedClusters = RtlFindLongestRunClear(&Bitmap, FirstAssignedCluster); } } Status = WriteAttribute(DeviceExt, DataContext, 0, BitmapData, (ULONG)BitmapDataSize, &LengthWritten, BitmapRecord); ReleaseAttributeContext(DataContext); ExFreePoolWithTag(BitmapData, TAG_NTFS); ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, BitmapRecord); return Status; }
BOOLEAN FFSCheckSetBlock( PFFS_IRP_CONTEXT IrpContext, PFFS_VCB Vcb, ULONG Block) { #if 0 ULONG Group, dwBlk, Length; RTL_BITMAP BlockBitmap; PVOID BitmapCache; PBCB BitmapBcb; LARGE_INTEGER Offset; BOOLEAN bModified = FALSE; //Group = (Block - FFS_FIRST_DATA_BLOCK) / BLOCKS_PER_GROUP; dwBlk = (Block - FFS_FIRST_DATA_BLOCK) % BLOCKS_PER_GROUP; Offset.QuadPart = (LONGLONG) Vcb->BlockSize; Offset.QuadPart = Offset.QuadPart * Vcb->ffs_group_desc[Group].bg_block_bitmap; if (Group == Vcb->ffs_groups - 1) { Length = TOTAL_BLOCKS % BLOCKS_PER_GROUP; /* s_blocks_count is integer multiple of s_blocks_per_group */ if (Length == 0) Length = BLOCKS_PER_GROUP; } else { Length = BLOCKS_PER_GROUP; } if (dwBlk >= Length) return FALSE; if (!CcPinRead(Vcb->StreamObj, &Offset, Vcb->BlockSize, PIN_WAIT, &BitmapBcb, &BitmapCache)) { FFSPrint((DBG_ERROR, "FFSDeleteBlock: PinReading error ...\n")); return FALSE; } RtlInitializeBitMap(&BlockBitmap, BitmapCache, Length); if (RtlCheckBit(&BlockBitmap, dwBlk) == 0) { FFSBreakPoint(); RtlSetBits(&BlockBitmap, dwBlk, 1); bModified = TRUE; } if (bModified) { CcSetDirtyPinnedData(BitmapBcb, NULL); FFSRepinBcb(IrpContext, BitmapBcb); FFSAddMcbEntry(Vcb, Offset.QuadPart, (LONGLONG)Vcb->BlockSize); } { CcUnpinData(BitmapBcb); BitmapBcb = NULL; BitmapCache = NULL; RtlZeroMemory(&BlockBitmap, sizeof(RTL_BITMAP)); } return (!bModified); #endif return FALSE; }