Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1570 lines
37 KiB

  1. //
  2. // Template Driver
  3. // Copyright (c) Microsoft Corporation, 1999.
  4. //
  5. // Module: tdriver.c
  6. // Author: Silviu Calinoiu (SilviuC)
  7. // Created: 4/20/1999 2:39pm
  8. //
  9. // This module contains a template driver.
  10. //
  11. // --- History ---
  12. //
  13. // 4/20/1999 (SilviuC): initial version.
  14. //
  15. // 10/25/1999 (DMihai): Aded tests for:
  16. // - paged pool size
  17. // - non paged pool size
  18. // - number of free system PTEs
  19. //
  20. #include <ntddk.h>
  21. #include "active.h"
  22. #include "mmtests.h"
  23. #include "physmem.h"
  24. #include "tdriver.h"
  25. #if !MMTESTS_ACTIVE
  26. //
  27. // Dummy implementation if the module is inactive
  28. //
  29. VOID MmTestDisabled (VOID)
  30. {
  31. DbgPrint ("Buggy: mmtests module is disabled (check \\driver\\active.h header) \n");
  32. }
  33. VOID MmTestProbeLockForEverStress (
  34. IN PVOID NotUsed
  35. )
  36. {
  37. MmTestDisabled ();
  38. }
  39. VOID MmTestNameToAddressStress (
  40. IN PVOID IrpAddress
  41. )
  42. {
  43. MmTestDisabled ();
  44. }
  45. VOID MmTestEccBadStress (
  46. IN PVOID IrpAddress
  47. )
  48. {
  49. MmTestDisabled ();
  50. }
  51. VOID
  52. TdSysPagedPoolMaxTest(
  53. IN PVOID IrpAddress
  54. )
  55. {
  56. MmTestDisabled ();
  57. }
  58. VOID
  59. TdSysPagedPoolTotalTest(
  60. IN PVOID IrpAddress
  61. )
  62. {
  63. MmTestDisabled ();
  64. }
  65. VOID
  66. TdNonPagedPoolMaxTest(
  67. IN PVOID IrpAddress
  68. )
  69. {
  70. MmTestDisabled ();
  71. }
  72. VOID
  73. TdNonPagedPoolTotalTest(
  74. IN PVOID IrpAddress
  75. )
  76. {
  77. MmTestDisabled ();
  78. }
  79. VOID
  80. TdFreeSystemPtesTest(
  81. IN PVOID IrpAddress
  82. )
  83. {
  84. MmTestDisabled ();
  85. }
  86. VOID
  87. StressPoolFlag (
  88. PVOID NotUsed
  89. )
  90. {
  91. MmTestDisabled ();
  92. }
  93. VOID
  94. StressPoolTagTableExtension (
  95. PVOID NotUsed
  96. )
  97. {
  98. MmTestDisabled ();
  99. }
  100. #else
  101. //
  102. // Real implementation if the module is active
  103. //
  104. ULONG BuggyPP = (96 * 1024 * 1024);
  105. PVOID BuggyOld;
  106. SIZE_T UserVaSize = (50 * 1024 * 1024);
  107. ULONG BuggyHold = 1;
  108. ULONG OverrideStart;
  109. ULONG OverrideSize;
  110. ULONG OverrideCount;
  111. #define VERBOSITY_PRINT 0x0001
  112. #define VERBOSITY_BREAK 0x0002
  113. ULONG Verbosity = 0x0003;
  114. NTSYSCALLAPI
  115. NTSTATUS
  116. NTAPI
  117. ZwAllocateVirtualMemory(
  118. IN HANDLE ProcessHandle,
  119. IN OUT PVOID *BaseAddress,
  120. IN ULONG_PTR ZeroBits,
  121. IN OUT PSIZE_T RegionSize,
  122. IN ULONG AllocationType,
  123. IN ULONG Protect
  124. );
  125. VOID MmTestProbeLockForEverStress (
  126. IN PVOID IrpAddress
  127. )
  128. {
  129. PIRP Irp = (PIRP) IrpAddress;
  130. PIO_STACK_LOCATION IrpStack;
  131. ULONG InputBufferLength;
  132. ULONG OutputBufferLength;
  133. ULONG Ioctl;
  134. NTSTATUS Status;
  135. ULONG BufferSize;
  136. ULONG ReturnedSize;
  137. IrpStack = IoGetCurrentIrpStackLocation (Irp);
  138. InputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
  139. OutputBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
  140. Ioctl = IrpStack->Parameters.DeviceIoControl.IoControlCode;
  141. {
  142. SIZE_T RegionSize;
  143. PVOID UserVa;
  144. PMDL Mdl;
  145. UserVa = NULL;
  146. RegionSize = UserVaSize;
  147. Status = ZwAllocateVirtualMemory (NtCurrentProcess(),
  148. (PVOID *)&UserVa,
  149. 0,
  150. &RegionSize,
  151. MEM_COMMIT,
  152. PAGE_READWRITE);
  153. if (NT_SUCCESS(Status)) {
  154. Mdl = IoAllocateMdl (
  155. UserVa,
  156. (ULONG)RegionSize,
  157. FALSE, // not secondary buffer
  158. FALSE, // do not charge quota
  159. NULL); // no irp
  160. if (Mdl != NULL) {
  161. try {
  162. MmProbeAndLockPages (Mdl,
  163. KernelMode,
  164. IoReadAccess);
  165. DbgPrint ("Buggy: locked pages in MDL %p\n", Mdl);
  166. DbgBreakPoint ();
  167. //
  168. // Don't exit now without unlocking !
  169. //
  170. while (BuggyHold != 0) {
  171. KeDelayExecutionThread (KernelMode, FALSE, &BuggyOneSecond);
  172. }
  173. MmUnlockPages (Mdl);
  174. IoFreeMdl (Mdl);
  175. }
  176. except (EXCEPTION_EXECUTE_HANDLER) {
  177. DbgPrint ("Buggy: exception raised while locking %p\n", Mdl);
  178. DbgBreakPoint ();
  179. }
  180. }
  181. }
  182. }
  183. DbgPrint ("Buggy: finish with probe-and-lock forever ioctl \n");
  184. Status = STATUS_SUCCESS;
  185. }
  186. VOID MmTestNameToAddressStress (
  187. IN PVOID IrpAddress
  188. )
  189. {
  190. PIRP Irp = (PIRP) IrpAddress;
  191. PIO_STACK_LOCATION IrpStack;
  192. ULONG InputBufferLength;
  193. ULONG OutputBufferLength;
  194. ULONG Ioctl;
  195. NTSTATUS Status;
  196. ULONG BufferSize;
  197. ULONG ReturnedSize;
  198. IrpStack = IoGetCurrentIrpStackLocation (Irp);
  199. InputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
  200. OutputBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
  201. Ioctl = IrpStack->Parameters.DeviceIoControl.IoControlCode;
  202. {
  203. #define CONSTANT_UNICODE_STRING(s) { sizeof( s ) - sizeof( WCHAR ), sizeof( s ), s }
  204. const UNICODE_STRING RoutineA = CONSTANT_UNICODE_STRING( L"KfRaiseIrql" );
  205. const UNICODE_STRING RoutineList[] = {
  206. CONSTANT_UNICODE_STRING( L"KeBugCheckEx" ),
  207. CONSTANT_UNICODE_STRING( L"KiBugCheckData" ),
  208. CONSTANT_UNICODE_STRING( L"KeWaitForSingleObject" ),
  209. CONSTANT_UNICODE_STRING( L"KeWaitForMutexObject" ),
  210. CONSTANT_UNICODE_STRING( L"Junk1" ),
  211. CONSTANT_UNICODE_STRING( L"CcCanIWrite" ),
  212. CONSTANT_UNICODE_STRING( L"Junk" ),
  213. };
  214. PVOID Addr;
  215. ULONG i;
  216. Addr = MmGetSystemRoutineAddress ((PUNICODE_STRING)&RoutineA);
  217. DbgPrint ("Addr is %p\n", Addr);
  218. for (i = 0; i < sizeof (RoutineList) / sizeof (UNICODE_STRING); i += 1) {
  219. Addr = MmGetSystemRoutineAddress ((PUNICODE_STRING)&RoutineList[i]);
  220. DbgPrint ("Addr0 is %p\n", Addr);
  221. }
  222. }
  223. }
  224. VOID MmTestEccBadStress (
  225. IN PVOID IrpAddress
  226. )
  227. {
  228. PIRP Irp = (PIRP) IrpAddress;
  229. PIO_STACK_LOCATION IrpStack;
  230. ULONG InputBufferLength;
  231. ULONG OutputBufferLength;
  232. ULONG Ioctl;
  233. NTSTATUS Status;
  234. ULONG BufferSize;
  235. ULONG ReturnedSize;
  236. IrpStack = IoGetCurrentIrpStackLocation (Irp);
  237. InputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
  238. OutputBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
  239. Ioctl = IrpStack->Parameters.DeviceIoControl.IoControlCode;
  240. DbgPrint ("Buggy: mark physical memory ECC bad ioctl \n");
  241. {
  242. ULONG i;
  243. PPHYSICAL_MEMORY_RANGE Ranges;
  244. PPHYSICAL_MEMORY_RANGE p;
  245. PHYSICAL_ADDRESS StartAddress;
  246. LARGE_INTEGER NumberOfBytes;
  247. PHYSICAL_ADDRESS InputAddress;
  248. LARGE_INTEGER InputBytes;
  249. Ranges = MmGetPhysicalMemoryRanges ();
  250. if (Ranges == NULL) {
  251. DbgPrint ("Buggy: MmRemovePhysicalMemory cannot get ranges\n");
  252. Status = STATUS_INSUFFICIENT_RESOURCES;
  253. return;
  254. }
  255. i = 0;
  256. DbgPrint("StartAddress @ %p, OverrideSize @ %p, OverrideCount @ %p\n", &OverrideStart, &OverrideSize, &OverrideCount);
  257. DbgBreakPoint();
  258. p = Ranges;
  259. while (p->BaseAddress.QuadPart != 0 && p->NumberOfBytes.QuadPart != 0) {
  260. StartAddress.QuadPart = p->BaseAddress.QuadPart;
  261. NumberOfBytes.QuadPart = p->NumberOfBytes.QuadPart;
  262. if (OverrideStart != 0) {
  263. StartAddress.LowPart = OverrideStart;
  264. }
  265. InputAddress.QuadPart = StartAddress.QuadPart;
  266. InputBytes.QuadPart = NumberOfBytes.QuadPart;
  267. #ifdef BIG_REMOVES
  268. if (InputBytes.QuadPart > (64 * 1024)) {
  269. InputBytes.QuadPart = (64 * 1024);
  270. }
  271. #else
  272. if (InputBytes.QuadPart > (4 * 1024)) {
  273. InputBytes.QuadPart = (4 * 1024);
  274. }
  275. #endif
  276. if (OverrideSize != 0) {
  277. InputBytes.LowPart = OverrideSize;
  278. }
  279. while (InputAddress.QuadPart + InputBytes.QuadPart <=
  280. StartAddress.QuadPart + NumberOfBytes.QuadPart) {
  281. if (OverrideCount != 0 && i > OverrideCount) {
  282. break;
  283. }
  284. i += 1;
  285. DbgPrint ("buggy: MmMarkPhysicalMemoryAsBad %x %x %x %x\n",
  286. InputAddress.HighPart,
  287. InputAddress.LowPart,
  288. InputBytes.HighPart,
  289. InputBytes.LowPart);
  290. Status = MmMarkPhysicalMemoryAsBad (&InputAddress,
  291. &InputBytes);
  292. DbgPrint ("buggy: MmMarkPhysicalMemoryAsBad %x %x %x %x %x\n\n",
  293. Status,
  294. InputAddress.HighPart,
  295. InputAddress.LowPart,
  296. InputBytes.HighPart,
  297. InputBytes.LowPart);
  298. KeDelayExecutionThread (KernelMode, FALSE, &BuggyOneSecond);
  299. if (NT_SUCCESS(Status)) {
  300. DbgPrint ("buggy: MmMarkPhysicalMemoryAsGood %x %x %x %x\n",
  301. InputAddress.HighPart,
  302. InputAddress.LowPart,
  303. InputBytes.HighPart,
  304. InputBytes.LowPart);
  305. Status = MmMarkPhysicalMemoryAsGood (&InputAddress,
  306. &InputBytes);
  307. if (NT_SUCCESS(Status)) {
  308. DbgPrint ("\n\n***************\nbuggy: MmMarkPhysicalMemoryAsGood WORKED %x %x %x %x %x\n****************\n",
  309. Status,
  310. InputAddress.HighPart,
  311. InputAddress.LowPart,
  312. InputBytes.HighPart,
  313. InputBytes.LowPart);
  314. }
  315. else {
  316. DbgPrint ("buggy: MmMarkPhysicalMemoryAsGood FAILED %x %x %x %x %x\n\n",
  317. Status,
  318. InputAddress.HighPart,
  319. InputAddress.LowPart,
  320. InputBytes.HighPart,
  321. InputBytes.LowPart);
  322. DbgBreakPoint ();
  323. }
  324. }
  325. if (InputAddress.QuadPart + InputBytes.QuadPart ==
  326. StartAddress.QuadPart + NumberOfBytes.QuadPart) {
  327. break;
  328. }
  329. InputAddress.QuadPart += InputBytes.QuadPart;
  330. if (InputAddress.QuadPart + InputBytes.QuadPart >
  331. StartAddress.QuadPart + NumberOfBytes.QuadPart) {
  332. InputBytes.QuadPart = StartAddress.QuadPart + NumberOfBytes.QuadPart - InputAddress.QuadPart;
  333. }
  334. }
  335. if (OverrideCount != 0 && i > OverrideCount) {
  336. break;
  337. }
  338. p += 1;
  339. }
  340. ExFreePool (Ranges);
  341. DbgPrint ("Buggy: MmMarkPhysicalMemory Ecc BAD test finished\n");
  342. }
  343. }
  344. ////////////////////////////////////////////////////////////////////////////
  345. typedef struct
  346. {
  347. LIST_ENTRY List;
  348. PVOID ChunkPointers[ ( 63 * 1024 ) / sizeof( PVOID ) ];
  349. } ALLOCATION_TABLE, *PALLOCATION_TABLE;
  350. LIST_ENTRY PagedPoolAllocationListHead;
  351. LIST_ENTRY NonPagedPoolAllocationListHead;
  352. const SIZE_T PoolChunkSize = 64 * 1024 - 32;
  353. //
  354. //
  355. //
  356. VOID
  357. TdpWriteSignature(
  358. PVOID Allocation,
  359. SIZE_T CurrentSize
  360. )
  361. {
  362. PSIZE_T CrtSignature;
  363. SIZE_T CrtSignatureValue;
  364. CrtSignature = (PSIZE_T)Allocation;
  365. CrtSignatureValue = ( (SIZE_T)Allocation ) ^ CurrentSize;
  366. /*
  367. DbgPrint( "Buggy: Writing signature %p from address %p, size %p\n",
  368. CrtSignatureValue,
  369. CrtSignature,
  370. CurrentSize );
  371. */
  372. while( sizeof( SIZE_T ) <= CurrentSize )
  373. {
  374. *CrtSignature = CrtSignatureValue;
  375. CrtSignatureValue +=1;
  376. CrtSignature = (PSIZE_T)( (PCHAR)CrtSignature + sizeof( SIZE_T ) );
  377. CurrentSize -= sizeof( SIZE_T );
  378. }
  379. }
  380. //
  381. //
  382. //
  383. VOID
  384. TdpVerifySignature(
  385. PVOID Allocation,
  386. SIZE_T CurrentSize )
  387. {
  388. PSIZE_T CrtSignature;
  389. SIZE_T CrtSignatureValue;
  390. CrtSignature = (PSIZE_T)Allocation;
  391. CrtSignatureValue = ( (SIZE_T)Allocation ) ^ CurrentSize;
  392. /*
  393. DbgPrint( "Buggy: Verifying signature %p from address %p, size %p\n",
  394. CrtSignatureValue,
  395. CrtSignature,
  396. CurrentSize );
  397. */
  398. while( sizeof( SIZE_T ) <= CurrentSize )
  399. {
  400. if( *CrtSignature != CrtSignatureValue )
  401. {
  402. DbgPrint ("Buggy: Signature at %p is incorrect, expected %p, base allocation %p\n",
  403. CrtSignature,
  404. CrtSignatureValue,
  405. Allocation );
  406. }
  407. CrtSignatureValue +=1;
  408. CrtSignature = (PSIZE_T)( (PCHAR)CrtSignature + sizeof( SIZE_T ) );
  409. CurrentSize -= sizeof( SIZE_T );
  410. }
  411. }
  412. //
  413. //
  414. //
  415. VOID
  416. TdpCleanupPoolAllocationTable(
  417. PLIST_ENTRY ListHead,
  418. SIZE_T Allocations
  419. )
  420. {
  421. PLIST_ENTRY NextEntry;
  422. PALLOCATION_TABLE AllocationTable;
  423. SIZE_T ChunksPerAllocationEntry;
  424. SIZE_T CrtChunksIndex;
  425. ChunksPerAllocationEntry = ARRAY_LENGTH( AllocationTable->ChunkPointers );
  426. NextEntry = ListHead->Flink;
  427. while( NextEntry != ListHead )
  428. {
  429. RemoveEntryList( NextEntry );
  430. AllocationTable = CONTAINING_RECORD( NextEntry, ALLOCATION_TABLE, List );
  431. DbgPrint( "Buggy: Current allocation table = %p\n",
  432. AllocationTable );
  433. for( CrtChunksIndex = 0; CrtChunksIndex < ChunksPerAllocationEntry; CrtChunksIndex++ )
  434. {
  435. if( 0 == Allocations )
  436. {
  437. //
  438. // Freed them all
  439. //
  440. break;
  441. }
  442. else
  443. {
  444. Allocations -= 1;
  445. if( 0 == Allocations % 0x100 )
  446. {
  447. //
  448. // Let the user know that we are still working on something
  449. //
  450. DbgPrint( "Buggy: cleaning up allocation index %p\n",
  451. Allocations );
  452. }
  453. /*
  454. DbgPrint( "Buggy: Verify and free chunk index %p (from the end) at address %p\n",
  455. Allocations,
  456. AllocationTable->ChunkPointers[ CrtChunksIndex ] );
  457. */
  458. TdpVerifySignature(
  459. AllocationTable->ChunkPointers[ CrtChunksIndex ],
  460. PoolChunkSize );
  461. ExFreePoolWithTag(
  462. AllocationTable->ChunkPointers[ CrtChunksIndex ],
  463. TD_POOL_TAG );
  464. }
  465. }
  466. //
  467. // Free the table as well
  468. //
  469. ExFreePoolWithTag(
  470. AllocationTable,
  471. TD_POOL_TAG );
  472. //
  473. // Go to the next allocations table
  474. //
  475. NextEntry = ListHead->Flink;
  476. }
  477. //
  478. // At this point, Allocations should be zero and the
  479. // list should be empty
  480. //
  481. if( 0 != Allocations )
  482. {
  483. DbgPrint ("Buggy: Emptied the allocation table list but still have %p allocations - this is a bug\n",
  484. Allocations );
  485. DbgBreakPoint();
  486. }
  487. if( ! IsListEmpty( ListHead ) )
  488. {
  489. DbgPrint ("Buggy: No allocations left but the list at %p is not empty yet - this is a bug\n",
  490. ListHead );
  491. DbgBreakPoint();
  492. }
  493. }
  494. //
  495. // Determine the maximum size of a block of paged pool currently available
  496. //
  497. VOID
  498. TdSysPagedPoolMaxTest(
  499. IN PVOID IrpAddress
  500. )
  501. {
  502. SIZE_T CurrentSize;
  503. SIZE_T SizeIncrement;
  504. ULONG Increment;
  505. PVOID Allocation;
  506. #ifdef _WIN64
  507. CurrentSize = 0xFFFFFFFF00000000;
  508. #else
  509. CurrentSize = 0xFFFFFFFF;
  510. #endif //#ifdef _WIN64
  511. do
  512. {
  513. DbgPrint ("Buggy: Trying to allocate %p bytes paged pool\n",
  514. CurrentSize );
  515. Allocation = ExAllocatePoolWithTag(
  516. PagedPool,
  517. CurrentSize,
  518. TD_POOL_TAG );
  519. if( NULL != Allocation )
  520. {
  521. DbgPrint ("Buggy: allocated %p bytes paged pool\n",
  522. CurrentSize );
  523. TdpWriteSignature(
  524. Allocation,
  525. CurrentSize );
  526. ExFreePoolWithTag(
  527. Allocation,
  528. TD_POOL_TAG );
  529. }
  530. else
  531. {
  532. CurrentSize /= 2;
  533. }
  534. }
  535. while( NULL == Allocation && PAGE_SIZE <= CurrentSize );
  536. if( NULL != Allocation )
  537. {
  538. //
  539. // Try to find an even bigger size in 10% increments
  540. //
  541. SizeIncrement = CurrentSize / 10;
  542. if( PAGE_SIZE <= SizeIncrement )
  543. {
  544. for( Increment = 0; Increment < 10; Increment += 1 )
  545. {
  546. CurrentSize += SizeIncrement;
  547. DbgPrint ("Buggy: Trying to allocate %p bytes paged pool\n",
  548. CurrentSize );
  549. Allocation = ExAllocatePoolWithTag(
  550. PagedPool,
  551. CurrentSize,
  552. TD_POOL_TAG );
  553. if( NULL != Allocation )
  554. {
  555. DbgPrint ("Buggy: Better result of the test: allocated %p bytes paged pool\n",
  556. CurrentSize );
  557. TdpWriteSignature(
  558. Allocation,
  559. CurrentSize );
  560. ExFreePoolWithTag(
  561. Allocation,
  562. TD_POOL_TAG );
  563. }
  564. else
  565. {
  566. DbgPrint ("Buggy: could not allocate %p bytes paged pool - done\n",
  567. CurrentSize );
  568. break;
  569. }
  570. }
  571. }
  572. }
  573. }
  574. //
  575. // Determine the total size of the paged pool currently available (64 Kb - 32 bytes blocks)
  576. //
  577. VOID
  578. TdSysPagedPoolTotalTest(
  579. IN PVOID IrpAddress
  580. )
  581. {
  582. SIZE_T CurrentChunkIndex;
  583. SIZE_T ChunksPerAllocationEntry;
  584. SIZE_T TotalBytes;
  585. PALLOCATION_TABLE AllocationListEntry;
  586. PVOID Allocation;
  587. //
  588. // No allocations yet
  589. //
  590. InitializeListHead(
  591. &PagedPoolAllocationListHead );
  592. //
  593. // We want to allocate 64 k chunks but leave space for the pool block header
  594. //
  595. ChunksPerAllocationEntry = ARRAY_LENGTH( AllocationListEntry->ChunkPointers );
  596. CurrentChunkIndex = 0;
  597. do
  598. {
  599. if( 0 == CurrentChunkIndex % ChunksPerAllocationEntry )
  600. {
  601. //
  602. // Need a new allocation entry structure
  603. //
  604. AllocationListEntry = (PALLOCATION_TABLE) ExAllocatePoolWithTag(
  605. NonPagedPool,
  606. sizeof( ALLOCATION_TABLE ),
  607. TD_POOL_TAG );
  608. if( NULL == AllocationListEntry )
  609. {
  610. DbgPrint ("Buggy: could not allocate new ALLOCATION_TABLE - aborting test here\n" );
  611. break;
  612. }
  613. RtlZeroMemory(
  614. AllocationListEntry,
  615. sizeof( ALLOCATION_TABLE ) );
  616. DbgPrint( "Buggy: New allocation table = %p\n",
  617. AllocationListEntry );
  618. }
  619. //
  620. // Try to allocate a new chunk
  621. //
  622. Allocation = ExAllocatePoolWithTag(
  623. PagedPool,
  624. PoolChunkSize,
  625. TD_POOL_TAG );
  626. if( NULL == Allocation )
  627. {
  628. DbgPrint ("Buggy: could not allocate paged pool chunk index %p - done\n",
  629. CurrentChunkIndex );
  630. if( 0 == CurrentChunkIndex % ChunksPerAllocationEntry )
  631. {
  632. //
  633. // We are using a new list entry - free it now because
  634. // we don't want to have empty tables in the list so we didn't insert it yet so we didn't insert it yet
  635. //
  636. ExFreePoolWithTag(
  637. AllocationListEntry,
  638. TD_POOL_TAG );
  639. }
  640. }
  641. else
  642. {
  643. if( 0 == CurrentChunkIndex % 0x100 )
  644. {
  645. //
  646. // Let the user know that we are still working on something
  647. //
  648. DbgPrint( "Buggy: Allocated pool chunk index = %p\n",
  649. CurrentChunkIndex );
  650. }
  651. if( 0 == CurrentChunkIndex % ChunksPerAllocationEntry )
  652. {
  653. //
  654. // We are using a new list entry - add it to our list only now because
  655. // we don't want to have empty tables in the list so we didn't insert it yet
  656. //
  657. InsertTailList(
  658. &PagedPoolAllocationListHead,
  659. &AllocationListEntry->List );
  660. }
  661. AllocationListEntry->ChunkPointers[ CurrentChunkIndex % ChunksPerAllocationEntry ] = Allocation;
  662. TdpWriteSignature(
  663. Allocation,
  664. PoolChunkSize );
  665. /*
  666. DbgPrint( "Buggy: Written signature to chunk index %p at address %p\n",
  667. CurrentChunkIndex,
  668. Allocation );
  669. */
  670. CurrentChunkIndex += 1;
  671. }
  672. }
  673. while( NULL != Allocation );
  674. TotalBytes = CurrentChunkIndex * 64 * 1024;
  675. DbgPrint ("Buggy: Result of the test: approx. %p total bytes of paged pool allocated\n",
  676. TotalBytes );
  677. //
  678. // Clean-up what we have allocated
  679. //
  680. TdpCleanupPoolAllocationTable(
  681. &PagedPoolAllocationListHead,
  682. CurrentChunkIndex );
  683. }
  684. VOID
  685. TdNonPagedPoolMaxTest(
  686. IN PVOID IrpAddress
  687. )
  688. {
  689. SIZE_T CurrentSize;
  690. SIZE_T SizeIncrement;
  691. ULONG Increment;
  692. PVOID Allocation;
  693. #ifdef _WIN64
  694. CurrentSize = 0xFFFFFFFF00000000;
  695. #else
  696. CurrentSize = 0xFFFFFFFF;
  697. #endif //#ifdef _WIN64
  698. do
  699. {
  700. DbgPrint ("Buggy: Trying to allocate %p bytes non-paged pool\n",
  701. CurrentSize );
  702. Allocation = ExAllocatePoolWithTag(
  703. NonPagedPool,
  704. CurrentSize,
  705. TD_POOL_TAG );
  706. if( NULL != Allocation )
  707. {
  708. DbgPrint ("Buggy: allocated %p bytes non-paged pool\n",
  709. CurrentSize );
  710. TdpWriteSignature(
  711. Allocation,
  712. CurrentSize );
  713. ExFreePoolWithTag(
  714. Allocation,
  715. TD_POOL_TAG );
  716. }
  717. else
  718. {
  719. CurrentSize /= 2;
  720. }
  721. }
  722. while( NULL == Allocation && PAGE_SIZE <= CurrentSize );
  723. if( NULL != Allocation )
  724. {
  725. //
  726. // Try to find an even bigger size in 10% increments
  727. //
  728. SizeIncrement = CurrentSize / 10;
  729. if( PAGE_SIZE <= SizeIncrement )
  730. {
  731. for( Increment = 0; Increment < 10; Increment += 1 )
  732. {
  733. CurrentSize += SizeIncrement;
  734. DbgPrint ("Buggy: Trying to allocate %p bytes non-paged pool\n",
  735. CurrentSize );
  736. Allocation = ExAllocatePoolWithTag(
  737. NonPagedPool,
  738. CurrentSize,
  739. TD_POOL_TAG );
  740. if( NULL != Allocation )
  741. {
  742. DbgPrint ("Buggy: Better result of the test: allocated %p bytes non-paged pool\n",
  743. CurrentSize );
  744. TdpWriteSignature(
  745. Allocation,
  746. CurrentSize );
  747. ExFreePoolWithTag(
  748. Allocation,
  749. TD_POOL_TAG );
  750. }
  751. else
  752. {
  753. DbgPrint ("Buggy: could not allocate %p bytes non-paged pool - done\n",
  754. CurrentSize );
  755. break;
  756. }
  757. }
  758. }
  759. }
  760. }
  761. //
  762. // Determine the total size of the non-paged pool currently available (64 Kb - 32 bytes blocks)
  763. //
  764. VOID
  765. TdNonPagedPoolTotalTest(
  766. IN PVOID IrpAddress
  767. )
  768. {
  769. SIZE_T CurrentChunkIndex;
  770. SIZE_T ChunksPerAllocationEntry;
  771. SIZE_T TotalBytes;
  772. PALLOCATION_TABLE AllocationListEntry;
  773. PVOID Allocation;
  774. //
  775. // No allocations yet
  776. //
  777. InitializeListHead(
  778. &NonPagedPoolAllocationListHead );
  779. //
  780. // We want to allocate 64 k chunks but leave space for the pool block header
  781. //
  782. ChunksPerAllocationEntry = ARRAY_LENGTH( AllocationListEntry->ChunkPointers );
  783. CurrentChunkIndex = 0;
  784. do
  785. {
  786. if( 0 == CurrentChunkIndex % ChunksPerAllocationEntry )
  787. {
  788. //
  789. // Need a new allocation entry structure
  790. //
  791. AllocationListEntry = (PALLOCATION_TABLE) ExAllocatePoolWithTag(
  792. PagedPool,
  793. sizeof( ALLOCATION_TABLE ),
  794. TD_POOL_TAG );
  795. if( NULL == AllocationListEntry )
  796. {
  797. DbgPrint ("Buggy: could not allocate new ALLOCATION_TABLE - aborting test here\n" );
  798. break;
  799. }
  800. }
  801. //
  802. // Try to allocate a new chunk
  803. //
  804. Allocation = ExAllocatePoolWithTag(
  805. NonPagedPool,
  806. PoolChunkSize,
  807. TD_POOL_TAG );
  808. if( NULL == Allocation )
  809. {
  810. DbgPrint ("Buggy: could not allocate non-paged pool chunk index %p - done\n",
  811. CurrentChunkIndex );
  812. if( 0 == CurrentChunkIndex % ChunksPerAllocationEntry )
  813. {
  814. //
  815. // We are using a new list entry - free it now because
  816. // we don't want to have empty tables in the list so we didn't insert it yet so we didn't insert it yet
  817. //
  818. ExFreePoolWithTag(
  819. AllocationListEntry,
  820. TD_POOL_TAG );
  821. }
  822. }
  823. else
  824. {
  825. if( 0 == CurrentChunkIndex % 0x100 )
  826. {
  827. //
  828. // Let the user know that we are still working on something
  829. //
  830. DbgPrint( "Buggy: Allocated pool chunk index = %p\n",
  831. CurrentChunkIndex );
  832. }
  833. if( 0 == CurrentChunkIndex % ChunksPerAllocationEntry )
  834. {
  835. //
  836. // We are using a new list entry - add it to our list only now because
  837. // we don't want to have empty tables in the list so we didn't insert it yet
  838. //
  839. InsertTailList(
  840. &NonPagedPoolAllocationListHead,
  841. &AllocationListEntry->List );
  842. }
  843. AllocationListEntry->ChunkPointers[ CurrentChunkIndex % ChunksPerAllocationEntry ] = Allocation;
  844. TdpWriteSignature(
  845. Allocation,
  846. PoolChunkSize );
  847. CurrentChunkIndex += 1;
  848. }
  849. }
  850. while( NULL != Allocation );
  851. TotalBytes = CurrentChunkIndex * 64 * 1024;
  852. DbgPrint ("Buggy: Result of the test: approx. %p total bytes of non-paged pool allocated\n",
  853. TotalBytes );
  854. //
  855. // Clean-up what we have allocated
  856. //
  857. TdpCleanupPoolAllocationTable(
  858. &NonPagedPoolAllocationListHead,
  859. CurrentChunkIndex );
  860. }
  861. /////////////////////////////////////////////////////////////////////////////////////
  862. typedef struct
  863. {
  864. LIST_ENTRY List;
  865. PMDL Mappings[ ( 63 * 1024 ) / sizeof( PMDL ) ];
  866. } MAPPING_TABLE_ENTRY, *PMAPPING_TABLE_ENTRY;
  867. LIST_ENTRY IoMappingsListHead;
  868. ULONG BytesPerIoMapping = 1024 * 1024;
  869. //
  870. //
  871. //
  872. VOID
  873. TdpCleanupMappingsAllocationTable(
  874. PLIST_ENTRY ListHead,
  875. SIZE_T Mappings
  876. )
  877. {
  878. PLIST_ENTRY NextEntry;
  879. PMAPPING_TABLE_ENTRY MappingTableEntry;
  880. SIZE_T MappingsPerMappingTableEntry;
  881. SIZE_T CrtMappingIndex;
  882. MappingsPerMappingTableEntry = ARRAY_LENGTH( MappingTableEntry->Mappings );
  883. NextEntry = ListHead->Flink;
  884. while( NextEntry != ListHead )
  885. {
  886. RemoveEntryList( NextEntry );
  887. MappingTableEntry = CONTAINING_RECORD( NextEntry, MAPPING_TABLE_ENTRY, List );
  888. for( CrtMappingIndex = 0; CrtMappingIndex < MappingsPerMappingTableEntry; CrtMappingIndex++ )
  889. {
  890. if( 0 == Mappings )
  891. {
  892. //
  893. // Freed them all
  894. //
  895. break;
  896. }
  897. else
  898. {
  899. Mappings -= 1;
  900. if( 0 == Mappings % 0x100 )
  901. {
  902. //
  903. // Let the user know that we are still working on something
  904. //
  905. DbgPrint( "Buggy: cleaning up mapping index %p\n",
  906. Mappings );
  907. }
  908. //
  909. // Unmap
  910. //
  911. MmUnmapIoSpace(
  912. MappingTableEntry->Mappings[ CrtMappingIndex ],
  913. BytesPerIoMapping );
  914. }
  915. }
  916. //
  917. // Free the table as well
  918. //
  919. ExFreePoolWithTag(
  920. MappingTableEntry,
  921. TD_POOL_TAG );
  922. //
  923. // Go to the next allocations table
  924. //
  925. NextEntry = ListHead->Flink;
  926. }
  927. //
  928. // At this point, Mappings should be zero and the
  929. // list should be empty
  930. //
  931. if( 0 != Mappings )
  932. {
  933. DbgPrint ("Buggy: Emptied the mappings table list but still have %p allocations - this is a bug\n",
  934. Mappings );
  935. DbgBreakPoint();
  936. }
  937. if( ! IsListEmpty( ListHead ) )
  938. {
  939. DbgPrint ("Buggy: No mappings left but the list at %p is not empty yet - this is a bug\n",
  940. ListHead );
  941. DbgBreakPoint();
  942. }
  943. }
  944. //
  945. // Determine the total amount of memory that can be mapped using system PTEs (1 Mb chunks)
  946. //
  947. VOID
  948. TdFreeSystemPtesTest(
  949. IN PVOID IrpAddress
  950. )
  951. {
  952. ULONG MemType;
  953. PHYSICAL_ADDRESS PortAddress;
  954. PHYSICAL_ADDRESS MyPhysicalAddress;
  955. SIZE_T CurrentMappingIndex;
  956. SIZE_T MappingsPerMappingTableEntry;
  957. SIZE_T TotalBytes;
  958. PVOID NewMapping;
  959. PMAPPING_TABLE_ENTRY MappingTableEntry;
  960. PMDL NewMdl;
  961. NTSTATUS Status;
  962. //
  963. // Use some joystick port address
  964. //
  965. MemType = 1; // IO space
  966. PortAddress.LowPart = 0x200;
  967. PortAddress.HighPart = 0;
  968. HalTranslateBusAddress(
  969. Isa,
  970. 0,
  971. PortAddress,
  972. &MemType,
  973. &MyPhysicalAddress);
  974. //
  975. // No Mappings allocated yet
  976. //
  977. InitializeListHead(
  978. &IoMappingsListHead );
  979. //
  980. // Map a ~64 Kb chunk over and over again to consume system PTEs
  981. //
  982. MappingsPerMappingTableEntry = ARRAY_LENGTH( MappingTableEntry->Mappings );
  983. CurrentMappingIndex = 0;
  984. do
  985. {
  986. if( 0 == CurrentMappingIndex % MappingsPerMappingTableEntry )
  987. {
  988. //
  989. // Need a new allocation entry structure
  990. //
  991. MappingTableEntry = (PMAPPING_TABLE_ENTRY) ExAllocatePoolWithTag(
  992. PagedPool,
  993. sizeof( MAPPING_TABLE_ENTRY ),
  994. TD_POOL_TAG );
  995. if( NULL == MappingTableEntry )
  996. {
  997. DbgPrint ("Buggy: could not allocate new MAPPING_TABLE_ENTRY - aborting test here\n" );
  998. break;
  999. }
  1000. }
  1001. NewMapping = MmMapIoSpace(
  1002. MyPhysicalAddress,
  1003. BytesPerIoMapping,
  1004. MmNonCached );
  1005. if( NULL == NewMapping )
  1006. {
  1007. DbgPrint ("Buggy: could not create mapping index %p\n",
  1008. CurrentMappingIndex );
  1009. if( 0 == CurrentMappingIndex % MappingsPerMappingTableEntry )
  1010. {
  1011. //
  1012. // We are using a new list entry - free it now because
  1013. // we don't want to have empty tables in the list so we didn't insert it yet so we didn't insert it yet
  1014. //
  1015. ExFreePoolWithTag(
  1016. MappingTableEntry,
  1017. TD_POOL_TAG );
  1018. }
  1019. }
  1020. else
  1021. {
  1022. //DbgPrint ("Buggy: created Mapping index %p at address %p\n",
  1023. // CurrentMappingIndex,
  1024. // NewMapping );
  1025. if( 0 == CurrentMappingIndex % 0x100 )
  1026. {
  1027. //
  1028. // Let the user know that we are still working on something
  1029. //
  1030. DbgPrint( "Buggy: mapped chunk index = %p\n",
  1031. CurrentMappingIndex );
  1032. }
  1033. if( 0 == CurrentMappingIndex % MappingsPerMappingTableEntry )
  1034. {
  1035. //
  1036. // We are using a new list entry - add it to our list only now because
  1037. // we don't want to have empty tables in the list so we didn't insert it yet
  1038. //
  1039. InsertTailList(
  1040. &IoMappingsListHead,
  1041. &MappingTableEntry->List );
  1042. }
  1043. MappingTableEntry->Mappings[ CurrentMappingIndex % MappingsPerMappingTableEntry ] = NewMapping;
  1044. CurrentMappingIndex += 1;
  1045. }
  1046. }
  1047. while( NULL != NewMapping );
  1048. TotalBytes = CurrentMappingIndex * BytesPerIoMapping;
  1049. DbgPrint( "Buggy: Result of the test: %p total bytes mapped\n",
  1050. TotalBytes );
  1051. //
  1052. // Clean-up what we have allocated and locked
  1053. //
  1054. TdpCleanupMappingsAllocationTable(
  1055. &IoMappingsListHead,
  1056. CurrentMappingIndex );
  1057. }
  1058. //
  1059. // Function:
  1060. //
  1061. // GetTag
  1062. //
  1063. // Description:
  1064. //
  1065. // This function transforms an integer into a four letter
  1066. // string. This is useful for the pool tag dynamic table
  1067. // in order to populate it with many different tags.
  1068. //
  1069. ULONG
  1070. GetTag (
  1071. ULONG Index
  1072. )
  1073. {
  1074. UCHAR Value[4];
  1075. Value[0] = (UCHAR)(((Index & 0x000F) >> 0 )) + 'A';
  1076. Value[1] = (UCHAR)(((Index & 0x00F0) >> 4 )) + 'A';
  1077. Value[2] = (UCHAR)(((Index & 0x0F00) >> 8 )) + 'A';
  1078. Value[3] = (UCHAR)(((Index & 0xF000) >> 12)) + 'A';
  1079. return *((PULONG)Value);
  1080. }
  1081. VOID
  1082. StressPoolFlag (
  1083. PVOID NotUsed
  1084. )
  1085. /*++
  1086. Routine Description:
  1087. This function iterates through all the pool types, pool flags
  1088. and pool sizes (1 .. 8 * PAGE_SIZE).
  1089. Arguments:
  1090. None.
  1091. Return Value:
  1092. None.
  1093. Environment:
  1094. Kernel mode.
  1095. --*/
  1096. {
  1097. POOL_TYPE PoolType;
  1098. SIZE_T NumberOfBytes;
  1099. EX_POOL_PRIORITY Priority;
  1100. PVOID Va;
  1101. ULONG i;
  1102. for (PoolType = NonPagedPool; PoolType < 0xff; PoolType += 1) {
  1103. for (Priority = LowPoolPriority; Priority < LowPoolPriority + 2; Priority += 1) {
  1104. for (i = 1; i < 8 * PAGE_SIZE; i += 1) {
  1105. NumberOfBytes = i;
  1106. if (PoolType & 0x40) {
  1107. break;
  1108. }
  1109. if ((NumberOfBytes > PAGE_SIZE) && (PoolType & 0x2)) {
  1110. break;
  1111. }
  1112. try {
  1113. Va = ExAllocatePoolWithTagPriority (
  1114. PoolType,
  1115. NumberOfBytes,
  1116. 'ZXCV',
  1117. Priority);
  1118. }
  1119. except (EXCEPTION_EXECUTE_HANDLER) {
  1120. if (Verbosity & VERBOSITY_PRINT) {
  1121. DbgPrint( "buggy: ExAllocatePool exceptioned %x %x %x\n",
  1122. PoolType, NumberOfBytes, Priority);
  1123. }
  1124. if (Verbosity & VERBOSITY_BREAK) {
  1125. DbgBreakPoint ();
  1126. }
  1127. Va = NULL;
  1128. }
  1129. if (Va) {
  1130. ExFreePool (Va);
  1131. }
  1132. else {
  1133. if (Verbosity & VERBOSITY_PRINT) {
  1134. DbgPrint( "buggy: ExAllocatePool failed %x %x %x\n",
  1135. PoolType, NumberOfBytes, Priority);
  1136. }
  1137. if (Verbosity & VERBOSITY_BREAK) {
  1138. DbgBreakPoint ();
  1139. }
  1140. }
  1141. }
  1142. }
  1143. }
  1144. DbgPrint ("Buggy: ExAllocatePoolFlag test finished\n");
  1145. }
  1146. VOID
  1147. StressPoolTagTableExtension (
  1148. PVOID NotUsed
  1149. )
  1150. /*++
  1151. Routine Description:
  1152. This function stresses the pool tag table dynamic extension.
  1153. Arguments:
  1154. None.
  1155. Return Value:
  1156. None.
  1157. Environment:
  1158. Kernel mode.
  1159. --*/
  1160. {
  1161. PVOID * Blocks;
  1162. ULONG Index;
  1163. Blocks = ExAllocatePoolWithTag (
  1164. NonPagedPool,
  1165. 16384 * sizeof(PVOID),
  1166. 'tguB');
  1167. if (Blocks == NULL) {
  1168. DbgPrint ("Buggy: cannot allocate pool buffer\n");
  1169. }
  1170. else {
  1171. //
  1172. // Loop with 8 byte size.
  1173. //
  1174. for (Index = 0; Index < 10000; Index++) {
  1175. if (Index && Index % 100 == 0) {
  1176. DbgPrint ("Index(a): %u \n", Index);
  1177. }
  1178. Blocks[Index] = ExAllocatePoolWithTag (
  1179. NonPagedPool,
  1180. 8,
  1181. GetTag(Index));
  1182. }
  1183. for (Index = 0; Index < 10000; Index++) {
  1184. if (Index && Index % 100 == 0) {
  1185. DbgPrint ("Index(f): %u \n", Index);
  1186. }
  1187. if (Blocks[Index]) {
  1188. ExFreePool (Blocks[Index]);
  1189. }
  1190. }
  1191. //
  1192. // Loop with PAGE_SIZE byte size.
  1193. //
  1194. for (Index = 0; Index < 4000; Index++) {
  1195. if (Index && Index % 100 == 0) {
  1196. DbgPrint ("Index(A): %u \n", Index);
  1197. }
  1198. Blocks[Index] = ExAllocatePoolWithTag (
  1199. NonPagedPool,
  1200. PAGE_SIZE,
  1201. GetTag(Index + 16384));
  1202. }
  1203. for (Index = 0; Index < 4000; Index++) {
  1204. if (Index && Index % 100 == 0) {
  1205. DbgPrint ("Index(F): %u \n", Index);
  1206. }
  1207. if (Blocks[Index]) {
  1208. ExFreePool (Blocks[Index]);
  1209. }
  1210. }
  1211. //
  1212. // Free block info.
  1213. //
  1214. ExFreePool (Blocks);
  1215. }
  1216. }
  1217. #endif // #if !MMTESTS_ACTIVE
  1218. //
  1219. // End of file
  1220. //