|
|
//
// Buggy.sys
// Copyright (c) Microsoft Corporation, 1999.
//
// Module: physmem.c
// Author: Silviu Calinoiu (SilviuC)
// Created: 4/20/1999 2:39pm
//
// This module contains stress functions for physical memory
// manipulation routines and also some pool allocaiton routines.
//
// --- History ---
//
// 08/14/99 (SilviuC): initial version (integrating code got from LandyW).
//
#include <ntddk.h>
#include "active.h"
#include "physmem.h"
#if !PHYSMEM_ACTIVE
//
// Dummy implementation if the module is inactive
//
LARGE_INTEGER BuggyOneSecond = {(ULONG)(-10 * 1000 * 1000 * 1), -1};
VOID PhysmemDisabled (VOID) { DbgPrint ("Buggy: physmem module is disabled (check \\driver\\active.h header) \n"); }
VOID StressAllocateContiguousMemory ( PVOID NotUsed ) { PhysmemDisabled (); }
VOID StressAllocateCommonBuffer ( PVOID NotUsed ) { PhysmemDisabled (); }
VOID StressAddPhysicalMemory ( PVOID NotUsed ) { PhysmemDisabled (); }
VOID StressDeletePhysicalMemory ( PVOID NotUsed ) { PhysmemDisabled (); }
VOID StressLockScenario ( PVOID NotUsed ) { PhysmemDisabled (); }
VOID StressPhysicalMemorySimple ( PVOID NotUsed ) { PhysmemDisabled (); }
#else
//
// Real implementation if the module is active
//
//////////////////////////
#define MAX_BUFFER_SIZE (2 * 1024 * 1024)
// #define BUFFER_SIZE (32 * 1024)
// ULONG uBufferSize = (64 * 1024);
ULONG uBufferSize = (4 * 1024);
int zlw = 3;
LARGE_INTEGER BuggyTenSeconds = {(ULONG)(-10 * 1000 * 1000 * 10), -1}; LARGE_INTEGER BuggyOneSecond = {(ULONG)(-10 * 1000 * 1000 * 1), -1};
VOID StressAllocateContiguousMemory ( PVOID NotUsed ) /*++
Routine Description:
Arguments:
Return Value:
Environment:
--*/ { PHYSICAL_ADDRESS LogicalAddress; PVOID VirtualAddress; ULONG j; ULONG i; ULONG k; PULONG_PTR p; PVOID MyVirtualAddress[16]; PHYSICAL_ADDRESS MyLogicalAddress[16]; ULONG MySize[16]; PHYSICAL_ADDRESS LowestAcceptableAddress; PHYSICAL_ADDRESS HighestAcceptableAddress; PHYSICAL_ADDRESS BoundaryAddressMultiple; MEMORY_CACHING_TYPE CacheType;
DbgPrint ("Buggy: MmAllocateContiguousMemorySpecifyCache stress ioctl \n");
//
// allocate the buffer
//
uBufferSize = (64 * 1024);
LowestAcceptableAddress.QuadPart = 0; HighestAcceptableAddress.QuadPart = 0x100000; BoundaryAddressMultiple.QuadPart = 0; LogicalAddress.QuadPart = 0;
for (k = 0; k <= 12; k += 1) {
if (k < 4) { LowestAcceptableAddress.QuadPart = 0; HighestAcceptableAddress.QuadPart = 0x1000000; BoundaryAddressMultiple.QuadPart = 0x10000; } else if (k < 4) { LowestAcceptableAddress.QuadPart = 0x1000000; HighestAcceptableAddress.QuadPart = 0x2000000; BoundaryAddressMultiple.QuadPart = 0; } else { LowestAcceptableAddress.QuadPart = 0x1800000; HighestAcceptableAddress.QuadPart = 0x4000000; BoundaryAddressMultiple.QuadPart = 0x30000; }
for (CacheType = MmCached; CacheType <= MmWriteCombined; CacheType += 1) {
for (i = 0; i < 16; i += 1) {
DbgPrint( "buffer size = %08X\n", uBufferSize ); if (uBufferSize == 0) { MyVirtualAddress[i] = NULL; continue; }
VirtualAddress = MmAllocateContiguousMemorySpecifyCache ( uBufferSize, LowestAcceptableAddress, HighestAcceptableAddress, BoundaryAddressMultiple, CacheType);
if (VirtualAddress == NULL) { DbgPrint( "buggy: MmAllocateContiguousMemSpecifyCache( %08X ) failed\n", (ULONG) uBufferSize );
// Status = STATUS_DRIVER_INTERNAL_ERROR;
MyVirtualAddress[i] = NULL; } else {
DbgPrint( "buggy: MmAllocateContiguousMemSpecifyCache( %p %08X ) - success\n", VirtualAddress, (ULONG) uBufferSize);
MyVirtualAddress[i] = VirtualAddress; MyLogicalAddress[i] = LogicalAddress; MySize[i] = uBufferSize;
p = VirtualAddress;
for (j = 0; j < uBufferSize / sizeof(ULONG_PTR); j += 1) { *p = ((ULONG_PTR)VirtualAddress + j); p += 1; } } uBufferSize -= PAGE_SIZE; }
for (i = 0; i < 16; i += 1) { if (MyVirtualAddress[i]) { DbgPrint( "buggy: MmFreeContiguousMemorySpecifyCache( %x %08X )\n", MyVirtualAddress[i], (ULONG) MySize[i]);
MmFreeContiguousMemorySpecifyCache (MyVirtualAddress[i], MySize[i], CacheType); } } } } DbgPrint ("Buggy: MmAllocateContiguousMemSpecifyCache test finished\n"); }
VOID StressAllocateCommonBuffer ( PVOID NotUsed ) /*++
Routine Description:
Arguments:
Return Value:
Environment:
--*/ { DEVICE_DESCRIPTION DeviceDescription; // DMA adapter object description
PADAPTER_OBJECT pAdapterObject; // DMA adapter object
ULONG NumberOfMapRegisters; PHYSICAL_ADDRESS LogicalAddress; PVOID VirtualAddress; ULONG j; ULONG i; PULONG_PTR p; PVOID MyVirtualAddress[16]; PHYSICAL_ADDRESS MyLogicalAddress[16]; ULONG MySize[16];
DbgPrint ("Buggy: HalAllocateCommonBuffer stress ioctl \n");
//
// Zero the device description structure.
//
RtlZeroMemory(&DeviceDescription, sizeof(DEVICE_DESCRIPTION));
//
// Get the adapter object for this card.
//
DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION; DeviceDescription.DmaChannel = 0; DeviceDescription.InterfaceType = Internal; DeviceDescription.DmaWidth = Width8Bits; DeviceDescription.DmaSpeed = Compatible; DeviceDescription.MaximumLength = MAX_BUFFER_SIZE; DeviceDescription.BusNumber = 0;
pAdapterObject = HalGetAdapter (&DeviceDescription, &NumberOfMapRegisters);
if ( pAdapterObject == NULL ) { DbgPrint( "buggy: HalGetAdapter - failed\n" ); // return STATUS_DRIVER_INTERNAL_ERROR;
return; }
DbgPrint( "buggy: HalGetAdapter - success\n" );
//
// allocate the buffer
//
uBufferSize = (64 * 1024);
for (i = 0; i < 16; i += 1) {
DbgPrint( "buffer size = %08X\n", uBufferSize );
VirtualAddress = HalAllocateCommonBuffer (pAdapterObject, uBufferSize, &LogicalAddress, FALSE );
if (VirtualAddress == NULL) { DbgPrint( "buggy: HalAllocateCommonBuffer( %08X ) failed\n", (ULONG) uBufferSize );
// Status = STATUS_DRIVER_INTERNAL_ERROR;
MyVirtualAddress[i] = NULL; } else {
DbgPrint( "buggy: HalAllocateCommonBuffer( %p %08X ) - success\n", VirtualAddress, (ULONG) uBufferSize);
MyVirtualAddress[i] = VirtualAddress; MyLogicalAddress[i] = LogicalAddress; MySize[i] = uBufferSize;
p = VirtualAddress;
for (j = 0; j < uBufferSize / sizeof(ULONG_PTR); j += 1) { *p = ((ULONG_PTR)VirtualAddress + j); p += 1; } } uBufferSize -= PAGE_SIZE; }
for (i = 0; i < 16; i += 1) { if (MyVirtualAddress[i]) { DbgPrint( "buggy: HalFreeCommonBuffer( %x %08X )\n", MyVirtualAddress[i], (ULONG) MySize[i]); HalFreeCommonBuffer( pAdapterObject, MySize[i], MyLogicalAddress[i], MyVirtualAddress[i], FALSE ); } } DbgPrint ("Buggy: HalAllocateCommonBuffer test finished\n"); // LWFIX: Halfreeadapter needed ?
}
LOGICAL StopToEdit = TRUE; PFN_NUMBER TestBasePage; PFN_NUMBER TestPageCount;
VOID EditPhysicalMemoryParameters ( ) /*++
Routine Description:
This function is called from StressAdd/DeletePhysicalMemory to allow user to set the parameters for stress (what region should be used for add/remove ?).
Arguments:
None.
Return Value:
None.
Environment:
Kernel mode.
--*/ { DbgPrint ("`dd nt!mmphysicalmemoryblock l1' should give the address of memory descriptor\n"); DbgPrint ("`dd ADDRESS' (first dword displayed by previous command) gives description\n"); DbgPrint ("The structure of the memory descriptor is presented below: \n"); DbgPrint ("(4) NoOfRuns \n"); DbgPrint ("(4) NoOfPages \n"); DbgPrint ("(4) Run[0]: BasePage \n"); DbgPrint ("(4) Run[0]: PageCount \n"); DbgPrint ("(4) Run[1]: ... \n"); DbgPrint ("(4) ... \n"); DbgPrint (" \n"); DbgPrint ("When you decide on values you should edit the following: \n"); DbgPrint ("buggy!StopToEdit <- 0 \n"); DbgPrint ("buggy!TestBasePage <- decided value \n"); DbgPrint ("buggy!TestPageCount <- decided value \n"); DbgPrint (" \n");
DbgBreakPoint (); }
VOID StressAddPhysicalMemory ( PVOID NotUsed ) /*++
Routine Description:
This function regresses the MmAddPhysicalMemory kernel API. It does not really stress it but rather iterate through some possible combinations.
Arguments:
None.
Return Value:
None.
Environment:
Kernel mode.
--*/ { NTSTATUS Status; ULONG i; PHYSICAL_ADDRESS StartAddress; LARGE_INTEGER NumberOfBytes;
DbgPrint ("Buggy: add physical memory stress ioctl \n");
//
// (SilviuC): We need an automatic way to figure out memory runs.
//
if (StopToEdit) { EditPhysicalMemoryParameters (); }
StartAddress.QuadPart = (LONGLONG)TestBasePage * PAGE_SIZE; NumberOfBytes.QuadPart = (LONGLONG)TestPageCount * PAGE_SIZE;
i = 0; do {
i += 1; DbgPrint ("buggy: MmAddPhysicalMemory0 %x %x %x %x\n", StartAddress.HighPart, StartAddress.LowPart, NumberOfBytes.HighPart, NumberOfBytes.LowPart);
Status = MmAddPhysicalMemory ( &StartAddress, &NumberOfBytes);
DbgPrint ("buggy: MmAddPhysicalMemory %x %x %x %x %x\n", Status, StartAddress.HighPart, StartAddress.LowPart, NumberOfBytes.HighPart, NumberOfBytes.LowPart);
if ((i % 8) == 0) { KeDelayExecutionThread (KernelMode, FALSE, &BuggyTenSeconds); }
StartAddress.QuadPart -= NumberOfBytes.QuadPart; } while (StartAddress.QuadPart > 0); DbgPrint ("Buggy: MmAddPhysicalMemory test finished\n"); }
VOID StressDeletePhysicalMemory ( PVOID NotUsed ) /*++
Routine Description:
This function regresses the MmRemovePhysicalMemory kernel API. It does not really stress the function but rather iterate throughout the physical memory and attempt to remove chunks of it.
Arguments:
None.
Return Value:
None.
Environment:
Kernel mode.
--*/
{ NTSTATUS Status; ULONG i; PHYSICAL_ADDRESS StartAddress; LARGE_INTEGER NumberOfBytes;
//
// SilviuC: we need an automatic way to figure out memory runs.
//
if (StopToEdit) { EditPhysicalMemoryParameters (); }
StartAddress.QuadPart = (LONGLONG)TestBasePage * PAGE_SIZE; NumberOfBytes.QuadPart = (LONGLONG)TestPageCount * PAGE_SIZE;
for (i = 0; i < (0xf0000000 / NumberOfBytes.LowPart); i += 1) {
DbgPrint ("buggy: MmRemovePhysicalMemory0 %x %x %x %x\n", StartAddress.HighPart, StartAddress.LowPart, NumberOfBytes.HighPart, NumberOfBytes.LowPart);
Status = MmRemovePhysicalMemory ( &StartAddress, &NumberOfBytes);
DbgPrint ("buggy: MmRemovePhysicalMemory %x %x %x %x %x\n", Status, StartAddress.HighPart, StartAddress.LowPart, NumberOfBytes.HighPart, NumberOfBytes.LowPart);
StartAddress.QuadPart += NumberOfBytes.QuadPart;
if ((i % 8) == 0) { KeDelayExecutionThread (KernelMode, FALSE, &BuggyTenSeconds); } } DbgPrint ("Buggy: MmRemovePhysicalMemory test finished\n"); }
//
// Global:
//
// BigData
//
// Description:
//
// Dummy pageable array needed to test lock/unlock scenarios.
//
NTSTATUS DriverEntry ( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath );
#ifdef ALLOC_PRAGMA
#pragma data_seg("BDAT")
ULONG BigData [0x10000]; #pragma data_seg()
#endif // #ifdef ALLOC_PRAGMA
VOID StressLockScenario ( PVOID NotUsed ) /*++
Routine Description:
Arguments:
Return Value:
Environment:
--*/ { ULONG I; PVOID Handle;
#if 0
for (I = 0; I < 16; I++) {
Handle = MmLockPagableDataSection (BigData); DbgPrint ("Buggy: lock handle %p \n", Handle); MmUnlockPagableImageSection (Handle); } #else
for (I = 0; I < 16; I++) {
MmPageEntireDriver (DriverEntry); MmResetDriverPaging (BigData); } #endif
}
VOID StressPhysicalMemorySimple ( PVOID NotUsed ) /*++
Routine Description:
This routine exercises add/remove physical memory functions using a simple remove scenario. Note. This function contributed by LandyW.
Arguments:
None.
Return Value:
None.
Environment:
Kernel mode.
--*/ { #if 0
ULONG i; PPHYSICAL_MEMORY_RANGE Ranges; PPHYSICAL_MEMORY_RANGE p;
PHYSICAL_ADDRESS StartAddress; LARGE_INTEGER NumberOfBytes;
PHYSICAL_ADDRESS InputAddress; LARGE_INTEGER InputBytes;
Ranges = MmGetPhysicalMemoryRanges ();
if (Ranges == NULL) { DbgPrint ("Buggy: MmRemovePhysicalMemory cannot get ranges\n"); Status = STATUS_INSUFFICIENT_RESOURCES; return; }
p = Ranges; while (p->BaseAddress.QuadPart != 0 && p->NumberOfBytes.QuadPart != 0) {
StartAddress.QuadPart = p->BaseAddress.QuadPart; NumberOfBytes.QuadPart = p->NumberOfBytes.QuadPart;
InputAddress.QuadPart = StartAddress.QuadPart; InputBytes.QuadPart = NumberOfBytes.QuadPart;
if (InputBytes.QuadPart > (128 * 1024 * 1024)) { InputBytes.QuadPart = (128 * 1024 * 1024); }
while (InputAddress.QuadPart + InputBytes.QuadPart <= StartAddress.QuadPart + NumberOfBytes.QuadPart) {
DbgPrint ("buggy: MmRemovePhysicalMemory0 %x %x %x %x\n", InputAddress.HighPart, InputAddress.LowPart, InputBytes.HighPart, InputBytes.LowPart);
Status = MmRemovePhysicalMemory (&InputAddress, &InputBytes);
DbgPrint ("buggy: MmRemovePhysicalMemory %x %x %x %x %x\n\n", Status, InputAddress.HighPart, InputAddress.LowPart, InputBytes.HighPart, InputBytes.LowPart);
KeDelayExecutionThread (KernelMode, FALSE, &BuggyOneSecond);
if (NT_SUCCESS(Status)) {
DbgPrint ("buggy: MmAddPhysicalMemory0 %x %x %x %x\n", InputAddress.HighPart, InputAddress.LowPart, InputBytes.HighPart, InputBytes.LowPart);
Status = MmAddPhysicalMemory ( &InputAddress, &InputBytes);
if (NT_SUCCESS(Status)) { DbgPrint ("\n\n***************\nbuggy: MmAddPhysicalMemory WORKED %x %x %x %x %x\n****************\n", Status, InputAddress.HighPart, InputAddress.LowPart, InputBytes.HighPart, InputBytes.LowPart); } else { DbgPrint ("buggy: MmAddPhysicalMemory FAILED %x %x %x %x %x\n\n", Status, InputAddress.HighPart, InputAddress.LowPart, InputBytes.HighPart, InputBytes.LowPart); DbgBreakPoint (); } }
if (InputAddress.QuadPart + InputBytes.QuadPart == StartAddress.QuadPart + NumberOfBytes.QuadPart) {
break; }
InputAddress.QuadPart += InputBytes.QuadPart;
if (InputAddress.QuadPart + InputBytes.QuadPart > StartAddress.QuadPart + NumberOfBytes.QuadPart) {
InputBytes.QuadPart = StartAddress.QuadPart + NumberOfBytes.QuadPart - InputAddress.QuadPart; } }
p += 1; }
ExFreePool (Ranges); DbgPrint ("Buggy: Add/remove physical memory simple stress finished\n"); #endif // #if 0
}
#endif // #if !PHYSMEM_ACTIVE
|