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.

3881 lines
95 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Copyright (c) 1995 Intel Corporation
  4. Module Name:
  5. miia64.h
  6. Abstract:
  7. This module contains the private data structures and procedure
  8. prototypes for the hardware dependent portion of the
  9. memory management system.
  10. This module is specifically tailored for the IA64.
  11. Author:
  12. Lou Perazzoli (loup) 6-Jan-1990
  13. Landy Wang (landyw) 2-June-1997
  14. Koichi Yamada (kyamada) 9-Jan-1996
  15. Revision History:
  16. --*/
  17. /*++
  18. Virtual Memory Layout on IA64 is:
  19. +------------------------------------+
  20. 0000000000000000 | User mode addresses - 7tb - 16gb | UADDRESS_BASE
  21. | |
  22. | |
  23. 000006FBFFFEFFFF | | MM_HIGHEST_USER_ADDRESS
  24. +------------------------------------+
  25. 000006FBFFFF0000 | 64k No Access Region | MM_USER_PROBE_ADDRESS
  26. +------------------------------------+
  27. 000006FC00000000 | Alternate 4K-page mappings | ALT4KB_BASE
  28. | for x86 process emulation |
  29. 000006FC00400000 | Alternate 4K-page mappings | ALT4KB_END
  30. +------------------------------------+
  31. 000006FC00800000 | HyperSpace - working set lists | HYPER_SPACE
  32. | and per process memory management |
  33. | structures mapped in this 16gb |
  34. 000006FFFFFFFFFF | region. | HYPER_SPACE_END
  35. +------------------------------------+
  36. 0000070000000000 | |
  37. | Page table selfmapping structures |
  38. 000007FFFFFFFFFF | |
  39. +------------------------------------+
  40. .
  41. .
  42. +------------------------------------+
  43. 1FFFFF0000000000 | 8gb leaf level page table map | PTE_UBASE
  44. | for user space |
  45. 1FFFFF01FFFFFFFF | | PTE_UTOP
  46. +------------------------------------+
  47. +------------------------------------+
  48. 1FFFFFFFC0000000 | 8mb page directory (2nd level) | PDE_UBASE
  49. | table map for user space |
  50. 1FFFFFFFC07FFFFF | | PDE_UTOP
  51. +------------------------------------+
  52. +------------------------------------+
  53. 1FFFFFFFFFF00000 | 8KB parent directory (1st level) | PDE_UTBASE
  54. +------------------------------------+
  55. .
  56. .
  57. +------------------------------------+
  58. 2000000000000000 | 1. Win32k.sys | MM_SESSION_SPACE_DEFAULT
  59. | 2. Hydra - 8gb |
  60. | and per session memory management |
  61. | structures mapped in this 8gb |
  62. | region. |
  63. +------------------------------------+
  64. .
  65. +------------------------------------+
  66. 3FFFFF0000000000 | 8gb leaf level page table map | PTE_SBASE
  67. | for session space |
  68. 3FFFFF01FFFFFFFF | | PTE_STOP
  69. +------------------------------------+
  70. +------------------------------------+
  71. 3FFFFFFFC0000000 | 8mb page directory (2nd level) | PDE_SBASE
  72. | table map for session space |
  73. 3FFFFFFFC07FFFFF | | PDE_STOP
  74. +------------------------------------+
  75. +------------------------------------+
  76. 3FFFFFFFFFF00000 | 8KB parent directory (1st level) | PDE_STBASE
  77. +------------------------------------+
  78. .
  79. +------------------------------------+
  80. 8000000000000000 | physical addressable memory | KSEG3_BASE
  81. | for 44-bit of address space |
  82. 80000FFFFFFFFFFF | mapped by VHPT 64KB page | KSEG3_LIMIT
  83. +------------------------------------+
  84. .
  85. +------------------------------------+
  86. 9FFFFF00000000000| vhpt 64kb page for KSEG3 space |
  87. | (not used) |
  88. +------------------------------------+
  89. .
  90. .
  91. +------------------------------------+ MM_SYSTEM_RANGE_START
  92. E000000000000000 | | KADDRESS_BASE
  93. +------------------------------------+
  94. E000000080000000 | The HAL, kernel, initial drivers, | KSEG0_BASE
  95. | NLS data, and registry load in the |
  96. | first 16mb of this region which |
  97. | physically addresses memory. |
  98. | |
  99. | Kernel mode access only. |
  100. | |
  101. | Initial NonPaged Pool is within |
  102. | KSEG0 |
  103. | | KSEG2_BASE
  104. +------------------------------------+
  105. E0000000FF000000 | Shared system page | KI_USER_SHARED_DATA
  106. +------------------------------------+
  107. E0000000FF002000 | Reserved for the HAL. |
  108. | |
  109. | |
  110. E0000000FFFFFFFF | |
  111. +------------------------------------+
  112. .
  113. .
  114. +------------------------------------+
  115. E000000200000000 | |
  116. | |
  117. | |
  118. | |
  119. +------------------------------------+
  120. E000000400000000 | The system cache working set | MM_SYSTEM_CACHE_WORKING_SET
  121. | | MM_SYSTEM_SPACE_START
  122. | information resides in this 8gb |
  123. | region. |
  124. +------------------------------------+
  125. E000000600000000 | System cache resides here. | MM_SYSTEM_CACHE_START
  126. | Kernel mode access only. |
  127. | 1tb. |
  128. +------------------------------------+
  129. E000010600000000 | Start of paged system area. | MM_PAGED_POOL_START
  130. | Kernel mode access only. |
  131. | 128gb. |
  132. +------------------------------------+
  133. | System mapped views start just |
  134. | after paged pool. Default is |
  135. | 104MB, can be registry-overridden. |
  136. | 8GB maximum. |
  137. +------------------------------------+
  138. | |
  139. .
  140. .
  141. In general, the next two areas (system PTE pool and nonpaged pool) will both
  142. be shifted upwards to conserve a PPE...
  143. .
  144. .
  145. +------------------------------------+
  146. E000012600000000 | System PTE pool. | MM_LOWEST_NONPAGED_SYSTEM_START
  147. | Kernel mode access only. |
  148. | 128gb. |
  149. +------------------------------------+
  150. E000014600000000 | NonPaged pool. | MM_NON_PAGED_POOL_START
  151. | Kernel mode access only. |
  152. | 128gb. |
  153. | |
  154. E0000165FFFFFFFF | NonPaged System area | MM_NONPAGED_POOL_END
  155. +------------------------------------+
  156. .
  157. .
  158. E000040000000000 +------------------------------------+ MM_PFN_DATABASE_START
  159. | PFN Database space |
  160. | Kernel mode access only. |
  161. | 2tb. |
  162. E000060000000000 +------------------------------------+ MM_PFN_DATABASE_END
  163. . MM_SYSTEM_SPACE_END
  164. .
  165. .
  166. +------------------------------------+
  167. FFFFFF0000000000 | 8gb leaf level page table map | PTE_KBASE
  168. | for kernel space |
  169. FFFFFF01FFFFFFFF | | PTE_KTOP
  170. +------------------------------------+
  171. +------------------------------------+
  172. FFFFFFFFC0000000 | 8mb page directory (2nd level) | PDE_KBASE
  173. | table map for kernel space |
  174. FFFFFFFFC07FFFFF | | PDE_KTOP
  175. +------------------------------------+
  176. +------------------------------------+
  177. FFFFFFFFFFF00000 | 8KB parent directory (1st level) | PDE_KTBASE
  178. +------------------------------------+
  179. --*/
  180. #define _MI_PAGING_LEVELS 3
  181. #define _MI_MORE_THAN_4GB_ 1
  182. #define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_IA64
  183. #define _MIALT4K_ 1
  184. //
  185. // Define empty list markers.
  186. //
  187. #define MM_EMPTY_LIST ((ULONG_PTR)-1) //
  188. #define MM_EMPTY_PTE_LIST ((ULONG)0xFFFFFFFF) // N.B. tied to MMPTE definition
  189. #define MI_PTE_BASE_FOR_LOWEST_KERNEL_ADDRESS ((PMMPTE)PTE_KBASE)
  190. //
  191. // Define the session PTE base.
  192. //
  193. #define MI_PTE_BASE_FOR_LOWEST_SESSION_ADDRESS ((PMMPTE)PTE_SBASE)
  194. //
  195. // 43-Bit virtual address mask.
  196. //
  197. #define MASK_43 0x7FFFFFFFFFFUI64 //
  198. //
  199. // 44-Bit Physical address mask.
  200. //
  201. #define MASK_44 0xFFFFFFFFFFFUI64
  202. #define MM_PAGES_IN_KSEG0 ((ULONG)((KSEG2_BASE - KSEG0_BASE) >> PAGE_SHIFT))
  203. extern ULONG_PTR MmKseg2Frame;
  204. extern ULONGLONG MmPageSizeInfo;
  205. #define MM_USER_ADDRESS_RANGE_LIMIT (0xFFFFFFFFFFFFFFFFUI64) // user address range limit
  206. #define MM_MAXIMUM_ZERO_BITS 53 // maximum number of zero bits
  207. //
  208. // PAGE_SIZE for IA64 is 8k, virtual page is 20 bits with a PAGE_SHIFT
  209. // byte offset.
  210. //
  211. #define MM_VIRTUAL_PAGE_FILLER (PAGE_SHIFT - 12)
  212. #define MM_VIRTUAL_PAGE_SIZE (64-PAGE_SHIFT)
  213. //
  214. // Address space layout definitions.
  215. //
  216. #define CODE_START KSEG0_BASE
  217. #define CODE_END KSEG2_BASE
  218. #define MM_SYSTEM_SPACE_START (KADDRESS_BASE + 0x400000000UI64)
  219. #define MM_SYSTEM_SPACE_END (KADDRESS_BASE + 0x60000000000UI64)
  220. #define PDE_TOP PDE_UTOP
  221. #define PTE_TOP PTE_UTOP
  222. //
  223. // Define Alternate 4KB permission table space for X86 emulation mappings.
  224. //
  225. #define ALT4KB_PERMISSION_TABLE_START ((PVOID)(UADDRESS_BASE + 0x6FC00000000))
  226. #define ALT4KB_PERMISSION_TABLE_END ((PVOID)(UADDRESS_BASE + 0x6FC00400000))
  227. //
  228. // Define hyper space.
  229. //
  230. #define HYPER_SPACE ((PVOID)(UADDRESS_BASE + 0x6FC00800000))
  231. #define HYPER_SPACE_END ((PVOID)(UADDRESS_BASE + 0x6FFFFFFFFFF))
  232. //
  233. // Define area for mapping views into system space.
  234. //
  235. #define MM_SYSTEM_VIEW_SIZE (104*1024*1024)
  236. //
  237. // Hydra lives in region 1.
  238. //
  239. #define MM_SESSION_SPACE_DEFAULT (0x2000000000000000UI64)
  240. #define MM_SESSION_SPACE_DEFAULT_END (0x2000000200000000UI64)
  241. //
  242. // Define the start and maximum size for the system cache.
  243. //
  244. #define MM_SYSTEM_CACHE_WORKING_SET (KADDRESS_BASE + 0x400000000UI64)
  245. #define MM_SYSTEM_CACHE_START (KADDRESS_BASE + 0x600000000UI64)
  246. #define MM_SYSTEM_CACHE_END (KADDRESS_BASE + 0x1005FFFFFFFFUI64)
  247. #define MM_MAXIMUM_SYSTEM_CACHE_SIZE \
  248. (((ULONG_PTR)MM_SYSTEM_CACHE_END - (ULONG_PTR)MM_SYSTEM_CACHE_START) >> PAGE_SHIFT)
  249. #define MM_PAGED_POOL_START ((PVOID)(KADDRESS_BASE + 0x10600000000UI64))
  250. #define MM_LOWEST_NONPAGED_SYSTEM_START ((PVOID)(KADDRESS_BASE + 0x12600000000UI64))
  251. #define MmProtopte_Base (KADDRESS_BASE)
  252. #define MM_NONPAGED_POOL_END ((PVOID)(KADDRESS_BASE + 0x16600000000UI64 - (16 * PAGE_SIZE)))
  253. #define MM_CRASH_DUMP_VA ((PVOID)(KADDRESS_BASE + 0xFF800000))
  254. // EPC VA at 0xFFA00000 (see ntia64.h)
  255. #define MM_DEBUG_VA ((PVOID)(KADDRESS_BASE + 0xFF900000))
  256. #define NON_PAGED_SYSTEM_END (KADDRESS_BASE + 0x16600000000UI64) //quadword aligned.
  257. #define MM_PFN_DATABASE_START (KADDRESS_BASE + 0x40000000000UI64)
  258. #define MM_PFN_DATABASE_END (KADDRESS_BASE + 0x60000000000UI64)
  259. extern ULONG MiMaximumSystemCacheSize;
  260. //
  261. // Define absolute minimum and maximum count for system ptes.
  262. //
  263. #define MM_MINIMUM_SYSTEM_PTES 7000
  264. #define MM_MAXIMUM_SYSTEM_PTES (16*1024*1024)
  265. #define MM_DEFAULT_SYSTEM_PTES 11000
  266. //
  267. // Pool limits
  268. //
  269. //
  270. // The maximum amount of nonpaged pool that can be initially created.
  271. //
  272. #define MM_MAX_INITIAL_NONPAGED_POOL ((SIZE_T)(128 * 1024 * 1024))
  273. //
  274. // The total amount of nonpaged pool (initial pool + expansion + system PTEs).
  275. //
  276. #define MM_MAX_ADDITIONAL_NONPAGED_POOL (((SIZE_T)128 * 1024 * 1024 * 1024) - 16)
  277. //
  278. // The maximum amount of paged pool that can be created.
  279. //
  280. #define MM_MAX_PAGED_POOL ((SIZE_T)128 * 1024 * 1024 * 1024)
  281. //
  282. // Define the maximum default for pool (user specified 0 in registry).
  283. //
  284. #define MM_MAX_DEFAULT_NONPAGED_POOL ((SIZE_T)8 * 1024 * 1024 * 1024)
  285. //
  286. // Structure layout defintions.
  287. //
  288. #define MM_PROTO_PTE_ALIGNMENT ((ULONG)PAGE_SIZE)
  289. //
  290. // Define the address bits mapped by PPE and PDE entries.
  291. //
  292. // A PPE entry maps 10+10+13 = 33 bits of address space.
  293. // A PDE entry maps 10+13 = 23 bits of address space.
  294. //
  295. #define PAGE_DIRECTORY1_MASK (((ULONG_PTR)1 << PDI1_SHIFT) - 1)
  296. #define PAGE_DIRECTORY2_MASK (((ULONG_PTR)1 << PDI_SHIFT) -1)
  297. #define MM_VA_MAPPED_BY_PDE ((ULONG_PTR)1 << PDI_SHIFT)
  298. #define MM_VA_MAPPED_BY_PPE ((ULONG_PTR)1 << PDI1_SHIFT)
  299. #define LOWEST_IO_ADDRESS 0xa0000
  300. //
  301. // The number of bits in a physical address.
  302. //
  303. #define PHYSICAL_ADDRESS_BITS 44
  304. #define MM_MAXIMUM_NUMBER_OF_COLORS (1)
  305. //
  306. // IA64 does not require support for colored pages.
  307. //
  308. #define MM_NUMBER_OF_COLORS (1)
  309. //
  310. // Mask for obtaining color from a physical page number.
  311. //
  312. #define MM_COLOR_MASK (0)
  313. //
  314. // Boundary for aligned pages of like color upon.
  315. //
  316. #define MM_COLOR_ALIGNMENT (0)
  317. //
  318. // Mask for isolating color from virtual address.
  319. //
  320. #define MM_COLOR_MASK_VIRTUAL (0)
  321. //
  322. // Define 256k worth of secondary colors.
  323. //
  324. #define MM_SECONDARY_COLORS_DEFAULT (64)
  325. #define MM_SECONDARY_COLORS_MIN (2)
  326. #define MM_SECONDARY_COLORS_MAX (1024)
  327. //
  328. // Maximum number of paging files.
  329. //
  330. #define MAX_PAGE_FILES 16
  331. //
  332. // Hyper space definitions.
  333. //
  334. #define FIRST_MAPPING_PTE ((PMMPTE)HYPER_SPACE)
  335. #define NUMBER_OF_MAPPING_PTES 253
  336. #define LAST_MAPPING_PTE \
  337. ((PVOID)((ULONG_PTR)FIRST_MAPPING_PTE + (NUMBER_OF_MAPPING_PTES * PAGE_SIZE)))
  338. #define COMPRESSION_MAPPING_PTE ((PMMPTE)((ULONG_PTR)LAST_MAPPING_PTE + PAGE_SIZE))
  339. #define IMAGE_MAPPING_PTE ((PMMPTE)((ULONG_PTR)COMPRESSION_MAPPING_PTE + PAGE_SIZE))
  340. #define NUMBER_OF_ZEROING_PTES 32
  341. #define VAD_BITMAP_SPACE ((PVOID)((ULONG_PTR)IMAGE_MAPPING_PTE + PAGE_SIZE))
  342. #define WORKING_SET_LIST ((PVOID)((ULONG_PTR)VAD_BITMAP_SPACE + PAGE_SIZE))
  343. #define MM_MAXIMUM_WORKING_SET (((ULONG_PTR)(HYPER_SPACE)) >> PAGE_SHIFT)
  344. #define MmWorkingSetList ((PMMWSL)WORKING_SET_LIST)
  345. #define MmWsle ((PMMWSLE)((PUCHAR)WORKING_SET_LIST + sizeof(MMWSL)))
  346. #define MM_WORKING_SET_END (UADDRESS_BASE + 0x3FFFFFFFFFFUI64)
  347. //
  348. // Define memory attributes fields within PTE.
  349. //
  350. #define MM_PTE_TB_MA_WB (0x0 << 2) // cacheable, write-back
  351. #define MM_PTE_TB_MA_UC (0x4 << 2) // uncacheable
  352. #define MM_PTE_TB_MA_UCE (0x5 << 2) // uncacheable, exporting fetchadd
  353. #define MM_PTE_TB_MA_WC (0x6 << 2) // uncacheable, coalescing
  354. #define MM_PTE_TB_MA_NATPAGE (0x7 << 2) // Nat Page
  355. //
  356. // Define masks for the PTE cache attributes.
  357. //
  358. #define MM_PTE_CACHE_ENABLED 0 // WB
  359. #define MM_PTE_CACHE_DISABLED 4 // UC
  360. #define MM_PTE_CACHE_DISPLAY 6 // WC
  361. #define MM_PTE_CACHE_RESERVED 1 // special encoding to cause a TLB miss
  362. //
  363. // Define masks for fields within the PTE.
  364. //
  365. #define MM_PTE_OWNER_MASK 0x0180
  366. #define MM_PTE_VALID_MASK 1
  367. #define MM_PTE_CACHE_DISABLE_MASK MM_PTE_TB_MA_UC
  368. #define MM_PTE_ACCESS_MASK 0x0020
  369. #define MM_PTE_DIRTY_MASK 0x0040
  370. #define MM_PTE_EXECUTE_MASK 0x0200
  371. #define MM_PTE_WRITE_MASK 0x0400
  372. #define MM_PTE_LARGE_PAGE_MASK 0
  373. #define MM_PTE_COPY_ON_WRITE_MASK ((ULONG)1 << (PAGE_SHIFT-1))
  374. #define MM_PTE_PROTOTYPE_MASK 0x0002
  375. #define MM_PTE_TRANSITION_MASK 0x0080
  376. //
  377. // Bit fields to or into PTE to make a PTE valid based on the
  378. // protection field of the invalid PTE.
  379. //
  380. #define MM_PTE_NOACCESS 0x0
  381. #define MM_PTE_READONLY 0x0
  382. #define MM_PTE_READWRITE MM_PTE_WRITE_MASK
  383. #define MM_PTE_WRITECOPY MM_PTE_COPY_ON_WRITE_MASK
  384. #define MM_PTE_EXECUTE MM_PTE_EXECUTE_MASK
  385. #define MM_PTE_EXECUTE_READ MM_PTE_EXECUTE_MASK
  386. #define MM_PTE_EXECUTE_READWRITE MM_PTE_EXECUTE_MASK | MM_PTE_WRITE_MASK
  387. #define MM_PTE_EXECUTE_WRITECOPY MM_PTE_EXECUTE_MASK | MM_PTE_COPY_ON_WRITE_MASK
  388. #define MM_PTE_GUARD 0x0
  389. #define MM_PTE_CACHE MM_PTE_TB_MA_WB
  390. #define MM_PTE_NOCACHE MM_PTE_CACHE // PAGE_NOCACHE is cached
  391. #define MM_PTE_EXC_DEFER 0x10000000000000 // defer exception
  392. #define MM_PROTECT_FIELD_SHIFT 2
  393. //
  394. // Define masks for fields within the IA64 TB entry.
  395. //
  396. #define MM_PTE_TB_VALID 0x0001
  397. #define MM_PTE_TB_ACCESSED 0x0020
  398. #define MM_PTE_TB_MODIFIED 0x0040
  399. #define MM_PTE_TB_WRITE 0x0400
  400. #define MM_PTE_TB_EXECUTE 0x0200 // read/execute
  401. #define MM_PTE_TB_EXC_DEFER 0x10000000000000 // defer exception
  402. //
  403. // Define the number of VHPT pages.
  404. //
  405. #define MM_VHPT_PAGES 32
  406. //
  407. // Bits available for the software working set index within the hardware PTE.
  408. //
  409. #define MI_MAXIMUM_PTE_WORKING_SET_INDEX (1 << _HARDWARE_PTE_WORKING_SET_BITS)
  410. //
  411. // Zero PTE.
  412. //
  413. #define MM_ZERO_PTE 0
  414. //
  415. // Zero Kernel PTE.
  416. //
  417. #define MM_ZERO_KERNEL_PTE 0
  418. //
  419. // A demand zero PTE with a protection of PAGE_READWRITE.
  420. //
  421. #define MM_DEMAND_ZERO_WRITE_PTE ((ULONGLONG)MM_READWRITE << MM_PROTECT_FIELD_SHIFT)
  422. //
  423. // A demand zero PTE with a protection of PAGE_READWRITE for system space.
  424. //
  425. #define MM_KERNEL_DEMAND_ZERO_PTE ((ULONGLONG)MM_READWRITE << MM_PROTECT_FIELD_SHIFT)
  426. //
  427. // A no access PTE for system space.
  428. //
  429. #define MM_KERNEL_NOACCESS_PTE ((ULONGLONG)MM_NOACCESS << MM_PROTECT_FIELD_SHIFT)
  430. //
  431. // Kernel stack alignment requirements.
  432. //
  433. #define MM_STACK_ALIGNMENT 0x0
  434. #define MM_STACK_OFFSET 0x0
  435. #define PDE_PER_PAGE ((ULONG)(PAGE_SIZE/(1 << PTE_SHIFT)))
  436. #define PTE_PER_PAGE ((ULONG)(PAGE_SIZE/(1 << PTE_SHIFT)))
  437. #define PTE_PER_PAGE_BITS 11 // This handles the case where the page is full
  438. #if PTE_PER_PAGE_BITS > 32
  439. error - too many bits to fit into MMPTE_SOFTWARE or MMPFN.u1
  440. #endif
  441. //
  442. // Number of page table pages for user addresses.
  443. //
  444. #define MM_USER_PAGE_TABLE_PAGES ((ULONG_PTR)MI_SYSTEM_RANGE_START / (PTE_PER_PAGE * PAGE_SIZE))
  445. #define MM_USER_PAGE_DIRECTORY_PAGES ((ULONG_PTR)MI_SYSTEM_RANGE_START / ((ULONG_PTR)PDE_PER_PAGE * PTE_PER_PAGE * PAGE_SIZE))
  446. //++
  447. //VOID
  448. //MI_MAKE_VALID_PTE (
  449. // OUT OUTPTE,
  450. // IN FRAME,
  451. // IN PMASK,
  452. // IN PPTE
  453. // );
  454. //
  455. // Routine Description:
  456. //
  457. // This macro makes a valid PTE from a page frame number, protection mask,
  458. // and owner.
  459. //
  460. // Arguments:
  461. //
  462. // OUTPTE - Supplies the PTE in which to build the transition PTE.
  463. //
  464. // FRAME - Supplies the page frame number for the PTE.
  465. //
  466. // PMASK - Supplies the protection to set in the transition PTE.
  467. //
  468. // PPTE - Supplies a pointer to the PTE which is being made valid.
  469. // For prototype PTEs NULL should be specified.
  470. //
  471. // Return Value:
  472. //
  473. // None.
  474. //
  475. //--
  476. #define _ALTPERM_BITMAP_MASK ((MM_MAX_WOW64_ADDRESS - 1) >> PTI_SHIFT)
  477. #if defined(_MIALT4K_)
  478. extern PVOID MiMaxWow64Pte;
  479. #define MI_SET_VALID_PTE_BITS(OUTPTE,PMASK,PPTE) { \
  480. PWOW64_PROCESS _Wow64Process; \
  481. if ((PPTE >= (PMMPTE)PTE_UBASE) && (PPTE < (PMMPTE)MiMaxWow64Pte)) { \
  482. _Wow64Process = PsGetCurrentProcess()->Wow64Process; \
  483. if (_Wow64Process != NULL) { \
  484. if (MI_CHECK_BIT(_Wow64Process->AltPermBitmap, \
  485. ((ULONG_PTR)PPTE >> PTE_SHIFT) & _ALTPERM_BITMAP_MASK) != 0) { \
  486. (OUTPTE).u.Long |= (MmProtectToPteMaskForSplit[PMASK]); \
  487. } \
  488. else { \
  489. (OUTPTE).u.Long |= (MmProtectToPteMaskForIA32[PMASK]); \
  490. (OUTPTE).u.Hard.Accessed = 1; \
  491. } \
  492. } \
  493. else { \
  494. (OUTPTE).u.Hard.Accessed = 1; \
  495. (OUTPTE).u.Long |= (MmProtectToPteMask[PMASK]); \
  496. } \
  497. } \
  498. else { \
  499. (OUTPTE).u.Hard.Accessed = 1; \
  500. (OUTPTE).u.Long |= (MmProtectToPteMask[PMASK]); \
  501. } \
  502. }
  503. #else
  504. #define MI_SET_VALID_PTE_BITS(OUTPTE,PMASK,PPTE) { \
  505. (OUTPTE).u.Hard.Accessed = 1; \
  506. (OUTPTE).u.Long |= (MmProtectToPteMask[PMASK]);
  507. }
  508. #endif
  509. #define MI_MAKE_VALID_PTE(OUTPTE,FRAME,PMASK,PPTE) \
  510. (OUTPTE).u.Long = 0; \
  511. (OUTPTE).u.Hard.Valid = 1; \
  512. (OUTPTE).u.Hard.Cache = MM_PTE_CACHE_ENABLED; \
  513. (OUTPTE).u.Hard.Exception = 1; \
  514. (OUTPTE).u.Hard.PageFrameNumber = FRAME; \
  515. (OUTPTE).u.Hard.Owner = MI_DETERMINE_OWNER(PPTE); \
  516. MI_SET_VALID_PTE_BITS(OUTPTE,PMASK,PPTE)
  517. //++
  518. //VOID
  519. //MI_MAKE_VALID_PTE_TRANSITION (
  520. // IN OUT OUTPTE
  521. // IN PROTECT
  522. // );
  523. //
  524. // Routine Description:
  525. //
  526. // This macro takes a valid PTE and turns it into a transition PTE.
  527. //
  528. // Arguments:
  529. //
  530. // OUTPTE - Supplies the current valid PTE. This PTE is then
  531. // modified into a transition PTE.
  532. //
  533. // PROTECT - Supplies the protection to set in the transition PTE.
  534. //
  535. // Return Value:
  536. //
  537. // None.
  538. //
  539. //--
  540. #define MI_MAKE_VALID_PTE_TRANSITION(OUTPTE,PROTECT) \
  541. (OUTPTE).u.Soft.Transition = 1; \
  542. (OUTPTE).u.Soft.Valid = 0; \
  543. (OUTPTE).u.Soft.Prototype = 0; \
  544. (OUTPTE).u.Soft.Protection = PROTECT;
  545. //++
  546. //VOID
  547. //MI_MAKE_TRANSITION_PTE (
  548. // OUT OUTPTE,
  549. // IN PAGE,
  550. // IN PROTECT,
  551. // IN PPTE
  552. // );
  553. //
  554. // Routine Description:
  555. //
  556. // This macro takes a valid PTE and turns it into a transition PTE.
  557. //
  558. // Arguments:
  559. //
  560. // OUTPTE - Supplies the PTE in which to build the transition PTE.
  561. //
  562. // PAGE - Supplies the page frame number for the PTE.
  563. //
  564. // PROTECT - Supplies the protection to set in the transition PTE.
  565. //
  566. // PPTE - Supplies a pointer to the PTE, this is used to determine
  567. // the owner of the PTE.
  568. //
  569. // Return Value:
  570. //
  571. // None.
  572. //
  573. //--
  574. #define MI_MAKE_TRANSITION_PTE(OUTPTE,PAGE,PROTECT,PPTE) \
  575. (OUTPTE).u.Long = 0; \
  576. (OUTPTE).u.Trans.PageFrameNumber = PAGE; \
  577. (OUTPTE).u.Trans.Transition = 1; \
  578. (OUTPTE).u.Trans.Protection = PROTECT;
  579. //++
  580. //VOID
  581. //MI_MAKE_TRANSITION_PTE_VALID (
  582. // OUT OUTPTE,
  583. // IN PPTE
  584. // );
  585. //
  586. // Routine Description:
  587. //
  588. // This macro takes a transition PTE and makes it a valid PTE.
  589. //
  590. // Arguments:
  591. //
  592. // OUTPTE - Supplies the PTE in which to build the valid PTE.
  593. //
  594. // PPTE - Supplies a pointer to the transition PTE.
  595. //
  596. // Return Value:
  597. //
  598. // None.
  599. //
  600. //--
  601. #define MI_MAKE_TRANSITION_PTE_VALID(OUTPTE,PPTE) { \
  602. ASSERT (((PPTE)->u.Hard.Valid == 0) && \
  603. ((PPTE)->u.Trans.Prototype == 0) && \
  604. ((PPTE)->u.Trans.Transition == 1)); \
  605. (OUTPTE).u.Long = (PPTE)->u.Long & 0x1FFFFFFFE000; \
  606. (OUTPTE).u.Hard.Valid = 1; \
  607. (OUTPTE).u.Hard.Cache = MM_PTE_CACHE_ENABLED; \
  608. (OUTPTE).u.Hard.Exception = 1; \
  609. (OUTPTE).u.Hard.Owner = MI_DETERMINE_OWNER(PPTE); \
  610. MI_SET_VALID_PTE_BITS(OUTPTE,(PPTE)->u.Trans.Protection,PPTE) \
  611. }
  612. #define MI_FAULT_STATUS_INDICATES_EXECUTION(_FaultStatus) (_FaultStatus & 0x2)
  613. #define MI_FAULT_STATUS_INDICATES_WRITE(_FaultStatus) (_FaultStatus & 0x1)
  614. #define MI_CLEAR_FAULT_STATUS(_FaultStatus) (_FaultStatus = 0)
  615. #define MI_IS_PTE_EXECUTABLE(_TempPte) ((_TempPte)->u.Hard.Execute != 0)
  616. //++
  617. //VOID
  618. //MI_SET_PTE_IN_WORKING_SET (
  619. // OUT PMMPTE PTE,
  620. // IN ULONG WSINDEX
  621. // );
  622. //
  623. // Routine Description:
  624. //
  625. // This macro inserts the specified working set index into the argument PTE.
  626. //
  627. // No TB invalidation is needed for other processors (or this one) even
  628. // though the entry may already be in a TB - it's just a software field
  629. // update and doesn't affect miss resolution.
  630. //
  631. // Arguments
  632. //
  633. // OUTPTE - Supplies the PTE in which to insert the working set index.
  634. //
  635. // WSINDEX - Supplies the working set index for the PTE.
  636. //
  637. // Return Value:
  638. //
  639. // None.
  640. //
  641. //--
  642. #define MI_SET_PTE_IN_WORKING_SET(PTE, WSINDEX) { \
  643. MMPTE _TempPte; \
  644. _TempPte = *(PTE); \
  645. _TempPte.u.Hard.SoftwareWsIndex = (WSINDEX); \
  646. *(PTE) = _TempPte; \
  647. }
  648. //++
  649. //ULONG WsIndex
  650. //MI_GET_WORKING_SET_FROM_PTE(
  651. // IN PMMPTE PTE
  652. // );
  653. //
  654. // Routine Description:
  655. //
  656. // This macro returns the working set index from the argument PTE.
  657. //
  658. // Arguments
  659. //
  660. // PTE - Supplies the PTE to extract the working set index from.
  661. //
  662. // Return Value:
  663. //
  664. // This macro returns the working set index for the argument PTE.
  665. //
  666. //--
  667. #define MI_GET_WORKING_SET_FROM_PTE(PTE) (ULONG)(PTE)->u.Hard.SoftwareWsIndex
  668. extern BOOLEAN MiWriteCombiningPtes;
  669. //++
  670. //VOID
  671. //MI_SET_PTE_WRITE_COMBINE (
  672. // IN MMPTE PTE
  673. // );
  674. //
  675. // Routine Description:
  676. //
  677. // This macro sets the write combined bit(s) in the specified PTE.
  678. //
  679. // Arguments
  680. //
  681. // PTE - Supplies the PTE to set dirty.
  682. //
  683. // Return Value:
  684. //
  685. // None.
  686. //
  687. //--
  688. #define MI_SET_PTE_WRITE_COMBINE(PTE) \
  689. ((PTE).u.Hard.Cache = MM_PTE_CACHE_DISABLED)
  690. #define MI_SET_PTE_WRITE_COMBINE2(PTE) \
  691. if (MiWriteCombiningPtes == TRUE) { \
  692. (PTE).u.Hard.Cache = MM_PTE_CACHE_DISPLAY; \
  693. } \
  694. else { \
  695. (PTE).u.Hard.Cache = MM_PTE_CACHE_DISABLED; \
  696. }
  697. //++
  698. //VOID
  699. //MI_PREPARE_FOR_NONCACHED (
  700. // IN MI_PFN_CACHE_ATTRIBUTE CacheAttribute
  701. // );
  702. //
  703. // Routine Description:
  704. //
  705. // This macro prepares the system prior to noncached PTEs being created.
  706. //
  707. // Note the entire TB must be flushed on all processors because there may
  708. // be stale system PTE (or hyperspace or zeropage) mappings in the TB which
  709. // may refer to the same physical page but with a different cache attribute.
  710. //
  711. // Arguments
  712. //
  713. // CacheAttribute - Supplies the cache attribute the PTEs will be filled
  714. // with.
  715. //
  716. // Return Value:
  717. //
  718. // None.
  719. //
  720. //--
  721. #define MI_PREPARE_FOR_NONCACHED(_CacheAttribute) \
  722. if (_CacheAttribute != MiCached) { \
  723. KeFlushEntireTb(FALSE, TRUE); \
  724. }
  725. //++
  726. //VOID
  727. //MI_SWEEP_CACHE (
  728. // IN MI_PFN_CACHE_ATTRIBUTE CacheAttribute,
  729. // IN PVOID StartVa,
  730. // IN ULONG NumberOfBytes
  731. // );
  732. //
  733. // Routine Description:
  734. //
  735. // This macro prepares the system prior to noncached PTEs being created.
  736. //
  737. // Arguments
  738. //
  739. // CacheAttribute - Supplies the cache attribute the PTEs were filled with.
  740. //
  741. // StartVa - Supplies the starting address that's been mapped.
  742. //
  743. // NumberOfBytes - Supplies the number of bytes that have been mapped.
  744. //
  745. // Return Value:
  746. //
  747. // None.
  748. //
  749. //--
  750. #define MI_SWEEP_CACHE(_CacheAttribute,_StartVa,_NumberOfBytes) \
  751. if (_CacheAttribute != MiCached) { \
  752. MiSweepCacheMachineDependent (_StartVa, \
  753. _NumberOfBytes, \
  754. (ULONG)(_CacheAttribute)); \
  755. }
  756. LOGICAL
  757. MiPageFrameIndexMustBeCached (
  758. IN PFN_NUMBER PageFrameIndex
  759. );
  760. #define MI_PAGE_FRAME_INDEX_MUST_BE_CACHED(PageFrameIndex) \
  761. MiPageFrameIndexMustBeCached(PageFrameIndex)
  762. //++
  763. //VOID
  764. //MI_SET_PTE_DIRTY (
  765. // IN MMPTE PTE
  766. // );
  767. //
  768. // Routine Description:
  769. //
  770. // This macro sets the dirty bit(s) in the specified PTE.
  771. //
  772. // Arguments:
  773. //
  774. // PTE - Supplies the PTE to set dirty.
  775. //
  776. // Return Value:
  777. //
  778. // None.
  779. //
  780. //--
  781. #define MI_SET_PTE_DIRTY(PTE) (PTE).u.Hard.Dirty = 1
  782. //++
  783. //VOID
  784. //MI_SET_PTE_CLEAN (
  785. // IN MMPTE PTE
  786. // );
  787. //
  788. // Routine Description:
  789. //
  790. // This macro clears the dirty bit(s) in the specified PTE.
  791. //
  792. // Arguments:
  793. //
  794. // PTE - Supplies the PTE to set clear.
  795. //
  796. // Return Value:
  797. //
  798. // None.
  799. //
  800. //--
  801. #define MI_SET_PTE_CLEAN(PTE) (PTE).u.Hard.Dirty = 0
  802. //++
  803. //VOID
  804. //MI_IS_PTE_DIRTY (
  805. // IN MMPTE PTE
  806. // );
  807. //
  808. // Routine Description:
  809. //
  810. // This macro checks the dirty bit(s) in the specified PTE.
  811. //
  812. // Arguments:
  813. //
  814. // PTE - Supplies the PTE to check.
  815. //
  816. // Return Value:
  817. //
  818. // TRUE if the page is dirty (modified), FALSE otherwise.
  819. //
  820. //--
  821. #define MI_IS_PTE_DIRTY(PTE) ((PTE).u.Hard.Dirty != 0)
  822. //++
  823. //VOID
  824. //MI_SET_GLOBAL_BIT_IF_SYSTEM (
  825. // OUT OUTPTE,
  826. // IN PPTE
  827. // );
  828. //
  829. // Routine Description:
  830. //
  831. // This macro sets the global bit if the pointer PTE is within
  832. // system space.
  833. //
  834. // Arguments:
  835. //
  836. // OUTPTE - Supplies the PTE in which to build the valid PTE.
  837. //
  838. // PPTE - Supplies a pointer to the PTE becoming valid.
  839. //
  840. // Return Value:
  841. //
  842. // None.
  843. //
  844. //--
  845. #define MI_SET_GLOBAL_BIT_IF_SYSTEM(OUTPTE,PPTE)
  846. //++
  847. //VOID
  848. //MI_SET_GLOBAL_STATE (
  849. // IN MMPTE PTE,
  850. // IN ULONG STATE
  851. // );
  852. //
  853. // Routine Description:
  854. //
  855. // This macro sets the global bit in the PTE. if the pointer PTE is within
  856. //
  857. // Arguments:
  858. //
  859. // PTE - Supplies the PTE to set global state into.
  860. //
  861. // STATE - Supplies 1 if global, 0 if not.
  862. //
  863. // Return Value:
  864. //
  865. // None.
  866. //
  867. //--
  868. #define MI_SET_GLOBAL_STATE(PTE,STATE)
  869. //++
  870. //VOID
  871. //MI_ENABLE_CACHING (
  872. // IN MMPTE PTE
  873. // );
  874. //
  875. // Routine Description:
  876. //
  877. // This macro takes a valid PTE and sets the caching state to be
  878. // enabled.
  879. //
  880. // Arguments:
  881. //
  882. // PTE - Supplies a valid PTE.
  883. //
  884. // Return Value:
  885. //
  886. // None.
  887. //
  888. //--
  889. #define MI_ENABLE_CACHING(PTE) ((PTE).u.Hard.Cache = MM_PTE_CACHE_ENABLED)
  890. //++
  891. //VOID
  892. //MI_DISABLE_CACHING (
  893. // IN MMPTE PTE
  894. // );
  895. //
  896. // Routine Description:
  897. //
  898. // This macro takes a valid PTE and sets the caching state to be
  899. // disabled.
  900. //
  901. // Arguments:
  902. //
  903. // PTE - Supplies a pointer to the valid PTE.
  904. //
  905. // Return Value:
  906. //
  907. // None.
  908. //
  909. //--
  910. #define MI_DISABLE_CACHING(PTE) ((PTE).u.Hard.Cache = MM_PTE_CACHE_DISABLED)
  911. //++
  912. //BOOLEAN
  913. //MI_IS_CACHING_DISABLED (
  914. // IN PMMPTE PPTE
  915. // );
  916. //
  917. // Routine Description:
  918. //
  919. // This macro takes a valid PTE and returns TRUE if caching is
  920. // disabled.
  921. //
  922. // Arguments:
  923. //
  924. // PPTE - Supplies a pointer to the valid PTE.
  925. //
  926. // Return Value:
  927. //
  928. // TRUE if caching is disabled, FALSE if it is enabled.
  929. //
  930. //--
  931. #define MI_IS_CACHING_DISABLED(PPTE) \
  932. ((PPTE)->u.Hard.Cache == MM_PTE_CACHE_DISABLED)
  933. //++
  934. //VOID
  935. //MI_SET_PFN_DELETED (
  936. // IN PMMPFN PPFN
  937. // );
  938. //
  939. // Routine Description:
  940. //
  941. // This macro takes a pointer to a PFN element and indicates that
  942. // the PFN is no longer in use.
  943. //
  944. // Arguments:
  945. //
  946. // PPTE - Supplies a pointer to the PFN element.
  947. //
  948. // Return Value:
  949. //
  950. // none.
  951. //
  952. //--
  953. #define MI_SET_PFN_DELETED(PPFN) \
  954. (PPFN)->PteAddress = (PMMPTE)((ULONG_PTR)PPFN->PteAddress | 0x1);
  955. //++
  956. //VOID
  957. //MI_MARK_PFN_UNDELETED (
  958. // IN PMMPFN PPFN
  959. // );
  960. //
  961. // Routine Description:
  962. //
  963. // This macro takes a pointer to a deleted PFN element and mark that
  964. // the PFN is not deleted.
  965. //
  966. // Arguments
  967. //
  968. // PPTE - Supplies a pointer to the PFN element.
  969. //
  970. // Return Value:
  971. //
  972. // none.
  973. //
  974. //--
  975. #define MI_MARK_PFN_UNDELETED(PPFN) \
  976. PPFN->PteAddress = (PMMPTE)((ULONG_PTR)PPFN->PteAddress & ~0x1);
  977. //++
  978. //BOOLEAN
  979. //MI_IS_PFN_DELETED (
  980. // IN PMMPFN PPFN
  981. // );
  982. //
  983. // Routine Description:
  984. //
  985. // This macro takes a pointer to a PFN element and determines if
  986. // the PFN is no longer in use.
  987. //
  988. // Arguments:
  989. //
  990. // PPTE - Supplies a pointer to the PFN element.
  991. //
  992. // Return Value:
  993. //
  994. // TRUE if PFN is no longer used, FALSE if it is still being used.
  995. //
  996. //--
  997. #define MI_IS_PFN_DELETED(PPFN) \
  998. ((ULONG_PTR)(PPFN)->PteAddress & 0x1)
  999. //++
  1000. //VOID
  1001. //MI_CHECK_PAGE_ALIGNMENT (
  1002. // IN ULONG PAGE,
  1003. // IN PMMPTE PPTE
  1004. // );
  1005. //
  1006. // Routine Description:
  1007. //
  1008. // This macro takes a PFN element number (Page) and checks to see
  1009. // if the virtual alignment for the previous address of the page
  1010. // is compatable with the new address of the page. If they are
  1011. // not compatible, the D cache is flushed.
  1012. //
  1013. // Arguments:
  1014. //
  1015. // PAGE - Supplies the PFN element.
  1016. // PPTE - Supplies a pointer to the new PTE which will contain the page.
  1017. //
  1018. // Return Value:
  1019. //
  1020. // none.
  1021. //
  1022. //--
  1023. // does nothing on IA64.
  1024. #define MI_CHECK_PAGE_ALIGNMENT(PAGE,PPTE)
  1025. //++
  1026. //VOID
  1027. //MI_INITIALIZE_HYPERSPACE_MAP (
  1028. // VOID
  1029. // );
  1030. //
  1031. // Routine Description:
  1032. //
  1033. // This macro initializes the PTEs reserved for double mapping within
  1034. // hyperspace.
  1035. //
  1036. // Arguments:
  1037. //
  1038. // None.
  1039. //
  1040. // Return Value:
  1041. //
  1042. // None.
  1043. //
  1044. //--
  1045. // does nothing on IA64.
  1046. #define MI_INITIALIZE_HYPERSPACE_MAP(INDEX)
  1047. //++
  1048. //ULONG
  1049. //MI_GET_PAGE_COLOR_FROM_PTE (
  1050. // IN PMMPTE PTEADDRESS
  1051. // );
  1052. //
  1053. // Routine Description:
  1054. //
  1055. // This macro determines the pages color based on the PTE address
  1056. // that maps the page.
  1057. //
  1058. // Arguments:
  1059. //
  1060. // PTEADDRESS - Supplies the PTE address the page is (or was) mapped at.
  1061. //
  1062. // Return Value:
  1063. //
  1064. // The pages color.
  1065. //
  1066. //--
  1067. #define MI_GET_PAGE_COLOR_FROM_PTE(PTEADDRESS) \
  1068. (((ULONG)((MI_SYSTEM_PAGE_COLOR++) & MmSecondaryColorMask)) | MI_CURRENT_NODE_COLOR)
  1069. //++
  1070. //ULONG
  1071. //MI_GET_PAGE_COLOR_FROM_VA (
  1072. // IN PVOID ADDRESS
  1073. // );
  1074. //
  1075. // Routine Description:
  1076. //
  1077. // This macro determines the pages color based on the PTE address
  1078. // that maps the page.
  1079. //
  1080. // Arguments:
  1081. //
  1082. // ADDRESS - Supplies the address the page is (or was) mapped at.
  1083. //
  1084. // Return Value:
  1085. //
  1086. // The pages color.
  1087. //
  1088. //--
  1089. #define MI_GET_PAGE_COLOR_FROM_VA(ADDRESS) \
  1090. (((ULONG)((MI_SYSTEM_PAGE_COLOR++) & MmSecondaryColorMask)) | MI_CURRENT_NODE_COLOR)
  1091. //++
  1092. //ULONG
  1093. //MI_GET_PAGE_COLOR_FROM_SESSION (
  1094. // IN PMM_SESSION_SPACE SessionSpace
  1095. // );
  1096. //
  1097. // Routine Description:
  1098. //
  1099. // This macro determines the page's color based on the PTE address
  1100. // that maps the page.
  1101. //
  1102. // Arguments
  1103. //
  1104. // SessionSpace - Supplies the session space the page will be mapped into.
  1105. //
  1106. // Return Value:
  1107. //
  1108. // The page's color.
  1109. //
  1110. //--
  1111. #define MI_GET_PAGE_COLOR_FROM_SESSION(_SessionSpace) \
  1112. (((ULONG)((_SessionSpace->Color++) & MmSecondaryColorMask)) | MI_CURRENT_NODE_COLOR)
  1113. //++
  1114. //ULONG
  1115. //MI_PAGE_COLOR_PTE_PROCESS (
  1116. // IN PMMPTE PTE,
  1117. // IN PUSHORT COLOR
  1118. // );
  1119. //
  1120. // Routine Description:
  1121. //
  1122. // Select page color for this process.
  1123. //
  1124. // Arguments
  1125. //
  1126. // PTE Not used.
  1127. // COLOR Value from which color is determined. This
  1128. // variable is incremented.
  1129. //
  1130. // Return Value:
  1131. //
  1132. // Page color.
  1133. //
  1134. //--
  1135. #define MI_PAGE_COLOR_PTE_PROCESS(PTE,COLOR) \
  1136. (((ULONG)((*(COLOR))++) & MmSecondaryColorMask) | MI_CURRENT_NODE_COLOR)
  1137. //++
  1138. //ULONG
  1139. //MI_PAGE_COLOR_VA_PROCESS (
  1140. // IN PVOID ADDRESS,
  1141. // IN PEPROCESS COLOR
  1142. // );
  1143. //
  1144. // Routine Description:
  1145. //
  1146. // This macro determines the pages color based on the PTE address
  1147. // that maps the page.
  1148. //
  1149. // Arguments:
  1150. //
  1151. // ADDRESS - Supplies the address the page is (or was) mapped at.
  1152. //
  1153. // Return Value:
  1154. //
  1155. // The pages color.
  1156. //
  1157. //--
  1158. #define MI_PAGE_COLOR_VA_PROCESS(ADDRESS,COLOR) \
  1159. (((ULONG)((*(COLOR))++) & MmSecondaryColorMask) | MI_CURRENT_NODE_COLOR)
  1160. //++
  1161. //ULONG
  1162. //MI_GET_NEXT_COLOR (
  1163. // IN ULONG COLOR
  1164. // );
  1165. //
  1166. // Routine Description:
  1167. //
  1168. // This macro returns the next color in the sequence.
  1169. //
  1170. // Arguments:
  1171. //
  1172. // COLOR - Supplies the color to return the next of.
  1173. //
  1174. // Return Value:
  1175. //
  1176. // Next color in sequence.
  1177. //
  1178. //--
  1179. #define MI_GET_NEXT_COLOR(COLOR) ((COLOR + 1) & MM_COLOR_MASK)
  1180. //++
  1181. //ULONG
  1182. //MI_GET_PREVIOUS_COLOR (
  1183. // IN ULONG COLOR
  1184. // );
  1185. //
  1186. // Routine Description:
  1187. //
  1188. // This macro returns the previous color in the sequence.
  1189. //
  1190. // Arguments:
  1191. //
  1192. // COLOR - Supplies the color to return the previous of.
  1193. //
  1194. // Return Value:
  1195. //
  1196. // Previous color in sequence.
  1197. //
  1198. //--
  1199. #define MI_GET_PREVIOUS_COLOR(COLOR) (0)
  1200. #define MI_GET_SECONDARY_COLOR(PAGE,PFN) (PAGE & MmSecondaryColorMask)
  1201. #define MI_GET_COLOR_FROM_SECONDARY(SECONDARY_COLOR) (0)
  1202. //++
  1203. //VOID
  1204. //MI_GET_MODIFIED_PAGE_BY_COLOR (
  1205. // OUT ULONG PAGE,
  1206. // IN ULONG COLOR
  1207. // );
  1208. //
  1209. // Routine Description:
  1210. //
  1211. // This macro returns the first page destined for a paging
  1212. // file with the desired color. It does NOT remove the page
  1213. // from its list.
  1214. //
  1215. // Arguments:
  1216. //
  1217. // PAGE - Returns the page located, the value MM_EMPTY_LIST is
  1218. // returned if there is no page of the specified color.
  1219. //
  1220. // COLOR - Supplies the color of page to locate.
  1221. //
  1222. // Return Value:
  1223. //
  1224. // none.
  1225. //
  1226. //--
  1227. #define MI_GET_MODIFIED_PAGE_BY_COLOR(PAGE,COLOR) \
  1228. PAGE = MmModifiedPageListByColor[COLOR].Flink
  1229. //++
  1230. //VOID
  1231. //MI_GET_MODIFIED_PAGE_ANY_COLOR (
  1232. // OUT ULONG PAGE,
  1233. // IN OUT ULONG COLOR
  1234. // );
  1235. //
  1236. // Routine Description:
  1237. //
  1238. // This macro returns the first page destined for a paging
  1239. // file with the desired color. If not page of the desired
  1240. // color exists, all colored lists are searched for a page.
  1241. // It does NOT remove the page from its list.
  1242. //
  1243. // Arguments:
  1244. //
  1245. // PAGE - Returns the page located, the value MM_EMPTY_LIST is
  1246. // returned if there is no page of the specified color.
  1247. //
  1248. // COLOR - Supplies the color of page to locate and returns the
  1249. // color of the page located.
  1250. //
  1251. // Return Value:
  1252. //
  1253. // none.
  1254. //
  1255. //--
  1256. #define MI_GET_MODIFIED_PAGE_ANY_COLOR(PAGE,COLOR) \
  1257. { \
  1258. if (MmTotalPagesForPagingFile == 0) { \
  1259. PAGE = MM_EMPTY_LIST; \
  1260. } else { \
  1261. PAGE = MmModifiedPageListByColor[COLOR].Flink; \
  1262. } \
  1263. }
  1264. //++
  1265. //VOID
  1266. //MI_MAKE_VALID_PTE_WRITE_COPY (
  1267. // IN OUT PMMPTE PTE
  1268. // );
  1269. //
  1270. // Routine Description:
  1271. //
  1272. // This macro checks to see if the PTE indicates that the
  1273. // page is writable and if so it clears the write bit and
  1274. // sets the copy-on-write bit.
  1275. //
  1276. // Arguments:
  1277. //
  1278. // PTE - Supplies the PTE to operate upon.
  1279. //
  1280. // Return Value:
  1281. //
  1282. // None.
  1283. //
  1284. //--
  1285. #define MI_MAKE_VALID_PTE_WRITE_COPY(PPTE) \
  1286. if ((PPTE)->u.Hard.Write == 1) { \
  1287. (PPTE)->u.Hard.CopyOnWrite = 1; \
  1288. (PPTE)->u.Hard.Write = 0; \
  1289. }
  1290. //++
  1291. //ULONG
  1292. //MI_DETERMINE_OWNER (
  1293. // IN MMPTE PPTE
  1294. // );
  1295. //
  1296. // Routine Description:
  1297. //
  1298. // This macro examines the virtual address of the PTE and determines
  1299. // if the PTE resides in system space or user space.
  1300. //
  1301. // Arguments:
  1302. //
  1303. // PTE - Supplies the PTE to operate upon.
  1304. //
  1305. // Return Value:
  1306. //
  1307. // 3 if the owner is USER_MODE, 0 if the owner is KERNEL_MODE.
  1308. //
  1309. //--
  1310. #if defined(_MIALT4K_)
  1311. #define MI_DETERMINE_OWNER(PPTE) \
  1312. ((((((PPTE) >= (PMMPTE)PTE_UBASE) && ((PPTE) <= MiHighestUserPte))) || \
  1313. (MI_IS_ALT_PAGE_TABLE_ADDRESS(PPTE))) ? 3 : 0)
  1314. #else
  1315. #define MI_DETERMINE_OWNER(PPTE) \
  1316. ((((PPTE) >= (PMMPTE)PTE_UBASE) && \
  1317. ((PPTE) <= MiHighestUserPte)) ? 3 : 0)
  1318. #endif
  1319. //++
  1320. //VOID
  1321. //MI_SET_ACCESSED_IN_PTE (
  1322. // IN OUT MMPTE PPTE,
  1323. // IN ULONG ACCESSED
  1324. // );
  1325. //
  1326. // Routine Description:
  1327. //
  1328. // This macro sets the ACCESSED field in the PTE. Note that this must
  1329. // not be cleared in PPEs or PDEs as they are not checked for this in
  1330. // memory management before referencing the hierarchy beneath them.
  1331. //
  1332. // Arguments:
  1333. //
  1334. // PTE - Supplies the PTE to operate upon.
  1335. //
  1336. // Return Value:
  1337. //
  1338. // None.
  1339. //
  1340. //--
  1341. #define MI_SET_ACCESSED_IN_PTE(PPTE,ACCESSED) { \
  1342. PWOW64_PROCESS _Wow64Process; \
  1343. if (ACCESSED == 0) { \
  1344. if (MI_IS_PTE_ADDRESS(PPTE)) { \
  1345. (PPTE)->u.Hard.Accessed = 0; \
  1346. } \
  1347. } \
  1348. else if ((PPTE >= (PMMPTE)PTE_UBASE) && (PPTE < (PMMPTE)MiMaxWow64Pte)) { \
  1349. _Wow64Process = PsGetCurrentProcess()->Wow64Process; \
  1350. if (_Wow64Process != NULL) { \
  1351. if (MI_CHECK_BIT(_Wow64Process->AltPermBitmap, \
  1352. ((ULONG_PTR)PPTE >> PTE_SHIFT) & _ALTPERM_BITMAP_MASK) != 0) { \
  1353. NOTHING; \
  1354. } \
  1355. else { \
  1356. (PPTE)->u.Hard.Accessed = 1; \
  1357. } \
  1358. } \
  1359. else { \
  1360. (PPTE)->u.Hard.Accessed = 1; \
  1361. } \
  1362. } \
  1363. else { \
  1364. (PPTE)->u.Hard.Accessed = 1; \
  1365. } \
  1366. }
  1367. //++
  1368. //ULONG
  1369. //MI_GET_ACCESSED_IN_PTE (
  1370. // IN OUT MMPTE PPTE
  1371. // );
  1372. //
  1373. // Routine Description:
  1374. //
  1375. // This macro returns the state of the ACCESSED field in the PTE.
  1376. //
  1377. // Arguments:
  1378. //
  1379. // PTE - Supplies the PTE to operate upon.
  1380. //
  1381. // Return Value:
  1382. //
  1383. // The state of the ACCESSED field.
  1384. //
  1385. //--
  1386. #define MI_GET_ACCESSED_IN_PTE(PPTE) ((PPTE)->u.Hard.Accessed)
  1387. //++
  1388. //VOID
  1389. //MI_SET_OWNER_IN_PTE (
  1390. // IN PMMPTE PPTE
  1391. // IN ULONG OWNER
  1392. // );
  1393. //
  1394. // Routine Description:
  1395. //
  1396. // This macro sets the owner field in the PTE.
  1397. //
  1398. // Arguments:
  1399. //
  1400. // PTE - Supplies the PTE to operate upon.
  1401. //
  1402. // Return Value:
  1403. //
  1404. // None.
  1405. //
  1406. //--
  1407. #define MI_SET_OWNER_IN_PTE(PPTE,OWNER)
  1408. //++
  1409. //ULONG
  1410. //MI_GET_OWNER_IN_PTE (
  1411. // IN PMMPTE PPTE
  1412. // );
  1413. //
  1414. // Routine Description:
  1415. //
  1416. // This macro gets the owner field from the PTE.
  1417. //
  1418. // Arguments:
  1419. //
  1420. // PTE - Supplies the PTE to operate upon.
  1421. //
  1422. // Return Value:
  1423. //
  1424. // The state of the OWNER field.
  1425. //
  1426. //--
  1427. #define MI_GET_OWNER_IN_PTE(PPTE) KernelMode
  1428. //++
  1429. //VOID
  1430. //MI_SET_PAGING_FILE_INFO (
  1431. // OUT MMPTE OUTPTE,
  1432. // IN MMPTE PPTE,
  1433. // IN ULONG FILEINFO,
  1434. // IN ULONG OFFSET
  1435. // );
  1436. //
  1437. // Routine Description:
  1438. //
  1439. // This macro sets into the specified PTE the supplied information
  1440. // to indicate where the backing store for the page is located.
  1441. //
  1442. // Arguments:
  1443. //
  1444. // OUTPTE - Supplies the PTE in which to store the result.
  1445. //
  1446. // PTE - Supplies the PTE to operate upon.
  1447. //
  1448. // FILEINFO - Supplies the number of the paging file.
  1449. //
  1450. // OFFSET - Supplies the offset into the paging file.
  1451. //
  1452. // Return Value:
  1453. //
  1454. // None.
  1455. //
  1456. //--
  1457. #define MI_SET_PAGING_FILE_INFO(OUTPTE,PTE,FILEINFO,OFFSET) \
  1458. (OUTPTE).u.Long = (((PTE).u.Soft.Protection << MM_PROTECT_FIELD_SHIFT) | \
  1459. ((ULONGLONG)(FILEINFO) << _MM_PAGING_FILE_LOW_SHIFT) | \
  1460. ((ULONGLONG)(OFFSET) << _MM_PAGING_FILE_HIGH_SHIFT));
  1461. //++
  1462. //PMMPTE
  1463. //MiPteToProto (
  1464. // IN OUT MMPTE PPTE,
  1465. // IN ULONG FILEINFO,
  1466. // IN ULONG OFFSET
  1467. // );
  1468. //
  1469. // Routine Description:
  1470. //
  1471. // This macro returns the address of the corresponding prototype which
  1472. // was encoded earlier into the supplied PTE.
  1473. //
  1474. // Arguments:
  1475. //
  1476. // lpte - Supplies the PTE to operate upon.
  1477. //
  1478. // Return Value:
  1479. //
  1480. // Pointer to the prototype PTE that backs this PTE.
  1481. //
  1482. //--
  1483. #define MiPteToProto(lpte) \
  1484. ((PMMPTE) ((ULONG_PTR)((lpte)->u.Proto.ProtoAddress) + MmProtopte_Base))
  1485. //++
  1486. //ULONG_PTR
  1487. //MiProtoAddressForPte (
  1488. // IN PMMPTE proto_va
  1489. // );
  1490. //
  1491. // Routine Description:
  1492. //
  1493. // This macro sets into the specified PTE the supplied information
  1494. // to indicate where the backing store for the page is located.
  1495. // MiProtoAddressForPte returns the bit field to OR into the PTE to
  1496. // reference a prototype PTE.
  1497. //
  1498. // And set the protoPTE MM_PTE_PROTOTYPE_MASK bit.
  1499. //
  1500. // Arguments:
  1501. //
  1502. // proto_va - Supplies the address of the prototype PTE.
  1503. //
  1504. // Return Value:
  1505. //
  1506. // Mask to set into the PTE.
  1507. //
  1508. //--
  1509. #define MiProtoAddressForPte(proto_va) \
  1510. (( (ULONGLONG)((ULONG_PTR)proto_va - MmProtopte_Base) << \
  1511. (_MM_PROTO_ADDRESS_SHIFT)) | MM_PTE_PROTOTYPE_MASK)
  1512. #define MISetProtoAddressForPte(PTE, proto_va) \
  1513. (PTE).u.Long = 0; \
  1514. (PTE).u.Proto.Prototype = 1; \
  1515. (PTE).u.Proto.ProtoAddress = (ULONG_PTR)proto_va - MmProtopte_Base;
  1516. //++
  1517. //ULONG_PTR
  1518. //MiProtoAddressForKernelPte (
  1519. // IN PMMPTE proto_va
  1520. // );
  1521. //
  1522. // Routine Description:
  1523. //
  1524. // This macro sets into the specified PTE the supplied information
  1525. // to indicate where the backing store for the page is located.
  1526. // MiProtoAddressForPte returns the bit field to OR into the PTE to
  1527. // reference a prototype PTE. And set the protoPTE bit,
  1528. // MM_PTE_PROTOTYPE_MASK.
  1529. //
  1530. // This macro also sets any other information (such as global bits)
  1531. // required for kernel mode PTEs.
  1532. //
  1533. // Arguments:
  1534. //
  1535. // proto_va - Supplies the address of the prototype PTE.
  1536. //
  1537. // Return Value:
  1538. //
  1539. // Mask to set into the PTE.
  1540. //
  1541. //--
  1542. // not different on IA64.
  1543. #define MiProtoAddressForKernelPte(proto_va) MiProtoAddressForPte(proto_va)
  1544. #define MM_SUBSECTION_MAP (128*1024*1024)
  1545. //++
  1546. //PSUBSECTION
  1547. //MiGetSubsectionAddress (
  1548. // IN PMMPTE lpte
  1549. // );
  1550. //
  1551. // Routine Description:
  1552. //
  1553. // This macro takes a PTE and returns the address of the subsection that
  1554. // the PTE refers to. Subsections are quadword structures allocated
  1555. // from nonpaged pool.
  1556. //
  1557. // Arguments:
  1558. //
  1559. // lpte - Supplies the PTE to operate upon.
  1560. //
  1561. // Return Value:
  1562. //
  1563. // A pointer to the subsection referred to by the supplied PTE.
  1564. //
  1565. //--
  1566. #define MiGetSubsectionAddress(lpte) \
  1567. (((lpte)->u.Subsect.WhichPool == 1) ? \
  1568. ((PSUBSECTION)((ULONG_PTR)MmSubsectionBase + \
  1569. ((ULONG_PTR)(lpte)->u.Subsect.SubsectionAddress))) \
  1570. : \
  1571. ((PSUBSECTION)((ULONG_PTR)MM_NONPAGED_POOL_END - \
  1572. ((ULONG_PTR)(lpte)->u.Subsect.SubsectionAddress))))
  1573. //++
  1574. //ULONGLONG
  1575. //MiGetSubsectionAddressForPte (
  1576. // IN PSUBSECTION VA
  1577. // );
  1578. //
  1579. // Routine Description:
  1580. //
  1581. // This macro takes the address of a subsection and encodes it for use
  1582. // in a PTE.
  1583. //
  1584. // NOTE - THE SUBSECTION ADDRESS MUST BE QUADWORD ALIGNED!
  1585. //
  1586. // Arguments:
  1587. //
  1588. // VA - Supplies a pointer to the subsection to encode.
  1589. //
  1590. // Return Value:
  1591. //
  1592. // The mask to set into the PTE to make it reference the supplied
  1593. // subsetion.
  1594. //
  1595. //--
  1596. #define MiGetSubsectionAddressForPte(VA) \
  1597. ( ((ULONG_PTR)(VA) < (ULONG_PTR)KSEG2_BASE) ? \
  1598. ( ((ULONGLONG)((ULONG_PTR)VA - (ULONG_PTR)MmSubsectionBase) \
  1599. << (_MM_PTE_SUBSECTION_ADDRESS_SHIFT)) | 0x80) \
  1600. : \
  1601. ((ULONGLONG)((ULONG_PTR)MM_NONPAGED_POOL_END - (ULONG_PTR)VA) \
  1602. << (_MM_PTE_SUBSECTION_ADDRESS_SHIFT)) )
  1603. //++
  1604. //ULONG
  1605. //MiGetPpeOffset (
  1606. // IN PVOID va
  1607. // );
  1608. //
  1609. // Routine Description:
  1610. //
  1611. // MiGetPpeOffset returns the offset into a page directory parent for a
  1612. // given virtual address.
  1613. //
  1614. // Arguments
  1615. //
  1616. // Va - Supplies the virtual address to locate the offset for.
  1617. //
  1618. // Return Value:
  1619. //
  1620. // The offset into the page root table the corresponding PPE is at.
  1621. //
  1622. //--
  1623. #define MiGetPpeOffset(va) \
  1624. ((((ULONG_PTR)(va) & PDE_TBASE) == PDE_TBASE) ? \
  1625. ((PDE_SELFMAP & ((sizeof(MMPTE)*PTE_PER_PAGE) - 1))/sizeof(MMPTE)) : \
  1626. ((ULONG)(((ULONG_PTR)(va) >> PDI1_SHIFT) & PDI_MASK)))
  1627. //++
  1628. //ULONG
  1629. //MiGetPpeIndex (
  1630. // IN PVOID va
  1631. // );
  1632. //
  1633. // Routine Description:
  1634. //
  1635. // MiGetPpeIndex returns the page directory parent index
  1636. // for a given virtual address.
  1637. //
  1638. // N.B. This does not mask off PXE bits.
  1639. //
  1640. // Arguments
  1641. //
  1642. // Va - Supplies the virtual address to locate the index for.
  1643. //
  1644. // Return Value:
  1645. //
  1646. // The index into the page directory parent - ie: the virtual page directory
  1647. // number. This is different from the page directory parent offset because
  1648. // this spans page directory parents on supported platforms.
  1649. //
  1650. // N.B. This macro only works on user addresses - the region ID bits
  1651. // are not masked off !
  1652. //--
  1653. #define MiGetPpeIndex(va) ((ULONG)((ULONG_PTR)(va) >> PDI1_SHIFT))
  1654. //++
  1655. //ULONG_PTR
  1656. //MiGetPdeOffset (
  1657. // IN PVOID va
  1658. // );
  1659. //
  1660. // Routine Description:
  1661. //
  1662. // MiGetPdeOffset returns the offset into a page directory
  1663. // for a given virtual address.
  1664. //
  1665. // Arguments:
  1666. //
  1667. // Va - Supplies the virtual address to locate the offset for.
  1668. //
  1669. // Return Value:
  1670. //
  1671. // The offset into the page directory table the corresponding PDE is at.
  1672. //
  1673. //--
  1674. #define MiGetPdeOffset(va) ((ULONG) (((ULONG_PTR)(va) >> PDI_SHIFT) & PDI_MASK))
  1675. //++
  1676. //ULONG
  1677. //MiGetPdeIndex (
  1678. // IN PVOID va
  1679. // );
  1680. //
  1681. // Routine Description:
  1682. //
  1683. // MiGetPdeIndex returns the page directory index
  1684. // for a given virtual address.
  1685. //
  1686. // N.B. This does not mask off PPE bits.
  1687. //
  1688. // Arguments
  1689. //
  1690. // Va - Supplies the virtual address to locate the index for.
  1691. //
  1692. // Return Value:
  1693. //
  1694. // The index into the page directory - ie: the virtual page table number.
  1695. // This is different from the page directory offset because this spans
  1696. // page directories on supported platforms.
  1697. //
  1698. // N.B. This macro only works on user addresses - the region ID bits
  1699. // are not masked off !
  1700. //
  1701. //--
  1702. #define MiGetPdeIndex(va) ((ULONG) ((ULONG_PTR)(va) >> PDI_SHIFT))
  1703. //++
  1704. //ULONG_PTR
  1705. //MiGetPteOffset (
  1706. // IN PVOID va
  1707. // );
  1708. //
  1709. // Routine Description:
  1710. //
  1711. // MiGetPteOffset returns the offset into a page table page
  1712. // for a given virtual address.
  1713. //
  1714. // Arguments:
  1715. //
  1716. // Va - Supplies the virtual address to locate the offset for.
  1717. //
  1718. // Return Value:
  1719. //
  1720. // The offset into the page table page table the corresponding PTE is at.
  1721. //
  1722. //--
  1723. #define MiGetPteOffset(va) ((ULONG) (((ULONG_PTR)(va) >> PTI_SHIFT) & PDI_MASK))
  1724. //++
  1725. //++
  1726. //PVOID
  1727. //MiGetVirtualAddressMappedByPpe (
  1728. // IN PMMPTE PTE
  1729. // );
  1730. //
  1731. // Routine Description:
  1732. //
  1733. // MiGetVirtualAddressMappedByPpe returns the virtual address
  1734. // which is mapped by a given PPE address.
  1735. //
  1736. // Arguments
  1737. //
  1738. // PPE - Supplies the PPE to get the virtual address for.
  1739. //
  1740. // Return Value:
  1741. //
  1742. // Virtual address mapped by the PPE.
  1743. //
  1744. //--
  1745. #define MiGetVirtualAddressMappedByPpe(PPE) \
  1746. MiGetVirtualAddressMappedByPte(MiGetVirtualAddressMappedByPde(PPE))
  1747. //++
  1748. //PVOID
  1749. //MiGetVirtualAddressMappedByPde (
  1750. // IN PMMPTE PDE
  1751. // );
  1752. //
  1753. // Routine Description:
  1754. //
  1755. // MiGetVirtualAddressMappedByPde returns the virtual address
  1756. // which is mapped by a given PDE address.
  1757. //
  1758. // Arguments
  1759. //
  1760. // PDE - Supplies the PDE to get the virtual address for.
  1761. //
  1762. // Return Value:
  1763. //
  1764. // Virtual address mapped by the PDE.
  1765. //
  1766. //--
  1767. #define MiGetVirtualAddressMappedByPde(Pde) \
  1768. MiGetVirtualAddressMappedByPte(MiGetVirtualAddressMappedByPte(Pde))
  1769. //++
  1770. //PVOID
  1771. //MiGetVirtualAddressMappedByPte (
  1772. // IN PMMPTE PTE
  1773. // );
  1774. //
  1775. // Routine Description:
  1776. //
  1777. // MiGetVirtualAddressMappedByPte returns the virtual address
  1778. // which is mapped by a given PTE address.
  1779. //
  1780. // Arguments:
  1781. //
  1782. // PTE - Supplies the PTE to get the virtual address for.
  1783. //
  1784. // Return Value:
  1785. //
  1786. // Virtual address mapped by the PTE.
  1787. //
  1788. //--
  1789. #define MiGetVirtualAddressMappedByPte(PTE) \
  1790. (((ULONG_PTR)(PTE) & PTA_SIGN) ? \
  1791. (PVOID)(((ULONG_PTR)(PTE) & VRN_MASK) | VA_FILL | \
  1792. (((ULONG_PTR)(PTE)-PTE_BASE) << (PAGE_SHIFT - PTE_SHIFT))) : \
  1793. (PVOID)(((ULONG_PTR)(PTE) & VRN_MASK) | (((ULONG_PTR)(PTE)-PTE_BASE) << (PAGE_SHIFT - PTE_SHIFT))))
  1794. //++
  1795. //LOGICAL
  1796. //MiIsVirtualAddressOnPpeBoundary (
  1797. // IN PVOID VA
  1798. // );
  1799. //
  1800. // Routine Description:
  1801. //
  1802. // MiIsVirtualAddressOnPpeBoundary returns TRUE if the virtual address is
  1803. // on a page directory entry boundary.
  1804. //
  1805. // Arguments
  1806. //
  1807. // VA - Supplies the virtual address to check.
  1808. //
  1809. // Return Value:
  1810. //
  1811. // TRUE if on a boundary, FALSE if not.
  1812. //
  1813. //--
  1814. #define MiIsVirtualAddressOnPpeBoundary(VA) (((ULONG_PTR)(VA) & PAGE_DIRECTORY1_MASK) == 0)
  1815. //++
  1816. //LOGICAL
  1817. //MiIsVirtualAddressOnPdeBoundary (
  1818. // IN PVOID VA
  1819. // );
  1820. //
  1821. // Routine Description:
  1822. //
  1823. // MiIsVirtualAddressOnPdeBoundary returns TRUE if the virtual address is
  1824. // on a page directory entry boundary.
  1825. //
  1826. // Arguments
  1827. //
  1828. // VA - Supplies the virtual address to check.
  1829. //
  1830. // Return Value:
  1831. //
  1832. // TRUE if on an 8MB PDE boundary, FALSE if not.
  1833. //
  1834. //--
  1835. #define MiIsVirtualAddressOnPdeBoundary(VA) (((ULONG_PTR)(VA) & PAGE_DIRECTORY2_MASK) == 0)
  1836. //++
  1837. //LOGICAL
  1838. //MiIsPteOnPpeBoundary (
  1839. // IN PVOID VA
  1840. // );
  1841. //
  1842. // Routine Description:
  1843. //
  1844. // MiIsPteOnPpeBoundary returns TRUE if the PTE is
  1845. // on a page directory parent entry boundary.
  1846. //
  1847. // Arguments
  1848. //
  1849. // VA - Supplies the virtual address to check.
  1850. //
  1851. // Return Value:
  1852. //
  1853. // TRUE if on a boundary, FALSE if not.
  1854. //
  1855. //--
  1856. #define MiIsPteOnPpeBoundary(PTE) (((ULONG_PTR)(PTE) & (MM_VA_MAPPED_BY_PDE - 1)) == 0)
  1857. //++
  1858. //LOGICAL
  1859. //MiIsPteOnPdeBoundary (
  1860. // IN PVOID PTE
  1861. // );
  1862. //
  1863. // Routine Description:
  1864. //
  1865. // MiIsPteOnPdeBoundary returns TRUE if the PTE is
  1866. // on a page directory entry boundary.
  1867. //
  1868. // Arguments
  1869. //
  1870. // PTE - Supplies the PTE to check.
  1871. //
  1872. // Return Value:
  1873. //
  1874. // TRUE if on a 8MB PDE boundary, FALSE if not.
  1875. //
  1876. //--
  1877. #define MiIsPteOnPdeBoundary(PTE) (((ULONG_PTR)(PTE) & (PAGE_SIZE - 1)) == 0)
  1878. //++
  1879. //ULONG
  1880. //GET_PAGING_FILE_NUMBER (
  1881. // IN MMPTE PTE
  1882. // );
  1883. //
  1884. // Routine Description:
  1885. //
  1886. // This macro extracts the paging file number from a PTE.
  1887. //
  1888. // Arguments:
  1889. //
  1890. // PTE - Supplies the PTE to operate upon.
  1891. //
  1892. // Return Value:
  1893. //
  1894. // The paging file number.
  1895. //
  1896. //--
  1897. #define GET_PAGING_FILE_NUMBER(PTE) ((ULONG) (PTE).u.Soft.PageFileLow)
  1898. //++
  1899. //ULONG
  1900. //GET_PAGING_FILE_OFFSET (
  1901. // IN MMPTE PTE
  1902. // );
  1903. //
  1904. // Routine Description:
  1905. //
  1906. // This macro extracts the offset into the paging file from a PTE.
  1907. //
  1908. // Arguments:
  1909. //
  1910. // PTE - Supplies the PTE to operate upon.
  1911. //
  1912. // Return Value:
  1913. //
  1914. // The paging file offset.
  1915. //
  1916. //--
  1917. #define GET_PAGING_FILE_OFFSET(PTE) ((ULONG) (PTE).u.Soft.PageFileHigh)
  1918. //++
  1919. //ULONG_PTR
  1920. //IS_PTE_NOT_DEMAND_ZERO (
  1921. // IN PMMPTE PPTE
  1922. // );
  1923. //
  1924. // Routine Description:
  1925. //
  1926. // This macro checks to see if a given PTE is NOT a demand zero PTE.
  1927. //
  1928. // Arguments:
  1929. //
  1930. // PTE - Supplies the PTE to operate upon.
  1931. //
  1932. // Return Value:
  1933. //
  1934. // Returns 0 if the PTE is demand zero, non-zero otherwise.
  1935. //
  1936. //--
  1937. #define IS_PTE_NOT_DEMAND_ZERO(PTE) \
  1938. ((PTE).u.Long & ((ULONG_PTR)0xFFFFFFFFF0000000 | \
  1939. MM_PTE_VALID_MASK | \
  1940. MM_PTE_PROTOTYPE_MASK | \
  1941. MM_PTE_TRANSITION_MASK))
  1942. //++
  1943. //VOID
  1944. //MI_MAKING_VALID_PTE_INVALID(
  1945. // IN PMMPTE PPTE
  1946. // );
  1947. //
  1948. // Routine Description:
  1949. //
  1950. // Prepare to make a single valid PTE invalid.
  1951. // No action is required on IA64.
  1952. //
  1953. // Arguments:
  1954. //
  1955. // SYSTEM_WIDE - Supplies TRUE if this will happen on all processors.
  1956. //
  1957. // Return Value:
  1958. //
  1959. // None.
  1960. //
  1961. //--
  1962. #define MI_MAKING_VALID_PTE_INVALID(SYSTEM_WIDE)
  1963. //++
  1964. //VOID
  1965. //MI_MAKING_VALID_MULTIPLE_PTES_INVALID(
  1966. // IN PMMPTE PPTE
  1967. // );
  1968. //
  1969. // Routine Description:
  1970. //
  1971. // Prepare to make multiple valid PTEs invalid.
  1972. // No action is required on IA64.
  1973. //
  1974. // Arguments:
  1975. //
  1976. // SYSTEM_WIDE - Supplies TRUE if this will happen on all processors.
  1977. //
  1978. // Return Value:
  1979. //
  1980. // None.
  1981. //
  1982. //--
  1983. #define MI_MAKING_MULTIPLE_PTES_INVALID(SYSTEM_WIDE)
  1984. //++
  1985. //VOID
  1986. //MI_MAKE_PROTECT_WRITE_COPY (
  1987. // IN OUT MMPTE PPTE
  1988. // );
  1989. //
  1990. // Routine Description:
  1991. //
  1992. // This macro makes a writable PTE a writeable-copy PTE.
  1993. //
  1994. // Arguments:
  1995. //
  1996. // PTE - Supplies the PTE to operate upon.
  1997. //
  1998. // Return Value:
  1999. //
  2000. // NONE
  2001. //
  2002. //--
  2003. #define MI_MAKE_PROTECT_WRITE_COPY(PTE) \
  2004. if ((PTE).u.Soft.Protection & MM_PROTECTION_WRITE_MASK) { \
  2005. (PTE).u.Long |= MM_PROTECTION_COPY_MASK << MM_PROTECT_FIELD_SHIFT; \
  2006. }
  2007. //++
  2008. //VOID
  2009. //MI_SET_PAGE_DIRTY(
  2010. // IN PMMPTE PPTE,
  2011. // IN PVOID VA,
  2012. // IN PVOID PFNHELD
  2013. // );
  2014. //
  2015. // Routine Description:
  2016. //
  2017. // This macro sets the dirty bit (and release page file space).
  2018. //
  2019. // Arguments:
  2020. //
  2021. // TEMP - Supplies a temporary for usage.
  2022. //
  2023. // PPTE - Supplies a pointer to the PTE that corresponds to VA.
  2024. //
  2025. // VA - Supplies a the virtual address of the page fault.
  2026. //
  2027. // PFNHELD - Supplies TRUE if the PFN lock is held.
  2028. //
  2029. // Return Value:
  2030. //
  2031. // None.
  2032. //
  2033. //--
  2034. #define MI_SET_PAGE_DIRTY(PPTE,VA,PFNHELD) \
  2035. if ((PPTE)->u.Hard.Dirty == 1) { \
  2036. MiSetDirtyBit ((VA),(PPTE),(PFNHELD)); \
  2037. }
  2038. //++
  2039. //VOID
  2040. //MI_NO_FAULT_FOUND(
  2041. // IN FAULTSTATUS,
  2042. // IN PMMPTE PPTE,
  2043. // IN PVOID VA,
  2044. // IN PVOID PFNHELD
  2045. // );
  2046. //
  2047. // Routine Description:
  2048. //
  2049. // This macro handles the case when a page fault is taken and no
  2050. // PTE with the valid bit clear is found.
  2051. //
  2052. // Arguments:
  2053. //
  2054. // FAULTSTATUS - Supplies the fault status.
  2055. //
  2056. // PPTE - Supplies a pointer to the PTE that corresponds to VA.
  2057. //
  2058. // VA - Supplies a the virtual address of the page fault.
  2059. //
  2060. // PFNHELD - Supplies TRUE if the PFN lock is held.
  2061. //
  2062. // Return Value:
  2063. //
  2064. // None.
  2065. //
  2066. //--
  2067. #define MI_NO_FAULT_FOUND(FAULTSTATUS,PPTE,VA,PFNHELD) \
  2068. if ((MI_FAULT_STATUS_INDICATES_WRITE(FAULTSTATUS)) && ((PPTE)->u.Hard.Dirty == 0)) { \
  2069. MiSetDirtyBit ((VA),(PPTE),(PFNHELD)); \
  2070. } else { \
  2071. MMPTE TempPte; \
  2072. TempPte = *(PPTE); \
  2073. MI_SET_ACCESSED_IN_PTE (&TempPte, 1); \
  2074. MI_WRITE_VALID_PTE_NEW_PROTECTION((PPTE), TempPte); \
  2075. KiFlushSingleTb(0, (VA)); \
  2076. }
  2077. //++
  2078. //ULONG_PTR
  2079. //MI_CAPTURE_DIRTY_BIT_TO_PFN (
  2080. // IN PMMPTE PPTE,
  2081. // IN PMMPFN PPFN
  2082. // );
  2083. //
  2084. // Routine Description:
  2085. //
  2086. // This macro gets captures the state of the dirty bit to the PFN
  2087. // and frees any associated page file space if the PTE has been
  2088. // modified element.
  2089. //
  2090. // NOTE - THE PFN LOCK MUST BE HELD!
  2091. //
  2092. // Arguments:
  2093. //
  2094. // PPTE - Supplies the PTE to operate upon.
  2095. //
  2096. // PPFN - Supplies a pointer to the PFN database element that corresponds
  2097. // to the page mapped by the PTE.
  2098. //
  2099. // Return Value:
  2100. //
  2101. // None.
  2102. //
  2103. //--
  2104. #define MI_CAPTURE_DIRTY_BIT_TO_PFN(PPTE,PPFN) \
  2105. ASSERT (KeGetCurrentIrql() > APC_LEVEL); \
  2106. if (((PPFN)->u3.e1.Modified == 0) && \
  2107. ((PPTE)->u.Hard.Dirty != 0)) { \
  2108. MI_SET_MODIFIED (PPFN, 1, 0x18); \
  2109. if (((PPFN)->OriginalPte.u.Soft.Prototype == 0) && \
  2110. ((PPFN)->u3.e1.WriteInProgress == 0)) { \
  2111. MiReleasePageFileSpace ((PPFN)->OriginalPte); \
  2112. (PPFN)->OriginalPte.u.Soft.PageFileHigh = 0; \
  2113. } \
  2114. }
  2115. //++
  2116. //BOOLEAN
  2117. //MI_IS_PHYSICAL_ADDRESS (
  2118. // IN PVOID VA
  2119. // );
  2120. //
  2121. // Routine Description:
  2122. //
  2123. // This macro determines if a given virtual address is really a
  2124. // physical address.
  2125. //
  2126. // Arguments:
  2127. //
  2128. // VA - Supplies the virtual address.
  2129. //
  2130. // Return Value:
  2131. //
  2132. // FALSE if it is not a physical address, TRUE if it is.
  2133. //
  2134. //--
  2135. #define MI_IS_PHYSICAL_ADDRESS(Va) \
  2136. ((((ULONG_PTR)(Va) >= KSEG3_BASE) && ((ULONG_PTR)(Va) < KSEG3_LIMIT)) || \
  2137. (((ULONG_PTR)(Va) >= KSEG4_BASE) && ((ULONG_PTR)(Va) < KSEG4_LIMIT)) || \
  2138. (((ULONG_PTR)Va >= KSEG0_BASE) && ((ULONG_PTR)Va < KSEG2_BASE)))
  2139. //++
  2140. //ULONG_PTR
  2141. //MI_CONVERT_PHYSICAL_TO_PFN (
  2142. // IN PVOID VA
  2143. // );
  2144. //
  2145. // Routine Description:
  2146. //
  2147. // This macro converts a physical address (see MI_IS_PHYSICAL_ADDRESS)
  2148. // to its corresponding physical frame number.
  2149. //
  2150. // Arguments:
  2151. //
  2152. // VA - Supplies a pointer to the physical address.
  2153. //
  2154. // Return Value:
  2155. //
  2156. // Returns the PFN for the page.
  2157. //
  2158. //--
  2159. PVOID KiGetPhysicalAddress(
  2160. IN PVOID VirtualAddress
  2161. );
  2162. #define MI_CONVERT_PHYSICAL_TO_PFN(Va) \
  2163. (((ULONG_PTR)(Va) >= KSEG0_BASE) ? \
  2164. ((PFN_NUMBER)(((ULONG_PTR)KiGetPhysicalAddress(Va)) >> PAGE_SHIFT)) :\
  2165. ((PFN_NUMBER)(((ULONG_PTR)(Va) & ~VRN_MASK) >> PAGE_SHIFT)))
  2166. typedef struct _MMCOLOR_TABLES {
  2167. PFN_NUMBER Flink;
  2168. PVOID Blink;
  2169. PFN_NUMBER Count;
  2170. } MMCOLOR_TABLES, *PMMCOLOR_TABLES;
  2171. #if MM_MAXIMUM_NUMBER_OF_COLORS > 1
  2172. extern MMPFNLIST MmFreePagesByPrimaryColor[2][MM_MAXIMUM_NUMBER_OF_COLORS];
  2173. #endif
  2174. extern PMMCOLOR_TABLES MmFreePagesByColor[2];
  2175. extern PFN_NUMBER MmTotalPagesForPagingFile;
  2176. //
  2177. // A VALID Page Table Entry on the IA64 has the following definition.
  2178. //
  2179. #define _MM_PAGING_FILE_LOW_SHIFT 28
  2180. #define _MM_PAGING_FILE_HIGH_SHIFT 32
  2181. #define MI_MAXIMUM_PAGEFILE_SIZE (((UINT64)4 * 1024 * 1024 * 1024 - 1) * PAGE_SIZE)
  2182. #define MI_PTE_LOOKUP_NEEDED ((ULONG64)0xffffffff)
  2183. typedef struct _MMPTE_SOFTWARE {
  2184. ULONGLONG Valid : 1;
  2185. ULONGLONG Prototype : 1;
  2186. ULONGLONG Protection : 5;
  2187. ULONGLONG Transition : 1;
  2188. ULONGLONG UsedPageTableEntries : PTE_PER_PAGE_BITS;
  2189. ULONGLONG Reserved : 20 - PTE_PER_PAGE_BITS;
  2190. ULONGLONG PageFileLow: 4;
  2191. ULONGLONG PageFileHigh : 32;
  2192. } MMPTE_SOFTWARE;
  2193. typedef struct _MMPTE_TRANSITION {
  2194. ULONGLONG Valid : 1;
  2195. ULONGLONG Prototype : 1;
  2196. ULONGLONG Protection : 5;
  2197. ULONGLONG Transition : 1;
  2198. ULONGLONG Rsvd0 : PAGE_SHIFT - 8;
  2199. ULONGLONG PageFrameNumber : 50 - PAGE_SHIFT;
  2200. ULONGLONG Rsvd1 : 14;
  2201. } MMPTE_TRANSITION;
  2202. #define _MM_PROTO_ADDRESS_SHIFT 12
  2203. typedef struct _MMPTE_PROTOTYPE {
  2204. ULONGLONG Valid : 1;
  2205. ULONGLONG Prototype : 1;
  2206. ULONGLONG ReadOnly : 1; // if set allow read only access.
  2207. ULONGLONG Rsvd : 9;
  2208. ULONGLONG ProtoAddress : 52;
  2209. } MMPTE_PROTOTYPE;
  2210. #define _MM_PTE_SUBSECTION_ADDRESS_SHIFT 12
  2211. typedef struct _MMPTE_SUBSECTION {
  2212. ULONGLONG Valid : 1;
  2213. ULONGLONG Prototype : 1;
  2214. ULONGLONG Protection : 5;
  2215. ULONGLONG WhichPool : 1;
  2216. ULONGLONG Rsvd : 4;
  2217. ULONGLONG SubsectionAddress : 52;
  2218. } MMPTE_SUBSECTION;
  2219. typedef struct _MMPTE_LIST {
  2220. ULONGLONG Valid : 1;
  2221. //
  2222. // Note the Prototype bit must not be used for lists like freed nonpaged
  2223. // pool because lookaside pops can legitimately reference bogus addresses
  2224. // (since the pop is unsynchronized) and the fault handler must be able to
  2225. // distinguish lists from protos so a retry status can be returned (vs a
  2226. // fatal bugcheck).
  2227. //
  2228. // The same caveat applies to both the Transition and the Protection
  2229. // fields as they are similarly examined in the fault handler and would
  2230. // be misinterpreted if ever nonzero in the freed nonpaged pool chains.
  2231. //
  2232. ULONGLONG Prototype : 1; // MUST BE ZERO as per above comment.
  2233. ULONGLONG Protection : 5;
  2234. ULONGLONG Transition : 1;
  2235. ULONGLONG OneEntry : 1;
  2236. ULONGLONG filler10 : 23;
  2237. ULONGLONG NextEntry : 32;
  2238. } MMPTE_LIST;
  2239. //
  2240. // A Page Table Entry on the IA64 has the following definition.
  2241. //
  2242. #define _HARDWARE_PTE_WORKING_SET_BITS 11
  2243. typedef struct _MMPTE_HARDWARE {
  2244. ULONGLONG Valid : 1;
  2245. ULONGLONG Rsvd0 : 1;
  2246. ULONGLONG Cache : 3;
  2247. ULONGLONG Accessed : 1;
  2248. ULONGLONG Dirty : 1;
  2249. ULONGLONG Owner : 2;
  2250. ULONGLONG Execute : 1;
  2251. ULONGLONG Write : 1;
  2252. ULONGLONG Rsvd1 : PAGE_SHIFT - 12;
  2253. ULONGLONG CopyOnWrite : 1;
  2254. ULONGLONG PageFrameNumber : 50 - PAGE_SHIFT;
  2255. ULONGLONG Rsvd2 : 2;
  2256. ULONGLONG Exception : 1;
  2257. ULONGLONG SoftwareWsIndex : _HARDWARE_PTE_WORKING_SET_BITS;
  2258. } MMPTE_HARDWARE, *PMMPTE_HARDWARE;
  2259. typedef struct _MMPTE_LARGEPAGE {
  2260. ULONGLONG Valid : 1;
  2261. ULONGLONG Rsvd0 : 1;
  2262. ULONGLONG Cache : 3;
  2263. ULONGLONG Accessed : 1;
  2264. ULONGLONG Dirty : 1;
  2265. ULONGLONG Owner : 2;
  2266. ULONGLONG Execute : 1;
  2267. ULONGLONG Write : 1;
  2268. ULONGLONG Rsvd1 : PAGE_SHIFT - 12;
  2269. ULONGLONG CopyOnWrite : 1;
  2270. ULONGLONG PageFrameNumber : 50 - PAGE_SHIFT;
  2271. ULONGLONG Rsvd2 : 2;
  2272. ULONGLONG Exception : 1;
  2273. ULONGLONG Rsvd3 : 1;
  2274. ULONGLONG LargePage : 1;
  2275. ULONGLONG PageSize : 6;
  2276. ULONGLONG Rsvd4 : 3;
  2277. } MMPTE_LARGEPAGE, *PMMPTE_LARGEPAGE;
  2278. typedef struct _ALT_4KPTE {
  2279. ULONGLONG Commit : 1;
  2280. ULONGLONG Rsvd0 : 1;
  2281. ULONGLONG Cache : 3;
  2282. ULONGLONG Accessed : 1;
  2283. ULONGLONG InPageInProgress : 1;
  2284. ULONGLONG Owner : 2;
  2285. ULONGLONG Execute : 1;
  2286. ULONGLONG Write : 1;
  2287. ULONGLONG Rsvd1 : 1;
  2288. ULONGLONG PteOffset : 32;
  2289. ULONGLONG Rsvd2 : 8;
  2290. ULONGLONG Exception : 1;
  2291. ULONGLONG Protection : 5;
  2292. ULONGLONG Lock : 1;
  2293. ULONGLONG FillZero : 1;
  2294. ULONGLONG NoAccess : 1;
  2295. ULONGLONG CopyOnWrite : 1;
  2296. ULONGLONG PteIndirect : 1;
  2297. ULONGLONG Private : 1;
  2298. } ALT_4KPTE, *PALT_4KPTE;
  2299. #define MI_GET_PAGE_FRAME_FROM_PTE(PTE) ((ULONG)((PTE)->u.Hard.PageFrameNumber))
  2300. #define MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE(PTE) ((ULONG)((PTE)->u.Trans.PageFrameNumber))
  2301. #define MI_GET_PROTECTION_FROM_SOFT_PTE(PTE) ((ULONG)((PTE)->u.Soft.Protection))
  2302. #define MI_GET_PROTECTION_FROM_TRANSITION_PTE(PTE) ((ULONG)((PTE)->u.Trans.Protection))
  2303. typedef struct _MMPTE {
  2304. union {
  2305. ULONGLONG Long;
  2306. MMPTE_HARDWARE Hard;
  2307. MMPTE_LARGEPAGE Large;
  2308. HARDWARE_PTE Flush;
  2309. MMPTE_PROTOTYPE Proto;
  2310. MMPTE_SOFTWARE Soft;
  2311. MMPTE_TRANSITION Trans;
  2312. MMPTE_SUBSECTION Subsect;
  2313. MMPTE_LIST List;
  2314. ALT_4KPTE Alt;
  2315. } u;
  2316. } MMPTE;
  2317. typedef MMPTE *PMMPTE;
  2318. extern PMMPTE MiFirstReservedZeroingPte;
  2319. #define InterlockedCompareExchangePte(_PointerPte, _NewContents, _OldContents) \
  2320. InterlockedCompareExchange64 ((PLONGLONG)(_PointerPte), (LONGLONG)(_NewContents), (LONGLONG)(_OldContents))
  2321. //++
  2322. //VOID
  2323. //MI_WRITE_VALID_PTE (
  2324. // IN PMMPTE PointerPte,
  2325. // IN MMPTE PteContents
  2326. // );
  2327. //
  2328. // Routine Description:
  2329. //
  2330. // MI_WRITE_VALID_PTE fills in the specified PTE making it valid with the
  2331. // specified contents.
  2332. //
  2333. // Arguments
  2334. //
  2335. // PointerPte - Supplies a PTE to fill.
  2336. //
  2337. // PteContents - Supplies the contents to put in the PTE.
  2338. //
  2339. // Return Value:
  2340. //
  2341. // None.
  2342. //
  2343. //--
  2344. #define MI_WRITE_VALID_PTE(_PointerPte, _PteContents) \
  2345. (*((volatile MMPTE *)(_PointerPte)) = (_PteContents))
  2346. //++
  2347. //VOID
  2348. //MI_WRITE_INVALID_PTE (
  2349. // IN PMMPTE PointerPte,
  2350. // IN MMPTE PteContents
  2351. // );
  2352. //
  2353. // Routine Description:
  2354. //
  2355. // MI_WRITE_INVALID_PTE fills in the specified PTE making it invalid with the
  2356. // specified contents.
  2357. //
  2358. // Arguments
  2359. //
  2360. // PointerPte - Supplies a PTE to fill.
  2361. //
  2362. // PteContents - Supplies the contents to put in the PTE.
  2363. //
  2364. // Return Value:
  2365. //
  2366. // None.
  2367. //
  2368. //--
  2369. #define MI_WRITE_INVALID_PTE(_PointerPte, _PteContents) \
  2370. (*(_PointerPte) = (_PteContents))
  2371. //++
  2372. //VOID
  2373. //MI_WRITE_VALID_PTE_NEW_PROTECTION (
  2374. // IN PMMPTE PointerPte,
  2375. // IN MMPTE PteContents
  2376. // );
  2377. //
  2378. // Routine Description:
  2379. //
  2380. // MI_WRITE_VALID_PTE_NEW_PROTECTION fills in the specified PTE (which was
  2381. // already valid) changing only the protection or the dirty bit.
  2382. //
  2383. // Arguments
  2384. //
  2385. // PointerPte - Supplies a PTE to fill.
  2386. //
  2387. // PteContents - Supplies the contents to put in the PTE.
  2388. //
  2389. // Return Value:
  2390. //
  2391. // None.
  2392. //
  2393. //--
  2394. #define MI_WRITE_VALID_PTE_NEW_PROTECTION(_PointerPte, _PteContents) \
  2395. (*(_PointerPte) = (_PteContents))
  2396. //++
  2397. //VOID
  2398. //MiFillMemoryPte (
  2399. // IN PMMPTE Destination,
  2400. // IN ULONGULONG Length,
  2401. // IN MMPTE Pattern
  2402. // };
  2403. //
  2404. // Routine Description:
  2405. //
  2406. // This function fills memory with the specified PTE pattern.
  2407. //
  2408. // Arguments
  2409. //
  2410. // Destination - Supplies a pointer to the memory to fill.
  2411. //
  2412. // Length - Supplies the length, in bytes, of the memory to be
  2413. // filled.
  2414. //
  2415. // Pattern - Supplies the PTE fill pattern.
  2416. //
  2417. // Return Value:
  2418. //
  2419. // None.
  2420. //
  2421. //--
  2422. #define MiFillMemoryPte(Destination, Length, Pattern) \
  2423. RtlFillMemoryUlonglong ((Destination), (Length), (Pattern))
  2424. #define KiWbInvalidateCache
  2425. //++
  2426. //BOOLEAN
  2427. //MI_IS_PAGE_TABLE_ADDRESS (
  2428. // IN PVOID VA
  2429. // );
  2430. //
  2431. // Routine Description:
  2432. //
  2433. // This macro determines if a given virtual address is really a
  2434. // page table address (PTE, PDE, PPE).
  2435. //
  2436. // Arguments
  2437. //
  2438. // VA - Supplies the virtual address.
  2439. //
  2440. // Return Value:
  2441. //
  2442. // FALSE if it is not a page table address, TRUE if it is.
  2443. //
  2444. //--
  2445. #if defined(_MIALT4K_)
  2446. #define MI_IS_PAGE_TABLE_ADDRESS(VA) \
  2447. ((((ULONG_PTR)VA >= PTE_UBASE) && ((ULONG_PTR)VA <= (PDE_UTBASE + PAGE_SIZE))) || \
  2448. (((ULONG_PTR)VA >= PTE_KBASE) && ((ULONG_PTR)VA <= (PDE_KTBASE + PAGE_SIZE))) || \
  2449. (((ULONG_PTR)VA >= PTE_SBASE) && ((ULONG_PTR)VA <= (PDE_STBASE + PAGE_SIZE))) || \
  2450. (((ULONG_PTR)VA >= (ULONG_PTR)ALT4KB_PERMISSION_TABLE_START) && \
  2451. ((ULONG_PTR)VA <= (ULONG_PTR)ALT4KB_PERMISSION_TABLE_END)))
  2452. #else
  2453. #define MI_IS_PAGE_TABLE_ADDRESS(VA) \
  2454. ((((ULONG_PTR)VA >= PTE_UBASE) && ((ULONG_PTR)VA <= (PDE_UTBASE + PAGE_SIZE))) || \
  2455. (((ULONG_PTR)VA >= PTE_KBASE) && ((ULONG_PTR)VA <= (PDE_KTBASE + PAGE_SIZE))) || \
  2456. (((ULONG_PTR)VA >= PTE_SBASE) && ((ULONG_PTR)VA <= (PDE_STBASE + PAGE_SIZE))))
  2457. #endif
  2458. //++
  2459. //BOOLEAN
  2460. //MI_IS_HYPER_SPACE_ADDRESS (
  2461. // IN PVOID VA
  2462. // );
  2463. //
  2464. // Routine Description:
  2465. //
  2466. // This macro determines if a given virtual address resides in
  2467. // hyperspace.
  2468. //
  2469. // Arguments
  2470. //
  2471. // VA - Supplies the virtual address.
  2472. //
  2473. // Return Value:
  2474. //
  2475. // FALSE if it is not a hyperspace address, TRUE if it is.
  2476. //
  2477. //--
  2478. #define MI_IS_HYPER_SPACE_ADDRESS(VA) \
  2479. (((PVOID)VA >= HYPER_SPACE) && ((PVOID)VA <= HYPER_SPACE_END))
  2480. //++
  2481. //BOOLEAN
  2482. //MI_IS_PTE_ADDRESS (
  2483. // IN PMMPTE PTE
  2484. // );
  2485. //
  2486. // Routine Description:
  2487. //
  2488. // This macro determines if a given virtual address is really a
  2489. // page table page (PTE) address.
  2490. //
  2491. // Arguments
  2492. //
  2493. // PTE - Supplies the PTE virtual address.
  2494. //
  2495. // Return Value:
  2496. //
  2497. // FALSE if it is not a PTE address, TRUE if it is.
  2498. //
  2499. //--
  2500. #define MI_IS_PTE_ADDRESS(PTE) \
  2501. (((PTE >= (PMMPTE)PTE_UBASE) && (PTE <= (PMMPTE)PTE_UTOP)) || \
  2502. ((PTE >= (PMMPTE)PTE_KBASE) && (PTE <= (PMMPTE)PTE_KTOP)) || \
  2503. ((PTE >= (PMMPTE)PTE_SBASE) && (PTE <= (PMMPTE)PTE_STOP)))
  2504. #define MI_IS_PPE_ADDRESS(PTE) \
  2505. (((PTE >= (PMMPTE)PDE_UTBASE) && (PTE <= (PMMPTE)(PDE_UTBASE + PAGE_SIZE))) || \
  2506. ((PTE >= (PMMPTE)PDE_KTBASE) && (PTE <= (PMMPTE)(PDE_KTBASE + PAGE_SIZE))) || \
  2507. ((PTE >= (PMMPTE)PDE_STBASE) && (PTE <= (PMMPTE)(PDE_STBASE + PAGE_SIZE))))
  2508. //++
  2509. //BOOLEAN
  2510. //MI_IS_KERNEL_PTE_ADDRESS (
  2511. // IN PMMPTE PTE
  2512. // );
  2513. //
  2514. // Routine Description:
  2515. //
  2516. // This macro determines if a given virtual address is really a
  2517. // kernel page table page (PTE) address.
  2518. //
  2519. // Arguments
  2520. //
  2521. // PTE - Supplies the PTE virtual address.
  2522. //
  2523. // Return Value:
  2524. //
  2525. // FALSE if it is not a kernel PTE address, TRUE if it is.
  2526. //
  2527. //--
  2528. #define MI_IS_KERNEL_PTE_ADDRESS(PTE) \
  2529. (((PMMPTE)PTE >= (PMMPTE)PTE_KBASE) && ((PMMPTE)PTE <= (PMMPTE)PTE_KTOP))
  2530. //++
  2531. //BOOLEAN
  2532. //MI_IS_USER_PTE_ADDRESS (
  2533. // IN PMMPTE PTE
  2534. // );
  2535. //
  2536. // Routine Description:
  2537. //
  2538. // This macro determines if a given virtual address is really a
  2539. // page table page (PTE) address.
  2540. //
  2541. // Arguments
  2542. //
  2543. // PTE - Supplies the PTE virtual address.
  2544. //
  2545. // Return Value:
  2546. //
  2547. // FALSE if it is not a PTE address, TRUE if it is.
  2548. //
  2549. //--
  2550. #define MI_IS_USER_PTE_ADDRESS(PTE) \
  2551. ((PTE >= (PMMPTE)PTE_UBASE) && (PTE <= (PMMPTE)PTE_UTOP))
  2552. //++
  2553. //BOOLEAN
  2554. //MI_IS_PAGE_DIRECTORY_ADDRESS (
  2555. // IN PMMPTE PDE
  2556. // );
  2557. //
  2558. // Routine Description:
  2559. //
  2560. // This macro determines if a given virtual address is really a
  2561. // page directory page (PDE) address.
  2562. //
  2563. // Arguments
  2564. //
  2565. // PDE - Supplies the virtual address.
  2566. //
  2567. // Return Value:
  2568. //
  2569. // FALSE if it is not a PDE address, TRUE if it is.
  2570. //
  2571. //--
  2572. #define MI_IS_PAGE_DIRECTORY_ADDRESS(PDE) \
  2573. (((PDE >= (PMMPTE)PDE_UBASE) && (PDE <= (PMMPTE)PDE_UTOP)) || \
  2574. ((PDE >= (PMMPTE)PDE_KBASE) && (PDE <= (PMMPTE)PDE_KTOP)) || \
  2575. ((PDE >= (PMMPTE)PDE_SBASE) && (PDE <= (PMMPTE)PDE_STOP)))
  2576. //++
  2577. //BOOLEAN
  2578. //MI_IS_USER_PDE_ADDRESS (
  2579. // IN PMMPTE PDE
  2580. // );
  2581. //
  2582. // Routine Description:
  2583. //
  2584. // This macro determines if a given virtual address is really a
  2585. // user page directory page (PDE) address.
  2586. //
  2587. // Arguments
  2588. //
  2589. // PDE - Supplies the PDE virtual address.
  2590. //
  2591. // Return Value:
  2592. //
  2593. // FALSE if it is not a user PDE address, TRUE if it is.
  2594. //
  2595. //--
  2596. #define MI_IS_USER_PDE_ADDRESS(PDE) \
  2597. ((PDE >= (PMMPTE)PDE_UBASE) && (PDE <= (PMMPTE)PDE_UTOP))
  2598. //++
  2599. //BOOLEAN
  2600. //MI_IS_KERNEL_PDE_ADDRESS (
  2601. // IN PMMPTE PDE
  2602. // );
  2603. //
  2604. // Routine Description:
  2605. //
  2606. // This macro determines if a given virtual address is really a
  2607. // kernel page directory page (PDE) address.
  2608. //
  2609. // Arguments
  2610. //
  2611. // PDE - Supplies the PDE virtual address.
  2612. //
  2613. // Return Value:
  2614. //
  2615. // FALSE if it is not a user PDE address, TRUE if it is.
  2616. //
  2617. //--
  2618. #define MI_IS_KERNEL_PDE_ADDRESS(PDE) \
  2619. ((PDE >= (PMMPTE)PDE_KBASE) && (PDE <= (PMMPTE)PDE_KTOP))
  2620. //++
  2621. //BOOLEAN
  2622. //MI_IS_PROCESS_SPACE_ADDRESS (
  2623. // IN PVOID VA
  2624. // );
  2625. //
  2626. // Routine Description:
  2627. //
  2628. // This macro determines if a given virtual address resides in
  2629. // the per-process space.
  2630. //
  2631. // Arguments
  2632. //
  2633. // VA - Supplies the virtual address.
  2634. //
  2635. // Return Value:
  2636. //
  2637. // FALSE if it is not a per-process address, TRUE if it is.
  2638. //
  2639. //--
  2640. #define MI_IS_PROCESS_SPACE_ADDRESS(VA) (((ULONG_PTR)VA >> 61) == UREGION_INDEX)
  2641. //++
  2642. //BOOLEAN
  2643. //MI_IS_SYSTEM_ADDRESS (
  2644. // IN PVOID VA
  2645. // );
  2646. //
  2647. // Routine Description:
  2648. //
  2649. // This macro determines if a given virtual address resides in
  2650. // the system (global) space.
  2651. //
  2652. // Arguments
  2653. //
  2654. // VA - Supplies the virtual address.
  2655. //
  2656. // Return Value:
  2657. //
  2658. // FALSE if it is not a system (global) address, TRUE if it is.
  2659. //
  2660. //--
  2661. #define MI_IS_SYSTEM_ADDRESS(VA) (((ULONG_PTR)VA >> 61) == KREGION_INDEX)
  2662. //
  2663. //++
  2664. //PVOID
  2665. //KSEG0_ADDRESS (
  2666. // IN PFN_NUMBER PAGE
  2667. // );
  2668. //
  2669. // Routine Description:
  2670. //
  2671. // This macro returns a KSEG0 virtual address which maps the page.
  2672. //
  2673. // Arguments:
  2674. //
  2675. // PAGE - Supplies the physical page frame number.
  2676. //
  2677. // Return Value:
  2678. //
  2679. // The KSEG0 virtual address.
  2680. //
  2681. //--
  2682. #define KSEG0_ADDRESS(PAGE) \
  2683. (PVOID)(KSEG0_BASE | ((PAGE) << PAGE_SHIFT))
  2684. extern MMPTE ValidPpePte;
  2685. //++
  2686. //PMMPTE
  2687. //MiGetPpeAddress (
  2688. // IN PVOID va
  2689. // );
  2690. //
  2691. // Routine Description:
  2692. //
  2693. // MiGetPpeAddress returns the address of the page directory parent entry
  2694. // which maps the given virtual address. This is one level above the
  2695. // page directory.
  2696. //
  2697. // Arguments
  2698. //
  2699. // Va - Supplies the virtual address to locate the PPE for.
  2700. //
  2701. // Return Value:
  2702. //
  2703. // The address of the PPE.
  2704. //
  2705. //--
  2706. __forceinline
  2707. PMMPTE
  2708. MiGetPpeAddress(
  2709. IN PVOID Va
  2710. )
  2711. {
  2712. if ((((ULONG_PTR)(Va) & PTE_BASE) == PTE_BASE) &&
  2713. ((((ULONG_PTR)(Va)) & ~(VRN_MASK|PTE_BASE)) < (ULONG_PTR)PDE_PER_PAGE * PTE_PER_PAGE * PAGE_SIZE)) {
  2714. return (PMMPTE) (((ULONG_PTR)Va & VRN_MASK) |
  2715. (PDE_TBASE + PAGE_SIZE - sizeof(MMPTE)));
  2716. }
  2717. if (((((ULONG_PTR)(Va)) & PDE_BASE) == PDE_BASE) &&
  2718. ((((ULONG_PTR)(Va)) & ~(VRN_MASK|PDE_BASE)) < PDE_PER_PAGE * PAGE_SIZE)) {
  2719. return (PMMPTE) ((((ULONG_PTR)(Va)) & VRN_MASK) |
  2720. (PDE_TBASE + PAGE_SIZE - sizeof(MMPTE)));
  2721. }
  2722. if (((((ULONG_PTR)(Va)) & PDE_TBASE) == PDE_TBASE) &&
  2723. ((((ULONG_PTR)(Va)) & ~(VRN_MASK|PDE_TBASE)) < PAGE_SIZE)) {
  2724. return (PMMPTE) ((((ULONG_PTR)(Va)) & VRN_MASK) |
  2725. (PDE_TBASE + PAGE_SIZE - sizeof(MMPTE)));
  2726. }
  2727. return (PMMPTE) (((((ULONG_PTR)(Va)) & VRN_MASK)) |
  2728. ((((((ULONG_PTR)(Va)) >> PDI1_SHIFT) << PTE_SHIFT) &
  2729. (~(PDE_TBASE|VRN_MASK)) ) + PDE_TBASE));
  2730. }
  2731. //MiGetPdeAddress (
  2732. // IN PVOID va
  2733. // );
  2734. //
  2735. // Routine Description:
  2736. //
  2737. // MiGetPdeAddress returns the address of the PDE which maps the
  2738. // given virtual address.
  2739. //
  2740. // Arguments:
  2741. //
  2742. // Va - Supplies the virtual address to locate the PDE for.
  2743. //
  2744. // Return Value:
  2745. //
  2746. // The address of the PDE.
  2747. //
  2748. //--
  2749. __forceinline
  2750. PMMPTE
  2751. MiGetPdeAddress(
  2752. IN PVOID Va
  2753. )
  2754. {
  2755. if (((((ULONG_PTR)(Va)) & PDE_BASE) == PDE_BASE) &&
  2756. ((((ULONG_PTR)(Va)) & ~(VRN_MASK|PDE_BASE)) < PDE_PER_PAGE * PAGE_SIZE)) {
  2757. return (PMMPTE) ((((ULONG_PTR)(Va)) & VRN_MASK) |
  2758. (PDE_TBASE + PAGE_SIZE - sizeof(MMPTE)));
  2759. }
  2760. if (((((ULONG_PTR)(Va)) & PDE_TBASE) == PDE_TBASE) &&
  2761. ((((ULONG_PTR)(Va)) & ~(VRN_MASK|PDE_TBASE)) < PAGE_SIZE)) {
  2762. return (PMMPTE) ((((ULONG_PTR)(Va)) & VRN_MASK) |
  2763. (PDE_TBASE + PAGE_SIZE - sizeof(MMPTE)));
  2764. }
  2765. return (PMMPTE) (((((ULONG_PTR)(Va)) & VRN_MASK)) |
  2766. ((((((ULONG_PTR)(Va)) >> PDI_SHIFT) << PTE_SHIFT) & (~(PDE_BASE|VRN_MASK))) + PDE_BASE));
  2767. }
  2768. //++
  2769. //PMMPTE
  2770. //MiGetPteAddress (
  2771. // IN PVOID va
  2772. // );
  2773. //
  2774. // Routine Description:
  2775. //
  2776. // MiGetPteAddress returns the address of the PTE which maps the
  2777. // given virtual address.
  2778. //
  2779. // Arguments:
  2780. //
  2781. // Va - Supplies the virtual address to locate the PTE for.
  2782. //
  2783. // Return Value:
  2784. //
  2785. // The address of the PTE.
  2786. //
  2787. //--
  2788. __forceinline
  2789. PMMPTE
  2790. MiGetPteAddress(
  2791. IN PVOID Va
  2792. )
  2793. {
  2794. if (((((ULONG_PTR)(Va)) & PDE_TBASE) == PDE_TBASE) &&
  2795. ((((ULONG_PTR)(Va)) & ~(VRN_MASK|PDE_TBASE)) < PAGE_SIZE)) {
  2796. return (PMMPTE) ((((ULONG_PTR)(Va)) & VRN_MASK) |
  2797. (PDE_TBASE + PAGE_SIZE - sizeof(MMPTE)));
  2798. }
  2799. return (PMMPTE) (((((ULONG_PTR)(Va)) & VRN_MASK)) |
  2800. ((((((ULONG_PTR)(Va)) >> PTI_SHIFT) << PTE_SHIFT) & (~(PTE_BASE|VRN_MASK))) + PTE_BASE));
  2801. }
  2802. #define MI_IS_PTE_PROTOTYPE(PointerPte) (!MI_IS_USER_PTE_ADDRESS (PointerPte))
  2803. //++
  2804. //BOOLEAN
  2805. //MI_IS_SYSTEM_CACHE_ADDRESS (
  2806. // IN PVOID VA
  2807. // );
  2808. //
  2809. // Routine Description:
  2810. //
  2811. // This macro takes a virtual address and determines if
  2812. // it is a system cache address.
  2813. //
  2814. // Arguments
  2815. //
  2816. // VA - Supplies a virtual address.
  2817. //
  2818. // Return Value:
  2819. //
  2820. // TRUE if the address is in the system cache, FALSE if not.
  2821. //
  2822. //--
  2823. #define MI_IS_SYSTEM_CACHE_ADDRESS(VA) \
  2824. (((PVOID)(VA) >= (PVOID)MmSystemCacheStart && \
  2825. (PVOID)(VA) <= (PVOID)MmSystemCacheEnd))
  2826. #if defined(_MIALT4K_)
  2827. //
  2828. // Define constants and macros for the alternate 4kb table.
  2829. //
  2830. // These are constants and defines that mimic the PAGE_SIZE constant but are
  2831. // hard coded to use 4K page values.
  2832. //
  2833. #define PAGE_4K 4096
  2834. #define PAGE_4K_SHIFT 12
  2835. #define PAGE_4K_MASK (PAGE_4K - 1)
  2836. #define PAGE_4K_ALIGN(Va) ((PVOID)((ULONG_PTR)(Va) & ~(PAGE_4K - 1)))
  2837. #define ROUND_TO_4K_PAGES(Size) (((ULONG_PTR)(Size) + PAGE_4K - 1) & ~(PAGE_4K - 1))
  2838. #define PAGE_NEXT_ALIGN(Va) ((PVOID)(PAGE_ALIGN((ULONG_PTR)Va + PAGE_SIZE - 1)))
  2839. #define BYTES_TO_4K_PAGES(Size) ((ULONG)((ULONG_PTR)(Size) >> PAGE_4K_SHIFT) + \
  2840. (((ULONG)(Size) & (PAGE_4K - 1)) != 0))
  2841. //
  2842. // Relative constants between native pages and 4K pages.
  2843. //
  2844. #define SPLITS_PER_PAGE (PAGE_SIZE / PAGE_4K)
  2845. #define PAGE_SHIFT_DIFF (PAGE_SHIFT - PAGE_4K_SHIFT)
  2846. #define ALT_PTE_SHIFT 3
  2847. #define ALT_PROTECTION_MASK (MM_PTE_EXECUTE_MASK|MM_PTE_WRITE_MASK)
  2848. #define MiGetAltPteAddress(VA) \
  2849. ((PMMPTE) ((ULONG_PTR)ALT4KB_PERMISSION_TABLE_START + \
  2850. ((((ULONG_PTR) (VA)) >> PAGE_4K_SHIFT) << ALT_PTE_SHIFT)))
  2851. //
  2852. // Alternate 4k table flags.
  2853. //
  2854. #define MI_ALTFLG_FLUSH2G 0x0000000000000001
  2855. //
  2856. // MiProtectFor4kPage flags.
  2857. //
  2858. #define ALT_ALLOCATE 1
  2859. #define ALT_COMMIT 2
  2860. #define ALT_CHANGE 4
  2861. //
  2862. // ATE (Alternate PTE) protection bits.
  2863. //
  2864. #define MM_ATE_COMMIT 0x0000000000000001
  2865. #define MM_ATE_ACCESS 0x0000000000000020
  2866. #define MM_ATE_READONLY 0x0000000000000200
  2867. #define MM_ATE_EXECUTE 0x0400000000000200
  2868. #define MM_ATE_EXECUTE_READ 0x0400000000000200
  2869. #define MM_ATE_READWRITE 0x0000000000000600
  2870. #define MM_ATE_WRITECOPY 0x0020000000000200
  2871. #define MM_ATE_EXECUTE_READWRITE 0x0400000000000600
  2872. #define MM_ATE_EXECUTE_WRITECOPY 0x0420000000000400
  2873. #define MM_ATE_ZEROFILL 0x0800000000000000
  2874. #define MM_ATE_NOACCESS 0x1000000000000000
  2875. #define MM_ATE_COPY_ON_WRITE 0x2000000000000000
  2876. #define MM_ATE_PRIVATE 0x8000000000000000
  2877. #define MM_ATE_PROTO_MASK 0x0000000000000621
  2878. NTSTATUS
  2879. MmX86Fault (
  2880. IN ULONG_PTR FaultStatus,
  2881. IN PVOID VirtualAddress,
  2882. IN KPROCESSOR_MODE PreviousMode,
  2883. IN PVOID TrapInformation
  2884. );
  2885. VOID
  2886. MiProtectFor4kPage(
  2887. IN PVOID Base,
  2888. IN SIZE_T Size,
  2889. IN ULONG NewProtect,
  2890. IN ULONG Flags,
  2891. IN PEPROCESS Process
  2892. );
  2893. VOID
  2894. MiProtectMapFileFor4kPage(
  2895. IN PVOID Base,
  2896. IN SIZE_T Size,
  2897. IN ULONG NewProtect,
  2898. IN SIZE_T CommitSize,
  2899. IN PMMPTE PointerPte,
  2900. IN PMMPTE LastPte,
  2901. IN PEPROCESS Process
  2902. );
  2903. VOID
  2904. MiProtectImageFileFor4kPage(
  2905. IN PVOID Base,
  2906. IN SIZE_T Size,
  2907. IN PMMPTE PointerPte,
  2908. IN PEPROCESS Process
  2909. );
  2910. VOID
  2911. MiReleaseFor4kPage(
  2912. IN PVOID StartVirtual,
  2913. IN PVOID EndVirtual,
  2914. IN PEPROCESS Process
  2915. );
  2916. VOID
  2917. MiDecommitFor4kPage(
  2918. IN PVOID StartVirtual,
  2919. IN PVOID EndVirtual,
  2920. IN PEPROCESS Process
  2921. );
  2922. VOID
  2923. MiDeleteFor4kPage(
  2924. IN PVOID StartVirtual,
  2925. IN PVOID EndVirtual,
  2926. IN PEPROCESS Process
  2927. );
  2928. VOID
  2929. MiQueryRegionFor4kPage (
  2930. IN PVOID BaseAddress,
  2931. IN PVOID EndAddress,
  2932. IN OUT PSIZE_T RegionSize,
  2933. IN OUT PULONG RegionState,
  2934. IN OUT PULONG RegionProtect,
  2935. IN PEPROCESS Process
  2936. );
  2937. ULONG
  2938. MiQueryProtectionFor4kPage (
  2939. IN PVOID BaseAddress,
  2940. IN PEPROCESS Process
  2941. );
  2942. NTSTATUS
  2943. MiInitializeAlternateTable (
  2944. PEPROCESS Process
  2945. );
  2946. VOID
  2947. MiDuplicateAlternateTable (
  2948. PEPROCESS CurrentProcess,
  2949. PEPROCESS ProcessToInitialize
  2950. );
  2951. VOID
  2952. MiDeleteAlternateTable (
  2953. PEPROCESS Process
  2954. );
  2955. VOID
  2956. MiLockFor4kPage (
  2957. PVOID CapturedBase,
  2958. SIZE_T CapturedRegionSize,
  2959. PEPROCESS Process
  2960. );
  2961. NTSTATUS
  2962. MiUnlockFor4kPage (
  2963. PVOID CapturedBase,
  2964. SIZE_T CapturedRegionSize,
  2965. PEPROCESS Process
  2966. );
  2967. LOGICAL
  2968. MiShouldBeUnlockedFor4kPage (
  2969. PVOID VirtualAddress,
  2970. PEPROCESS Process
  2971. );
  2972. ULONG
  2973. MiMakeProtectForNativePage (
  2974. IN PVOID VirtualAddress,
  2975. IN ULONG NewProtect,
  2976. IN PEPROCESS Process
  2977. );
  2978. LOGICAL
  2979. MiArePreceding4kPagesAllocated (
  2980. IN PVOID VirtualAddress
  2981. );
  2982. LOGICAL
  2983. MiAreFollowing4kPagesAllocated (
  2984. IN PVOID VirtualAddress
  2985. );
  2986. extern ULONG MmProtectToPteMaskForIA32[32];
  2987. extern ULONG MmProtectToPteMaskForSplit[32];
  2988. extern ULONGLONG MmProtectToAteMask[32];
  2989. #define MiMakeProtectionAteMask(NewProtect) MmProtectToAteMask[NewProtect]
  2990. #define LOCK_ALTERNATE_TABLE_UNSAFE(PWOW64) \
  2991. ASSERT (KeGetCurrentIrql() == APC_LEVEL); \
  2992. ExAcquireFastMutexUnsafe (&(PWOW64)->AlternateTableLock); \
  2993. (PWOW64)->AlternateTableAcquiredUnsafe = MI_MUTEX_ACQUIRED_UNSAFE;
  2994. #define UNLOCK_ALTERNATE_TABLE_UNSAFE(PWOW64) \
  2995. ASSERT (KeGetCurrentIrql() == APC_LEVEL); \
  2996. ASSERT ((PWOW64)->AlternateTableAcquiredUnsafe == MI_MUTEX_ACQUIRED_UNSAFE); \
  2997. ExReleaseFastMutexUnsafe (&(PWOW64)->AlternateTableLock); \
  2998. ASSERT (KeGetCurrentIrql() == APC_LEVEL);
  2999. #define LOCK_ALTERNATE_TABLE(PWOW64) \
  3000. ExAcquireFastMutex( &(PWOW64)->AlternateTableLock)
  3001. #define UNLOCK_ALTERNATE_TABLE(PWOW64) \
  3002. ExReleaseFastMutex(&(PWOW64)->AlternateTableLock)
  3003. #define MI_IS_ALT_PAGE_TABLE_ADDRESS(PPTE) \
  3004. (((PPTE) >= (PMMPTE)ALT4KB_PERMISSION_TABLE_START) && \
  3005. ((PPTE) < (PMMPTE)ALT4KB_PERMISSION_TABLE_END))
  3006. #endif
  3007. #define MI_ALT_PTE_IN_PAGE_IN_PROGRESS(AltPte) \
  3008. AltPte->u.Alt.InPageInProgress
  3009. //++
  3010. //VOID
  3011. //MI_BARRIER_SYNCHRONIZE (
  3012. // IN ULONG TimeStamp
  3013. // );
  3014. //
  3015. // Routine Description:
  3016. //
  3017. // MI_BARRIER_SYNCHRONIZE compares the argument timestamp against the
  3018. // current IPI barrier sequence stamp. When equal, all processors will
  3019. // issue memory barriers to ensure that newly created pages remain coherent.
  3020. //
  3021. // When a page is put in the zeroed or free page list the current
  3022. // barrier sequence stamp is read (interlocked - this is necessary
  3023. // to get the correct value - memory barriers won't do the trick)
  3024. // and stored in the pfn entry for the page. The current barrier
  3025. // sequence stamp is maintained by the IPI send logic and is
  3026. // incremented (interlocked) when the target set of an IPI send
  3027. // includes all processors, but the one doing the send. When a page
  3028. // is needed its sequence number is compared against the current
  3029. // barrier sequence number. If it is equal, then the contents of
  3030. // the page may not be coherent on all processors, and an IPI must
  3031. // be sent to all processors to ensure a memory barrier is
  3032. // executed (generic call can be used for this). Sending the IPI
  3033. // automatically updates the barrier sequence number. The compare
  3034. // is for equality as this is the only value that requires the IPI
  3035. // (i.e., the sequence number wraps, values in both directions are
  3036. // older). When a page is removed in this fashion and either found
  3037. // to be coherent or made coherent, it cannot be modified between
  3038. // that time and writing the PTE. If the page is modified between
  3039. // these times, then an IPI must be sent.
  3040. //
  3041. // Arguments
  3042. //
  3043. // TimeStamp - Supplies the timestamp at the time when the page was zeroed.
  3044. //
  3045. // Return Value:
  3046. //
  3047. // None.
  3048. //
  3049. //--
  3050. #define MI_BARRIER_SYNCHRONIZE(TimeStamp) NOTHING
  3051. //++
  3052. //VOID
  3053. //MI_BARRIER_STAMP_ZEROED_PAGE (
  3054. // IN PULONG PointerTimeStamp
  3055. // );
  3056. //
  3057. // Routine Description:
  3058. //
  3059. // MI_BARRIER_STAMP_ZEROED_PAGE issues an interlocked read to get the
  3060. // current IPI barrier sequence stamp. This is called AFTER a page is
  3061. // zeroed.
  3062. //
  3063. // Arguments
  3064. //
  3065. // PointerTimeStamp - Supplies a timestamp pointer to fill with the
  3066. // current IPI barrier sequence stamp.
  3067. //
  3068. // Return Value:
  3069. //
  3070. // None.
  3071. //
  3072. //--
  3073. #define MI_BARRIER_STAMP_ZEROED_PAGE(PointerTimeStamp) NOTHING
  3074. //++
  3075. //VOID
  3076. //MI_FLUSH_SINGLE_SESSION_TB (
  3077. // IN PVOID Virtual,
  3078. // IN ULONG Invalid,
  3079. // IN LOGICAL AllProcessors,
  3080. // IN PMMPTE PtePointer,
  3081. // IN MMPTE PteValue,
  3082. // IN MMPTE PreviousPte
  3083. // );
  3084. //
  3085. // Routine Description:
  3086. //
  3087. // MI_FLUSH_SINGLE_SESSION_TB flushes the requested single address
  3088. // translation from the TB.
  3089. //
  3090. // Since IA64 supports ASNs and session space doesn't have one, the entire
  3091. // TB needs to be flushed.
  3092. //
  3093. // Arguments
  3094. //
  3095. // Virtual - Supplies the virtual address to invalidate.
  3096. //
  3097. // Invalid - TRUE if invalidating.
  3098. //
  3099. // AllProcessors - TRUE if all processors need to be IPI'd.
  3100. //
  3101. // PtePointer - Supplies the PTE to invalidate.
  3102. //
  3103. // PteValue - Supplies the new PTE value.
  3104. //
  3105. // PreviousPte - The previous PTE value is returned here.
  3106. //
  3107. // Return Value:
  3108. //
  3109. // None.
  3110. //
  3111. //--
  3112. #define MI_FLUSH_SINGLE_SESSION_TB(Virtual, Invalid, AllProcessors, PtePointer, PteValue, PreviousPte) \
  3113. PreviousPte.u.Flush = *PtePointer; \
  3114. *PtePointer = PteValue; \
  3115. KeFlushEntireTb (TRUE, TRUE);
  3116. //++
  3117. //VOID
  3118. //MI_FLUSH_ENTIRE_SESSION_TB (
  3119. // IN ULONG Invalid,
  3120. // IN LOGICAL AllProcessors
  3121. // );
  3122. //
  3123. // Routine Description:
  3124. //
  3125. // MI_FLUSH_ENTIRE_SESSION_TB flushes the entire TB on IA64 since
  3126. // the IA64 supports ASNs.
  3127. //
  3128. // Arguments
  3129. //
  3130. // Invalid - TRUE if invalidating.
  3131. //
  3132. // AllProcessors - TRUE if all processors need to be IPI'd.
  3133. //
  3134. // Return Value:
  3135. //
  3136. // None.
  3137. //
  3138. #define MI_FLUSH_ENTIRE_SESSION_TB(Invalid, AllProcessors) \
  3139. KeFlushEntireTb (Invalid, AllProcessors);
  3140. VOID
  3141. MiSweepCacheMachineDependent (
  3142. IN PVOID VirtualAddress,
  3143. IN SIZE_T Size,
  3144. IN ULONG CacheAttribute
  3145. );
  3146. extern LOGICAL MiMappingsInitialized;
  3147. extern BOOLEAN MiKseg0Mapping;
  3148. extern PVOID MiKseg0Start;
  3149. extern PVOID MiKseg0End;
  3150. VOID
  3151. MiEliminateDriverTrEntries (
  3152. VOID
  3153. );
  3154. LOGICAL
  3155. MiIsVirtualAddressMappedByTr (
  3156. IN PVOID VirtualAddress
  3157. );
  3158. //++
  3159. //LOGICAL
  3160. //MI_RESERVED_BITS_CANONICAL (
  3161. // IN PVOID VirtualAddress
  3162. // );
  3163. //
  3164. // Routine Description:
  3165. //
  3166. // This routine checks whether all of the reserved bits are correct.
  3167. //
  3168. // The processor implements at least 51 bits of VA (in addition to the 3
  3169. // bits of VRN) - this is greater than the 43 bits of VA decode implemented
  3170. // by memory management so the VA is checked against 43 bits to prevent
  3171. // bogus address crashes which would not be caught by the processor.
  3172. //
  3173. // Arguments
  3174. //
  3175. // VirtualAddress - Supplies the virtual address to check.
  3176. //
  3177. // Return Value:
  3178. //
  3179. // TRUE if the address is ok, FALSE if not.
  3180. //
  3181. LOGICAL
  3182. __forceinline
  3183. MI_RESERVED_BITS_CANONICAL (
  3184. IN PVOID VirtualAddress
  3185. )
  3186. {
  3187. LONG_PTR ReservedBits;
  3188. ULONG_PTR ImplVirtualMsb;
  3189. PMMPTE PointerPte;
  3190. LOGICAL ReservedBitsOn;
  3191. //
  3192. // The address must be validated as NT-canonical. Note this is different
  3193. // than being processor-canonical (which must also be done as well). Of
  3194. // course if the NT validation is stricter then it is sufficient for both.
  3195. // Note however, there are certain addresses used by memory management for
  3196. // internal purposes (ie: McKinley page table VHPT space) which are never
  3197. // made visible to any external components and are thus allowed to violate
  3198. // the NT-canonical rule because it is not possible for anyone else to
  3199. // use them and thus they cannot encode values into them. (We don't want
  3200. // anyone trying to encode unused bits because if we ever expand the
  3201. // virtual address space, they will break).
  3202. //
  3203. // NT uses 43 bits of virtual address (not including VRN bits) and Merced
  3204. // has 51 while McKinley has 61. All valid Merced addresses can be
  3205. // validated via the 43 bit NT checking. However, McKinley VHPT addresses
  3206. // begin at 0x1FF8.0000.0000.0000, so they need to be checked separately.
  3207. //
  3208. ImplVirtualMsb = 43;
  3209. ReservedBitsOn = FALSE;
  3210. if ((ULONG_PTR)VirtualAddress & ((ULONG_PTR)1 << ImplVirtualMsb)) {
  3211. //
  3212. // All the reserved bits (not including the VRN) must also be set
  3213. // unless this is a special memory management-internal address.
  3214. //
  3215. ReservedBits = (LONG_PTR) VirtualAddress | VRN_MASK;
  3216. ReservedBits >>= (ImplVirtualMsb + 1);
  3217. if (ReservedBits != (LONG_PTR)-1) {
  3218. ReservedBitsOn = TRUE;
  3219. }
  3220. }
  3221. else {
  3222. //
  3223. // All the reserved bits (not including the VRN) must also be clear
  3224. // unless this is a special memory management-internal address.
  3225. //
  3226. ReservedBits = (LONG_PTR) VirtualAddress & ~VRN_MASK;
  3227. ReservedBits >>= (ImplVirtualMsb + 1);
  3228. if (ReservedBits != 0) {
  3229. ReservedBitsOn = TRUE;
  3230. }
  3231. }
  3232. //
  3233. // Note region registers are initialized for all regions so the VRN bits
  3234. // are stripped now for speed (ie: only the region 0 PTE ranges need to
  3235. // be checked below).
  3236. //
  3237. VirtualAddress = (PVOID) ((LONG_PTR) VirtualAddress & ~VRN_MASK);
  3238. if (ReservedBitsOn == FALSE) {
  3239. //
  3240. // No reserved bits were on, ensure that the virtual address is
  3241. // okay by ensuring the PPE/PDE/PTE are within bounds.
  3242. //
  3243. PointerPte = MiGetPteAddress (VirtualAddress);
  3244. }
  3245. else {
  3246. //
  3247. // Some reserved bits are on. This better be an internal address
  3248. // (ie: the McKinley VHPT), otherwise it's a bogus address.
  3249. //
  3250. // Note the Merced VHPT is NT-canonical so the checks below are
  3251. // no-ops on that processor, but this would be an error path on
  3252. // Merced anyway so the slight overhead is not critical.
  3253. //
  3254. PointerPte = (PMMPTE) VirtualAddress;
  3255. }
  3256. //
  3257. // Because the IA64 VHPT must cover the number of virtual address bits
  3258. // implemented by the processor and it must be on a natural boundary, the
  3259. // following window exists and must be explicitly checked for here.
  3260. //
  3261. // The initial Merced implementation supports 50 bits of virtual address.
  3262. // Hence the VHPT must cover 50-PAGE_SHIFT+PTE_SHIFT == 40 bits.
  3263. //
  3264. // However, NT uses PPE_PER_PAGE+PDE_PER_PAGE+PTE_PER_PAGE+PTE_SHIFT ==
  3265. // 33 bits.
  3266. //
  3267. // This seven bit difference between what the VHPT actually covers and
  3268. // what NT actually handles is what must be explicitly checked.
  3269. //
  3270. // Depending on what the VirtualAddress really represents, the PTE below
  3271. // may really be a PPE or PDE so check for all cases.
  3272. //
  3273. if ((PointerPte >= (PMMPTE)PTE_BASE) &&
  3274. (PointerPte < (PMMPTE)(PTE_BASE + (ULONG_PTR)PDE_PER_PAGE * PTE_PER_PAGE * PAGE_SIZE))) {
  3275. return TRUE;
  3276. }
  3277. if ((PointerPte >= (PMMPTE)PDE_BASE) &&
  3278. (PointerPte < (PMMPTE)(PDE_BASE + PDE_PER_PAGE * PAGE_SIZE))) {
  3279. return TRUE;
  3280. }
  3281. if ((PointerPte >= (PMMPTE)PDE_TBASE) &&
  3282. (PointerPte < (PMMPTE)(PDE_TBASE + PAGE_SIZE))) {
  3283. return TRUE;
  3284. }
  3285. return FALSE;
  3286. }
  3287. //++
  3288. //VOID
  3289. //MI_DISPLAY_TRAP_INFORMATION (
  3290. // IN PVOID TrapInformation
  3291. // );
  3292. //
  3293. // Routine Description:
  3294. //
  3295. // Display any relevant trap information to aid debugging.
  3296. //
  3297. // Arguments
  3298. //
  3299. // TrapInformation - Supplies a pointer to a trap frame.
  3300. //
  3301. // Return Value:
  3302. //
  3303. // None.
  3304. //
  3305. #define MI_DISPLAY_TRAP_INFORMATION(TrapInformation) \
  3306. KdPrint(("MM:***IIP %p, IIPA %p\n", \
  3307. ((PKTRAP_FRAME) (TrapInformation))->StIIP, \
  3308. ((PKTRAP_FRAME) (TrapInformation))->StIIPA));