Leaked source code of windows server 2003
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.

1035 lines
26 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. miglobal.c
  5. Abstract:
  6. This module contains the private global storage for the memory
  7. management subsystem.
  8. Author:
  9. Lou Perazzoli (loup) 6-Apr-1989
  10. Landy Wang (landyw) 02-June-1997
  11. Revision History:
  12. --*/
  13. #include "mi.h"
  14. //
  15. // Highest user address;
  16. //
  17. PVOID MmHighestUserAddress;
  18. //
  19. // Start of system address range.
  20. //
  21. PVOID MmSystemRangeStart;
  22. //
  23. // User probe address;
  24. //
  25. ULONG_PTR MmUserProbeAddress;
  26. #if !defined(_WIN64)
  27. //
  28. // Virtual bias applied during the loading of the kernel image.
  29. //
  30. ULONG_PTR MmVirtualBias;
  31. #endif
  32. //
  33. // Number of secondary colors, based on level 2 d cache size.
  34. //
  35. ULONG MmSecondaryColors;
  36. //
  37. // The starting color index seed, incremented at each process creation.
  38. //
  39. ULONG MmProcessColorSeed = 0x12345678;
  40. //
  41. // Total number of physical pages available on the system.
  42. //
  43. PFN_COUNT MmNumberOfPhysicalPages;
  44. //
  45. // Lowest physical page number in the system.
  46. //
  47. PFN_NUMBER MmLowestPhysicalPage = (PFN_NUMBER)-1;
  48. //
  49. // Highest physical page number in the system.
  50. //
  51. PFN_NUMBER MmHighestPhysicalPage;
  52. //
  53. // Highest possible physical page number in the system.
  54. //
  55. PFN_NUMBER MmHighestPossiblePhysicalPage;
  56. //
  57. // Total number of available pages in the system. This
  58. // is the sum of the pages on the zeroed, free and standby lists.
  59. //
  60. PFN_NUMBER MmAvailablePages;
  61. PFN_NUMBER MmThrottleTop;
  62. PFN_NUMBER MmThrottleBottom;
  63. //
  64. // Highest VAD index used to create bitmaps.
  65. //
  66. ULONG MiLastVadBit = 1;
  67. //
  68. // System wide memory management statistics block.
  69. //
  70. MMINFO_COUNTERS MmInfoCounters;
  71. //
  72. // Total number of physical pages which would be usable if every process
  73. // was at its minimum working set size. This value is initialized
  74. // at system initialization to MmAvailablePages - MM_FLUID_PHYSICAL_PAGES.
  75. // Every time a thread is created, the kernel stack is subtracted from
  76. // this and every time a process is created, the minimum working set
  77. // is subtracted from this. If the value would become negative, the
  78. // operation (create process/kernel stack/ adjust working set) fails.
  79. // The PFN LOCK must be owned to manipulate this value.
  80. //
  81. SPFN_NUMBER MmResidentAvailablePages;
  82. //
  83. // The total number of pages which would be removed from working sets
  84. // if every working set was at its minimum.
  85. //
  86. PFN_NUMBER MmPagesAboveWsMinimum;
  87. //
  88. // If memory is becoming short and MmPagesAboveWsMinimum is
  89. // greater than MmPagesAboveWsThreshold, trim working sets.
  90. //
  91. PFN_NUMBER MmPagesAboveWsThreshold = 37;
  92. //
  93. // The total number of pages needed for the loader to successfully hibernate.
  94. // Make it big so we can handle a loader that may use a large bootfont.bin
  95. //
  96. PFN_NUMBER MmHiberPages = 768;
  97. //
  98. // The following values are frequently used together. They tend
  99. // not to be modified once the system has initialized so should
  100. // not be grouped with data whose values change frequently to
  101. // eliminate false sharing.
  102. //
  103. ULONG MmSecondaryColorMask;
  104. UCHAR MmSecondaryColorNodeShift;
  105. //
  106. // Registry-settable threshold for using large pages. x86 only.
  107. //
  108. ULONG MmLargePageMinimum;
  109. PMMPFN MmPfnDatabase;
  110. MMPFNLIST MmZeroedPageListHead = {
  111. 0, // Total
  112. ZeroedPageList, // ListName
  113. MM_EMPTY_LIST, //Flink
  114. MM_EMPTY_LIST // Blink
  115. };
  116. MMPFNLIST MmFreePageListHead = {
  117. 0, // Total
  118. FreePageList, // ListName
  119. MM_EMPTY_LIST, //Flink
  120. MM_EMPTY_LIST // Blink
  121. };
  122. MMPFNLIST MmStandbyPageListHead = {
  123. 0, // Total
  124. StandbyPageList, // ListName
  125. MM_EMPTY_LIST, //Flink
  126. MM_EMPTY_LIST // Blink
  127. };
  128. MMPFNLIST MmModifiedPageListHead = {
  129. 0, // Total
  130. ModifiedPageList, // ListName
  131. MM_EMPTY_LIST, //Flink
  132. MM_EMPTY_LIST // Blink
  133. };
  134. MMPFNLIST MmModifiedNoWritePageListHead = {
  135. 0, // Total
  136. ModifiedNoWritePageList, // ListName
  137. MM_EMPTY_LIST, //Flink
  138. MM_EMPTY_LIST // Blink
  139. };
  140. MMPFNLIST MmBadPageListHead = {
  141. 0, // Total
  142. BadPageList, // ListName
  143. MM_EMPTY_LIST, //Flink
  144. MM_EMPTY_LIST // Blink
  145. };
  146. //
  147. // Note the ROM page listhead is deliberately not in the set
  148. // of MmPageLocationList ranges.
  149. //
  150. MMPFNLIST MmRomPageListHead = {
  151. 0, // Total
  152. StandbyPageList, // ListName
  153. MM_EMPTY_LIST, //Flink
  154. MM_EMPTY_LIST // Blink
  155. };
  156. PMMPFNLIST MmPageLocationList[NUMBER_OF_PAGE_LISTS] = {
  157. &MmZeroedPageListHead,
  158. &MmFreePageListHead,
  159. &MmStandbyPageListHead,
  160. &MmModifiedPageListHead,
  161. &MmModifiedNoWritePageListHead,
  162. &MmBadPageListHead,
  163. NULL,
  164. NULL };
  165. PMMPTE MiHighestUserPte;
  166. PMMPTE MiHighestUserPde;
  167. #if (_MI_PAGING_LEVELS >= 4)
  168. PMMPTE MiHighestUserPpe;
  169. PMMPTE MiHighestUserPxe;
  170. #endif
  171. PMMPTE MiSessionBasePte;
  172. PMMPTE MiSessionLastPte;
  173. //
  174. // Hyper space items.
  175. //
  176. PMMPTE MmFirstReservedMappingPte;
  177. PMMPTE MmLastReservedMappingPte;
  178. //
  179. // Event for available pages, set means pages are available.
  180. //
  181. KEVENT MmAvailablePagesEvent;
  182. //
  183. // Event for the zeroing page thread.
  184. //
  185. KEVENT MmZeroingPageEvent;
  186. //
  187. // Boolean to indicate if the zeroing page thread is currently
  188. // active. This is set to true when the zeroing page event is
  189. // set and set to false when the zeroing page thread is done
  190. // zeroing all the pages on the free list.
  191. //
  192. BOOLEAN MmZeroingPageThreadActive;
  193. //
  194. // Minimum number of free pages before zeroing page thread starts.
  195. //
  196. PFN_NUMBER MmMinimumFreePagesToZero = 8;
  197. //
  198. // System space sizes - MmNonPagedSystemStart to MM_NON_PAGED_SYSTEM_END
  199. // defines the ranges of PDEs which must be copied into a new process's
  200. // address space.
  201. //
  202. PVOID MmNonPagedSystemStart;
  203. LOGICAL MmProtectFreedNonPagedPool;
  204. //
  205. // This is set in the registry to the maximum number of gigabytes of RAM
  206. // that can be added to this machine (ie: #of DIMM slots times maximum
  207. // supported DIMM size). This lets configurations that won't use the absolute
  208. // maximum indicate that a smaller (virtually) PFN database size can be used
  209. // thus leaving more virtual address space for things like system PTEs, etc.
  210. //
  211. PFN_NUMBER MmDynamicPfn;
  212. #ifdef MM_BUMP_COUNTER_MAX
  213. SIZE_T MmResTrack[MM_BUMP_COUNTER_MAX];
  214. #endif
  215. #ifdef MM_COMMIT_COUNTER_MAX
  216. SIZE_T MmTrackCommit[MM_COMMIT_COUNTER_MAX];
  217. #endif
  218. //
  219. // Set via the registry to identify which drivers are leaking locked pages.
  220. //
  221. LOGICAL MmTrackLockedPages;
  222. //
  223. // Set via the registry to identify drivers which unload without releasing
  224. // resources or still have active timers, etc.
  225. //
  226. LOGICAL MmSnapUnloads = TRUE;
  227. #if DBG
  228. PETHREAD MiExpansionLockOwner;
  229. #endif
  230. //
  231. // Pool sizes.
  232. //
  233. SIZE_T MmSizeOfNonPagedPoolInBytes;
  234. SIZE_T MmMaximumNonPagedPoolInBytes;
  235. PFN_NUMBER MmMaximumNonPagedPoolInPages;
  236. ULONG MmMaximumNonPagedPoolPercent;
  237. SIZE_T MmMinimumNonPagedPoolSize = 256 * 1024; // 256k
  238. ULONG MmMinAdditionNonPagedPoolPerMb = 32 * 1024; // 32k
  239. SIZE_T MmDefaultMaximumNonPagedPool = 1024 * 1024; // 1mb
  240. ULONG MmMaxAdditionNonPagedPoolPerMb = 400 * 1024; //400k
  241. SIZE_T MmSizeOfPagedPoolInBytes = 32 * 1024 * 1024; // 32 MB.
  242. PFN_NUMBER MmSizeOfPagedPoolInPages = (32 * 1024 * 1024) / PAGE_SIZE; // 32 MB.
  243. PFN_NUMBER MmNumberOfSystemPtes;
  244. ULONG MiRequestedSystemPtes;
  245. PMMPTE MmFirstPteForPagedPool;
  246. PMMPTE MmLastPteForPagedPool;
  247. //
  248. // Pool bit maps and other related structures.
  249. //
  250. PVOID MmPageAlignedPoolBase[2];
  251. ULONG MmExpandedPoolBitPosition;
  252. PFN_NUMBER MmNumberOfFreeNonPagedPool;
  253. //
  254. // MmFirstFreeSystemPte contains the offset from the
  255. // Nonpaged system base to the first free system PTE.
  256. // Note that an offset of -1 indicates an empty list.
  257. //
  258. MMPTE MmFirstFreeSystemPte[MaximumPtePoolTypes];
  259. //
  260. // System cache sizes.
  261. //
  262. PMMWSL MmSystemCacheWorkingSetList = (PMMWSL)MM_SYSTEM_CACHE_WORKING_SET;
  263. MMSUPPORT MmSystemCacheWs;
  264. PMMWSLE MmSystemCacheWsle;
  265. PVOID MmSystemCacheStart = (PVOID)MM_SYSTEM_CACHE_START;
  266. PVOID MmSystemCacheEnd;
  267. PRTL_BITMAP MmSystemCacheAllocationMap;
  268. PRTL_BITMAP MmSystemCacheEndingMap;
  269. //
  270. // This value should not be greater than 256MB in a system with 1GB of
  271. // system space.
  272. //
  273. ULONG_PTR MmSizeOfSystemCacheInPages = 64 * 256; //64MB.
  274. //
  275. // Default sizes for the system cache.
  276. //
  277. PFN_NUMBER MmSystemCacheWsMinimum = 288;
  278. PFN_NUMBER MmSystemCacheWsMaximum = 350;
  279. //
  280. // Cells to track unused thread kernel stacks to avoid TB flushes
  281. // every time a thread terminates.
  282. //
  283. ULONG MmMaximumDeadKernelStacks = 5;
  284. SLIST_HEADER MmDeadStackSListHead;
  285. //
  286. // Cells to track control area synchronization.
  287. //
  288. SLIST_HEADER MmEventCountSListHead;
  289. SLIST_HEADER MmInPageSupportSListHead;
  290. //
  291. // MmSystemPteBase contains the address of 1 PTE before
  292. // the first free system PTE (zero indicates an empty list).
  293. // The value of this field does not change once set.
  294. //
  295. PMMPTE MmSystemPteBase;
  296. MM_AVL_TABLE MmSectionBasedRoot;
  297. PVOID MmHighSectionBase;
  298. //
  299. // Section object type.
  300. //
  301. POBJECT_TYPE MmSectionObjectType;
  302. //
  303. // Section commit mutex.
  304. //
  305. KGUARDED_MUTEX MmSectionCommitMutex;
  306. //
  307. // Section base address mutex.
  308. //
  309. KGUARDED_MUTEX MmSectionBasedMutex;
  310. //
  311. // Resource for section extension.
  312. //
  313. ERESOURCE MmSectionExtendResource;
  314. ERESOURCE MmSectionExtendSetResource;
  315. //
  316. // Pagefile creation lock.
  317. //
  318. KGUARDED_MUTEX MmPageFileCreationLock;
  319. MMDEREFERENCE_SEGMENT_HEADER MmDereferenceSegmentHeader;
  320. LIST_ENTRY MmUnusedSegmentList;
  321. LIST_ENTRY MmUnusedSubsectionList;
  322. KEVENT MmUnusedSegmentCleanup;
  323. ULONG MmUnusedSegmentCount;
  324. ULONG MmUnusedSubsectionCount;
  325. ULONG MmUnusedSubsectionCountPeak;
  326. SIZE_T MiUnusedSubsectionPagedPool;
  327. SIZE_T MiUnusedSubsectionPagedPoolPeak;
  328. //
  329. // If more than this percentage of pool is consumed and pool allocations
  330. // might fail, then trim unused segments & subsections to get back to
  331. // this percentage.
  332. //
  333. ULONG MmConsumedPoolPercentage;
  334. MMWORKING_SET_EXPANSION_HEAD MmWorkingSetExpansionHead;
  335. MMPAGE_FILE_EXPANSION MmAttemptForCantExtend;
  336. //
  337. // Paging files
  338. //
  339. MMMOD_WRITER_LISTHEAD MmPagingFileHeader;
  340. MMMOD_WRITER_LISTHEAD MmMappedFileHeader;
  341. LIST_ENTRY MmFreePagingSpaceLow;
  342. ULONG MmNumberOfActiveMdlEntries;
  343. PMMPAGING_FILE MmPagingFile[MAX_PAGE_FILES];
  344. ULONG MmNumberOfPagingFiles;
  345. KEVENT MmModifiedPageWriterEvent;
  346. KEVENT MmWorkingSetManagerEvent;
  347. KEVENT MmCollidedFlushEvent;
  348. //
  349. // Total number of committed pages.
  350. //
  351. SIZE_T MmTotalCommittedPages;
  352. #if DBG
  353. SPFN_NUMBER MiLockedCommit;
  354. #endif
  355. //
  356. // Limit on committed pages. When MmTotalCommittedPages would become
  357. // greater than or equal to this number the paging files must be expanded.
  358. //
  359. SIZE_T MmTotalCommitLimit;
  360. SIZE_T MmTotalCommitLimitMaximum;
  361. ULONG MiChargeCommitmentFailures[3]; // referenced also in mi.h macros.
  362. //
  363. // Modified page writer.
  364. //
  365. //
  366. // Minimum number of free pages before working set trimming and
  367. // aggressive modified page writing is started.
  368. //
  369. PFN_NUMBER MmMinimumFreePages = 26;
  370. //
  371. // Stop writing modified pages when MmFreeGoal pages exist.
  372. //
  373. PFN_NUMBER MmFreeGoal = 100;
  374. //
  375. // Start writing pages if more than this number of pages
  376. // is on the modified page list.
  377. //
  378. PFN_NUMBER MmModifiedPageMaximum;
  379. //
  380. // Amount of disk space that must be free after the paging file is
  381. // extended.
  382. //
  383. ULONG MmMinimumFreeDiskSpace = 1024 * 1024;
  384. //
  385. // Minimum size in pages to extend the paging file by.
  386. //
  387. ULONG MmPageFileExtension = 256;
  388. //
  389. // Size to reduce the paging file by.
  390. //
  391. ULONG MmMinimumPageFileReduction = 256; //256 pages (1mb)
  392. //
  393. // Number of pages to write in a single I/O.
  394. //
  395. ULONG MmModifiedWriteClusterSize = MM_MAXIMUM_WRITE_CLUSTER;
  396. //
  397. // Number of pages to read in a single I/O if possible.
  398. //
  399. ULONG MmReadClusterSize = 7;
  400. const ULONG MMSECT = 'tSmM'; // This is exported to special pool.
  401. //
  402. // Spin lock for allowing working set expansion.
  403. //
  404. KSPIN_LOCK MmExpansionLock;
  405. //
  406. // System process working set sizes.
  407. //
  408. PFN_NUMBER MmSystemProcessWorkingSetMin = 50;
  409. PFN_NUMBER MmSystemProcessWorkingSetMax = 450;
  410. WSLE_NUMBER MmMaximumWorkingSetSize;
  411. PFN_NUMBER MmMinimumWorkingSetSize = 20;
  412. //
  413. // Page color for system working set.
  414. //
  415. ULONG MmSystemPageColor;
  416. //
  417. // Time constants
  418. //
  419. const LARGE_INTEGER MmSevenMinutes = {0, -1};
  420. const LARGE_INTEGER MmOneSecond = {(ULONG)(-1 * 1000 * 1000 * 10), -1};
  421. const LARGE_INTEGER MmTwentySeconds = {(ULONG)(-20 * 1000 * 1000 * 10), -1};
  422. const LARGE_INTEGER MmSeventySeconds = {(ULONG)(-70 * 1000 * 1000 * 10), -1};
  423. const LARGE_INTEGER MmShortTime = {(ULONG)(-10 * 1000 * 10), -1}; // 10 milliseconds
  424. const LARGE_INTEGER MmHalfSecond = {(ULONG)(-5 * 100 * 1000 * 10), -1};
  425. const LARGE_INTEGER Mm30Milliseconds = {(ULONG)(-30 * 1000 * 10), -1};
  426. //
  427. // Parameters for user mode passed up via PEB in MmCreatePeb.
  428. //
  429. LARGE_INTEGER MmCriticalSectionTimeout; // Filled in by mminit.c
  430. SIZE_T MmHeapSegmentReserve = 1024 * 1024;
  431. SIZE_T MmHeapSegmentCommit = PAGE_SIZE * 2;
  432. SIZE_T MmHeapDeCommitTotalFreeThreshold = 64 * 1024;
  433. SIZE_T MmHeapDeCommitFreeBlockThreshold = PAGE_SIZE;
  434. //
  435. // Set from ntos\config\CMDAT3.C Used by customers to disable paging
  436. // of executive on machines with lots of memory. Worth a few TPS on a
  437. // database server.
  438. //
  439. ULONG MmDisablePagingExecutive;
  440. BOOLEAN Mm64BitPhysicalAddress;
  441. #if DBG
  442. ULONG MmDebug;
  443. #endif
  444. //
  445. // Map a page protection from the Pte.Protect field into a protection mask.
  446. //
  447. #ifdef ALLOC_DATA_PRAGMA
  448. #pragma data_seg("PAGEDATA")
  449. #endif
  450. ULONG MmProtectToValue[32] = {
  451. PAGE_NOACCESS,
  452. PAGE_READONLY,
  453. PAGE_EXECUTE,
  454. PAGE_EXECUTE_READ,
  455. PAGE_READWRITE,
  456. PAGE_WRITECOPY,
  457. PAGE_EXECUTE_READWRITE,
  458. PAGE_EXECUTE_WRITECOPY,
  459. PAGE_NOACCESS,
  460. PAGE_NOCACHE | PAGE_READONLY,
  461. PAGE_NOCACHE | PAGE_EXECUTE,
  462. PAGE_NOCACHE | PAGE_EXECUTE_READ,
  463. PAGE_NOCACHE | PAGE_READWRITE,
  464. PAGE_NOCACHE | PAGE_WRITECOPY,
  465. PAGE_NOCACHE | PAGE_EXECUTE_READWRITE,
  466. PAGE_NOCACHE | PAGE_EXECUTE_WRITECOPY,
  467. PAGE_NOACCESS,
  468. PAGE_GUARD | PAGE_READONLY,
  469. PAGE_GUARD | PAGE_EXECUTE,
  470. PAGE_GUARD | PAGE_EXECUTE_READ,
  471. PAGE_GUARD | PAGE_READWRITE,
  472. PAGE_GUARD | PAGE_WRITECOPY,
  473. PAGE_GUARD | PAGE_EXECUTE_READWRITE,
  474. PAGE_GUARD | PAGE_EXECUTE_WRITECOPY,
  475. PAGE_NOACCESS,
  476. PAGE_NOCACHE | PAGE_GUARD | PAGE_READONLY,
  477. PAGE_NOCACHE | PAGE_GUARD | PAGE_EXECUTE,
  478. PAGE_NOCACHE | PAGE_GUARD | PAGE_EXECUTE_READ,
  479. PAGE_NOCACHE | PAGE_GUARD | PAGE_READWRITE,
  480. PAGE_NOCACHE | PAGE_GUARD | PAGE_WRITECOPY,
  481. PAGE_NOCACHE | PAGE_GUARD | PAGE_EXECUTE_READWRITE,
  482. PAGE_NOCACHE | PAGE_GUARD | PAGE_EXECUTE_WRITECOPY
  483. };
  484. #ifdef ALLOC_DATA_PRAGMA
  485. #pragma data_seg()
  486. #endif
  487. #if (defined(_WIN64) || defined(_X86PAE_))
  488. ULONGLONG
  489. #else
  490. ULONG
  491. #endif
  492. MmProtectToPteMask[32] = {
  493. MM_PTE_NOACCESS,
  494. MM_PTE_READONLY | MM_PTE_CACHE,
  495. MM_PTE_EXECUTE | MM_PTE_CACHE,
  496. MM_PTE_EXECUTE_READ | MM_PTE_CACHE,
  497. MM_PTE_READWRITE | MM_PTE_CACHE,
  498. MM_PTE_WRITECOPY | MM_PTE_CACHE,
  499. MM_PTE_EXECUTE_READWRITE | MM_PTE_CACHE,
  500. MM_PTE_EXECUTE_WRITECOPY | MM_PTE_CACHE,
  501. MM_PTE_NOACCESS,
  502. MM_PTE_NOCACHE | MM_PTE_READONLY,
  503. MM_PTE_NOCACHE | MM_PTE_EXECUTE,
  504. MM_PTE_NOCACHE | MM_PTE_EXECUTE_READ,
  505. MM_PTE_NOCACHE | MM_PTE_READWRITE,
  506. MM_PTE_NOCACHE | MM_PTE_WRITECOPY,
  507. MM_PTE_NOCACHE | MM_PTE_EXECUTE_READWRITE,
  508. MM_PTE_NOCACHE | MM_PTE_EXECUTE_WRITECOPY,
  509. MM_PTE_NOACCESS,
  510. MM_PTE_GUARD | MM_PTE_READONLY | MM_PTE_CACHE,
  511. MM_PTE_GUARD | MM_PTE_EXECUTE | MM_PTE_CACHE,
  512. MM_PTE_GUARD | MM_PTE_EXECUTE_READ | MM_PTE_CACHE,
  513. MM_PTE_GUARD | MM_PTE_READWRITE | MM_PTE_CACHE,
  514. MM_PTE_GUARD | MM_PTE_WRITECOPY | MM_PTE_CACHE,
  515. MM_PTE_GUARD | MM_PTE_EXECUTE_READWRITE | MM_PTE_CACHE,
  516. MM_PTE_GUARD | MM_PTE_EXECUTE_WRITECOPY | MM_PTE_CACHE,
  517. MM_PTE_NOACCESS,
  518. MM_PTE_NOCACHE | MM_PTE_GUARD | MM_PTE_READONLY,
  519. MM_PTE_NOCACHE | MM_PTE_GUARD | MM_PTE_EXECUTE,
  520. MM_PTE_NOCACHE | MM_PTE_GUARD | MM_PTE_EXECUTE_READ,
  521. MM_PTE_NOCACHE | MM_PTE_GUARD | MM_PTE_READWRITE,
  522. MM_PTE_NOCACHE | MM_PTE_GUARD | MM_PTE_WRITECOPY,
  523. MM_PTE_NOCACHE | MM_PTE_GUARD | MM_PTE_EXECUTE_READWRITE,
  524. MM_PTE_NOCACHE | MM_PTE_GUARD | MM_PTE_EXECUTE_WRITECOPY
  525. };
  526. //
  527. // Conversion which takes a Pte.Protect and builds a new Pte.Protect which
  528. // is not copy-on-write.
  529. //
  530. ULONG MmMakeProtectNotWriteCopy[32] = {
  531. MM_NOACCESS,
  532. MM_READONLY,
  533. MM_EXECUTE,
  534. MM_EXECUTE_READ,
  535. MM_READWRITE,
  536. MM_READWRITE, //not copy
  537. MM_EXECUTE_READWRITE,
  538. MM_EXECUTE_READWRITE,
  539. MM_NOACCESS,
  540. MM_NOCACHE | MM_READONLY,
  541. MM_NOCACHE | MM_EXECUTE,
  542. MM_NOCACHE | MM_EXECUTE_READ,
  543. MM_NOCACHE | MM_READWRITE,
  544. MM_NOCACHE | MM_READWRITE,
  545. MM_NOCACHE | MM_EXECUTE_READWRITE,
  546. MM_NOCACHE | MM_EXECUTE_READWRITE,
  547. MM_NOACCESS,
  548. MM_GUARD_PAGE | MM_READONLY,
  549. MM_GUARD_PAGE | MM_EXECUTE,
  550. MM_GUARD_PAGE | MM_EXECUTE_READ,
  551. MM_GUARD_PAGE | MM_READWRITE,
  552. MM_GUARD_PAGE | MM_READWRITE,
  553. MM_GUARD_PAGE | MM_EXECUTE_READWRITE,
  554. MM_GUARD_PAGE | MM_EXECUTE_READWRITE,
  555. MM_NOACCESS,
  556. MM_NOCACHE | MM_GUARD_PAGE | MM_READONLY,
  557. MM_NOCACHE | MM_GUARD_PAGE | MM_EXECUTE,
  558. MM_NOCACHE | MM_GUARD_PAGE | MM_EXECUTE_READ,
  559. MM_NOCACHE | MM_GUARD_PAGE | MM_READWRITE,
  560. MM_NOCACHE | MM_GUARD_PAGE | MM_READWRITE,
  561. MM_NOCACHE | MM_GUARD_PAGE | MM_EXECUTE_READWRITE,
  562. MM_NOCACHE | MM_GUARD_PAGE | MM_EXECUTE_READWRITE
  563. };
  564. #ifdef ALLOC_DATA_PRAGMA
  565. #pragma data_seg("PAGEDATA")
  566. #endif
  567. //
  568. // Converts a protection code to an access right for section access.
  569. // This uses only the lower 3 bits of the 5 bit protection code.
  570. //
  571. ACCESS_MASK MmMakeSectionAccess[8] = { SECTION_MAP_READ,
  572. SECTION_MAP_READ,
  573. SECTION_MAP_EXECUTE,
  574. SECTION_MAP_EXECUTE | SECTION_MAP_READ,
  575. SECTION_MAP_WRITE,
  576. SECTION_MAP_READ,
  577. SECTION_MAP_EXECUTE | SECTION_MAP_WRITE,
  578. SECTION_MAP_EXECUTE | SECTION_MAP_READ };
  579. //
  580. // Converts a protection code to an access right for file access.
  581. // This uses only the lower 3 bits of the 5 bit protection code.
  582. //
  583. ACCESS_MASK MmMakeFileAccess[8] = { FILE_READ_DATA,
  584. FILE_READ_DATA,
  585. FILE_EXECUTE,
  586. FILE_EXECUTE | FILE_READ_DATA,
  587. FILE_WRITE_DATA | FILE_READ_DATA,
  588. FILE_READ_DATA,
  589. FILE_EXECUTE | FILE_WRITE_DATA | FILE_READ_DATA,
  590. FILE_EXECUTE | FILE_READ_DATA };
  591. #ifdef ALLOC_DATA_PRAGMA
  592. #pragma data_seg()
  593. #endif
  594. MM_PAGED_POOL_INFO MmPagedPoolInfo;
  595. //
  596. // Some Hydra variables.
  597. //
  598. ULONG_PTR MmSessionBase;
  599. PMM_SESSION_SPACE MmSessionSpace;
  600. ULONG_PTR MiSessionSpaceWs;
  601. SIZE_T MmSessionSize;
  602. LIST_ENTRY MiSessionWsList;
  603. ULONG_PTR MiSystemViewStart;
  604. SIZE_T MmSystemViewSize;
  605. ULONG_PTR MiSessionPoolStart;
  606. ULONG_PTR MiSessionPoolEnd;
  607. ULONG_PTR MiSessionSpaceEnd;
  608. ULONG_PTR MiSessionViewStart;
  609. ULONG MiSessionSpacePageTables;
  610. SIZE_T MmSessionViewSize;
  611. SIZE_T MmSessionPoolSize;
  612. ULONG_PTR MiSessionImageStart;
  613. ULONG_PTR MiSessionImageEnd;
  614. PMMPTE MiSessionImagePteStart;
  615. PMMPTE MiSessionImagePteEnd;
  616. SIZE_T MmSessionImageSize;
  617. //
  618. // Cache control stuff. Note this may be overridden by deficient hardware
  619. // platforms at startup.
  620. //
  621. MI_PFN_CACHE_ATTRIBUTE MiPlatformCacheAttributes[2 * MmMaximumCacheType] =
  622. {
  623. //
  624. // Memory space
  625. //
  626. MiNonCached,
  627. MiCached,
  628. MiWriteCombined,
  629. MiCached,
  630. MiNonCached,
  631. MiWriteCombined,
  632. //
  633. // I/O space
  634. //
  635. MiNonCached,
  636. MiCached,
  637. MiWriteCombined,
  638. MiCached,
  639. MiNonCached,
  640. MiWriteCombined
  641. };
  642. //
  643. // Note the Driver Verifier can reinitialize the mask values.
  644. //
  645. ULONG MiIoRetryMask = 0x1f;
  646. ULONG MiFaultRetryMask = 0x1f;
  647. ULONG MiUserFaultRetryMask = 0xF;
  648. #if defined (_MI_INSTRUMENT_PFN) || defined (_MI_INSTRUMENT_WS)
  649. EPROCESS MiSystemCacheDummyProcess;
  650. //
  651. // Instrumentation code to track PFN lock duration.
  652. //
  653. ULONG MiPfnTimings;
  654. PVOID MiPfnAcquiredAddress;
  655. LARGE_INTEGER MiPfnAcquired;
  656. LARGE_INTEGER MiPfnReleased;
  657. LARGE_INTEGER MiPfnThreshold;
  658. MMPFNTIMINGS MiPfnSorted[MI_MAX_PFN_CALLERS];
  659. ULONG MiMaxPfnTimings = MI_MAX_PFN_CALLERS;
  660. PVOID
  661. MiGetExecutionAddress (
  662. VOID
  663. )
  664. {
  665. #if defined(_X86_)
  666. _asm {
  667. push dword ptr [esp]
  668. pop eax
  669. }
  670. #else
  671. PVOID CallingAddress;
  672. PVOID CallersCaller;
  673. RtlGetCallersAddress (&CallingAddress, &CallersCaller);
  674. return CallingAddress;
  675. #endif
  676. }
  677. LARGE_INTEGER
  678. MiQueryPerformanceCounter (
  679. IN PLARGE_INTEGER PerformanceFrequency
  680. )
  681. {
  682. #if defined(_X86_)
  683. UNREFERENCED_PARAMETER (PerformanceFrequency);
  684. _asm {
  685. rdtsc
  686. }
  687. #else
  688. return KeQueryPerformanceCounter (PerformanceFrequency);
  689. #endif
  690. }
  691. #if defined (_MI_INSTRUMENT_WS)
  692. KSPIN_LOCK MiInstrumentationLock;
  693. #endif
  694. VOID
  695. MiAddLockToTable (
  696. IN PVOID AcquireAddress,
  697. IN PVOID ReleaseAddress,
  698. IN LARGE_INTEGER HoldTime
  699. )
  700. {
  701. ULONG i;
  702. #if defined (_MI_INSTRUMENT_WS)
  703. KIRQL OldIrql;
  704. #endif
  705. i = MI_MAX_PFN_CALLERS - 1;
  706. #if defined (_MI_INSTRUMENT_WS)
  707. ExAcquireSpinLock (&MiInstrumentationLock, &OldIrql);
  708. #endif
  709. do {
  710. if (HoldTime.QuadPart < MiPfnSorted[i].HoldTime.QuadPart) {
  711. break;
  712. }
  713. i -= 1;
  714. } while (i != (ULONG)-1);
  715. if (i != MI_MAX_PFN_CALLERS - 1) {
  716. i += 1;
  717. if (i != MI_MAX_PFN_CALLERS - 1) {
  718. RtlMoveMemory (&MiPfnSorted[i+1], &MiPfnSorted[i], (MI_MAX_PFN_CALLERS-(i+1)) * sizeof(MMPFNTIMINGS));
  719. }
  720. MiPfnSorted[i].HoldTime = HoldTime;
  721. #if defined (_MI_INSTRUMENT_WS)
  722. if (PsGetCurrentProcess()->WorkingSetLock.Count != 0)
  723. #else
  724. if (KeTestForWaitersQueuedSpinLock (LockQueuePfnLock) == TRUE)
  725. #endif
  726. {
  727. MiPfnSorted[i].HoldTime.LowPart |= 0x1;
  728. }
  729. MiPfnSorted[i].AcquiredAddress = AcquireAddress;
  730. MiPfnSorted[i].ReleasedAddress = ReleaseAddress;
  731. }
  732. if ((MiPfnTimings & 0x2) && (HoldTime.QuadPart >= MiPfnThreshold.QuadPart)) {
  733. DbgBreakPoint ();
  734. }
  735. if (MiPfnTimings & 0x1) {
  736. MiPfnTimings &= ~0x1;
  737. RtlZeroMemory (&MiPfnSorted[0], MI_MAX_PFN_CALLERS * sizeof(MMPFNTIMINGS));
  738. }
  739. #if defined (_MI_INSTRUMENT_WS)
  740. ExReleaseSpinLock (&MiInstrumentationLock, OldIrql);
  741. #endif
  742. return;
  743. }
  744. #endif
  745. #ifdef ALLOC_DATA_PRAGMA
  746. #pragma data_seg("INIT")
  747. #endif
  748. WCHAR MmVerifyDriverBuffer[MI_SUSPECT_DRIVER_BUFFER_LENGTH] = {0};
  749. ULONG MmVerifyDriverBufferType = REG_NONE;
  750. ULONG MmVerifyDriverLevel = (ULONG)-1;
  751. ULONG MmCritsectTimeoutSeconds = 2592000;
  752. ULONG MmLargePageDriverBufferType = REG_NONE;
  753. #ifdef ALLOC_DATA_PRAGMA
  754. #pragma data_seg()
  755. #endif
  756. WCHAR MmLargePageDriverBuffer[MI_LARGE_PAGE_DRIVER_BUFFER_LENGTH] = {0};
  757. ULONG MmVerifyDriverBufferLength = sizeof(MmVerifyDriverBuffer);
  758. ULONG MmLargePageDriverBufferLength = sizeof(MmLargePageDriverBuffer);