Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3337 lines
81 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. miamd.h
  5. Abstract:
  6. This module contains the private data structures and procedure
  7. prototypes for the hardware dependent portion of the
  8. memory management system.
  9. This module is specifically tailored for the AMD 64-bit processor.
  10. Author:
  11. Landy Wang (landyw) 08-Apr-2000
  12. Revision History:
  13. --*/
  14. /*++
  15. Virtual Memory Layout on the AMD64 is:
  16. +------------------------------------+
  17. 0000000000000000 | User mode addresses - 8tb minus 64k|
  18. | |
  19. | |
  20. 000007FFFFFEFFFF | | MM_HIGHEST_USER_ADDRESS
  21. +------------------------------------+
  22. 000007FFFFFF0000 | 64k No Access Region | MM_USER_PROBE_ADDRESS
  23. 000007FFFFFFFFFF | |
  24. +------------------------------------+
  25. .
  26. +------------------------------------+
  27. FFFF080000000000 | Start of System space | MM_SYSTEM_RANGE_START
  28. +------------------------------------+
  29. FFFFF68000000000 | 512gb four level page table map. | PTE_BASE
  30. +------------------------------------+
  31. FFFFF70000000000 | HyperSpace - working set lists | HYPER_SPACE
  32. | and per process memory management |
  33. | structures mapped in this 512gb |
  34. | region. | HYPER_SPACE_END
  35. +------------------------------------+ MM_WORKING_SET_END
  36. FFFFF78000000000 | Shared system page | KI_USER_SHARED_DATA
  37. +------------------------------------+
  38. FFFFF78000001000 | The system cache working set | MM_SYSTEM_CACHE_WORKING_SET
  39. | information resides in this |
  40. | 512gb-4k region. |
  41. | |
  42. +------------------------------------+
  43. .
  44. .
  45. Note the ranges below are sign extended for > 43 bits and therefore
  46. can be used with interlocked slists. The system address space above is NOT.
  47. .
  48. .
  49. +------------------------------------+
  50. FFFFF80000000000 | Start of 1tb of | MM_KSEG0_BASE
  51. | physically addressable memory. | MM_KSEG2_BASE
  52. +------------------------------------+
  53. FFFFF90000000000 | win32k.sys |
  54. | |
  55. | Hydra configurations have session |
  56. | data structures here. |
  57. | |
  58. | This is a 512gb region. |
  59. +------------------------------------+
  60. | | MM_SYSTEM_SPACE_START
  61. FFFFF98000000000 | System cache resides here. | MM_SYSTEM_CACHE_START
  62. | Kernel mode access only. |
  63. | 1tb. |
  64. | | MM_SYSTEM_CACHE_END
  65. +------------------------------------+
  66. FFFFFA8000000000 | Start of paged system area. | MM_PAGED_POOL_START
  67. | Kernel mode access only. |
  68. | 128gb. |
  69. +------------------------------------+
  70. | System mapped views start just |
  71. | after paged pool. Default is |
  72. | 104MB, can be registry-overridden. |
  73. | 8GB maximum. |
  74. | |
  75. +------------------------------------+
  76. FFFFFAA000000000 | System PTE pool. | MM_LOWEST_NONPAGED_SYSTEM_START
  77. | Kernel mode access only. |
  78. | 128gb. |
  79. +------------------------------------+
  80. FFFFFAC000000000 | NonPaged pool. | MM_NON_PAGED_POOL_START
  81. | Kernel mode access only. |
  82. | 128gb. |
  83. | |
  84. FFFFFADFFFFFFFFF | NonPaged System area | MM_NONPAGED_POOL_END
  85. +------------------------------------+
  86. .
  87. .
  88. .
  89. .
  90. +------------------------------------+
  91. FFFFFFFF80000000 | |
  92. | Reserved for the HAL. 2gb. |
  93. FFFFFFFFFFFFFFFF | | MM_SYSTEM_SPACE_END
  94. +------------------------------------+
  95. --*/
  96. #define _MI_PAGING_LEVELS 4
  97. #define _MI_MORE_THAN_4GB_ 1
  98. #define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_AMD64
  99. //
  100. // Top level PXE mapping allocations:
  101. //
  102. // 0x0->0xF: 0x10 user entries
  103. // 0x1ed: 0x1 for selfmaps
  104. // 0x1ee: 0x1 hyperspace entry
  105. // 0x1ef: 0x1 entry for syscache WSL & shared user data
  106. // 0x1f0->0x1ff: 0x10 kernel entries
  107. //
  108. //
  109. // Define empty list markers.
  110. //
  111. #define MM_EMPTY_LIST ((ULONG_PTR)-1) //
  112. #define MM_EMPTY_PTE_LIST 0xFFFFFFFFUI64 // N.B. tied to MMPTE definition
  113. #define MI_PTE_BASE_FOR_LOWEST_KERNEL_ADDRESS (MiGetPteAddress (MM_KSEG0_BASE))
  114. #define MI_PTE_BASE_FOR_LOWEST_SESSION_ADDRESS (MiGetPteAddress (MM_SESSION_SPACE_DEFAULT))
  115. //
  116. // This is the size of the region used by the loader.
  117. //
  118. extern ULONG_PTR MmBootImageSize;
  119. //
  120. // PAGE_SIZE for AMD64 is 4k, virtual page is 36 bits with a PAGE_SHIFT
  121. // byte offset.
  122. //
  123. #define MM_VIRTUAL_PAGE_FILLER 0
  124. #define MM_VIRTUAL_PAGE_SIZE (48 - 12)
  125. //
  126. // Address space layout definitions.
  127. //
  128. #define MM_KSEG0_BASE 0xFFFFF80000000000UI64
  129. #define MM_KSEG2_BASE 0xFFFFF90000000000UI64
  130. #define MM_PAGES_IN_KSEG0 ((MM_KSEG2_BASE - MM_KSEG0_BASE) >> PAGE_SHIFT)
  131. #define MM_SYSTEM_SPACE_START 0xFFFFF98000000000UI64
  132. #define MM_SYSTEM_SPACE_END 0xFFFFFFFFFFFFFFFFUI64
  133. #define MM_USER_ADDRESS_RANGE_LIMIT 0xFFFFFFFFFFFFFFFF // user address range limit
  134. #define MM_MAXIMUM_ZERO_BITS 53 // maximum number of zero bits
  135. //
  136. // Define the start and maximum size for the system cache.
  137. //
  138. #define MM_SYSTEM_CACHE_START 0xFFFFF98000000000UI64
  139. #define MM_SYSTEM_CACHE_END 0xFFFFFA8000000000UI64
  140. #define MM_MAXIMUM_SYSTEM_CACHE_SIZE \
  141. ((MM_SYSTEM_CACHE_END - MM_SYSTEM_CACHE_START) >> PAGE_SHIFT)
  142. #define MM_SYSTEM_CACHE_WORKING_SET 0xFFFFF78000001000UI64
  143. //
  144. // Define area for mapping views into system space.
  145. //
  146. #define MM_SESSION_SPACE_DEFAULT_END 0xFFFFF98000000000UI64
  147. #define MM_SESSION_SPACE_DEFAULT (MM_SESSION_SPACE_DEFAULT_END - MI_SESSION_SPACE_MAXIMUM_TOTAL_SIZE)
  148. #define MM_SYSTEM_VIEW_SIZE (104 * 1024 * 1024)
  149. //
  150. // Various system resource locations.
  151. //
  152. #define MM_PAGED_POOL_START ((PVOID)0xFFFFFA8000000000)
  153. #define MM_LOWEST_NONPAGED_SYSTEM_START ((PVOID)0xFFFFFAA000000000)
  154. #define MM_NONPAGED_POOL_END ((PVOID)(0xFFFFFAE000000000))
  155. extern PVOID MmDebugVa;
  156. #define MM_DEBUG_VA MmDebugVa
  157. extern PVOID MmCrashDumpVa;
  158. #define MM_CRASH_DUMP_VA MmCrashDumpVa
  159. #define NON_PAGED_SYSTEM_END ((PVOID)0xFFFFFFFFFFFFFFF0)
  160. extern BOOLEAN MiWriteCombiningPtes;
  161. //
  162. // Define absolute minimum and maximum count for system PTEs.
  163. //
  164. #define MM_MINIMUM_SYSTEM_PTES 7000
  165. #define MM_MAXIMUM_SYSTEM_PTES (16*1024*1024)
  166. #define MM_DEFAULT_SYSTEM_PTES 11000
  167. //
  168. // Pool limits.
  169. //
  170. // The maximum amount of nonpaged pool that can be initially created.
  171. //
  172. #define MM_MAX_INITIAL_NONPAGED_POOL (128 * 1024 * 1024)
  173. //
  174. // The total amount of nonpaged pool (initial pool + expansion).
  175. //
  176. #define MM_MAX_ADDITIONAL_NONPAGED_POOL (((SIZE_T)128 * 1024 * 1024 * 1024))
  177. //
  178. // The maximum amount of paged pool that can be created.
  179. //
  180. #define MM_MAX_PAGED_POOL ((SIZE_T)128 * 1024 * 1024 * 1024)
  181. #define MM_MAX_DEFAULT_NONPAGED_POOL ((SIZE_T)8 * 1024 * 1024 * 1024)
  182. //
  183. // Structure layout definitions.
  184. //
  185. #define MM_PROTO_PTE_ALIGNMENT ((ULONG)MM_MAXIMUM_NUMBER_OF_COLORS * (ULONG)PAGE_SIZE)
  186. //
  187. // Define the address bits mapped by one PXE/PPE/PDE/PTE entry.
  188. //
  189. #define MM_VA_MAPPED_BY_PTE ((ULONG_PTR)PAGE_SIZE)
  190. #define MM_VA_MAPPED_BY_PDE (PTE_PER_PAGE * MM_VA_MAPPED_BY_PTE)
  191. #define MM_VA_MAPPED_BY_PPE (PDE_PER_PAGE * MM_VA_MAPPED_BY_PDE)
  192. #define MM_VA_MAPPED_BY_PXE (PPE_PER_PAGE * MM_VA_MAPPED_BY_PPE)
  193. //
  194. // Define the address bits mapped by PPE and PDE entries.
  195. //
  196. // A PXE entry maps 9+9+9+12 = 39 bits of address space.
  197. // A PPE entry maps 9+9+12 = 30 bits of address space.
  198. // A PDE entry maps 9+12 = 21 bits of address space.
  199. //
  200. #define PAGE_DIRECTORY0_MASK (MM_VA_MAPPED_BY_PXE - 1)
  201. #define PAGE_DIRECTORY1_MASK (MM_VA_MAPPED_BY_PPE - 1)
  202. #define PAGE_DIRECTORY2_MASK (MM_VA_MAPPED_BY_PDE - 1)
  203. #define PTE_SHIFT 3
  204. #define MM_MINIMUM_VA_FOR_LARGE_PAGE MM_VA_MAPPED_BY_PDE
  205. //
  206. // The number of bits in a virtual address.
  207. //
  208. #define VIRTUAL_ADDRESS_BITS 48
  209. #define VIRTUAL_ADDRESS_MASK ((((ULONG_PTR)1) << VIRTUAL_ADDRESS_BITS) - 1)
  210. //
  211. // The number of bits in a physical address.
  212. //
  213. #define PHYSICAL_ADDRESS_BITS 40
  214. #define MM_MAXIMUM_NUMBER_OF_COLORS (1)
  215. //
  216. // AMD64 does not require support for colored pages.
  217. //
  218. #define MM_NUMBER_OF_COLORS (1)
  219. //
  220. // Mask for obtaining color from a physical page number.
  221. //
  222. #define MM_COLOR_MASK (0)
  223. //
  224. // Boundary for aligned pages of like color upon.
  225. //
  226. #define MM_COLOR_ALIGNMENT (0)
  227. //
  228. // Mask for isolating color from virtual address.
  229. //
  230. #define MM_COLOR_MASK_VIRTUAL (0)
  231. //
  232. // Define 256k worth of secondary colors.
  233. //
  234. #define MM_SECONDARY_COLORS_DEFAULT (64)
  235. #define MM_SECONDARY_COLORS_MIN (2)
  236. #define MM_SECONDARY_COLORS_MAX (1024)
  237. //
  238. // Maximum number of paging files.
  239. //
  240. #define MAX_PAGE_FILES 16
  241. //
  242. // Hyper space definitions.
  243. //
  244. #define HYPER_SPACE ((PVOID)0xFFFFF70000000000)
  245. #define HYPER_SPACE_END 0xFFFFF77FFFFFFFFFUI64
  246. #define FIRST_MAPPING_PTE 0xFFFFF70000000000
  247. #define NUMBER_OF_MAPPING_PTES 126
  248. #define LAST_MAPPING_PTE \
  249. (FIRST_MAPPING_PTE + (NUMBER_OF_MAPPING_PTES * PAGE_SIZE))
  250. #define COMPRESSION_MAPPING_PTE ((PMMPTE)((ULONG_PTR)LAST_MAPPING_PTE + PAGE_SIZE))
  251. #define IMAGE_MAPPING_PTE ((PMMPTE)((ULONG_PTR)COMPRESSION_MAPPING_PTE + PAGE_SIZE))
  252. #define NUMBER_OF_ZEROING_PTES 256
  253. #define VAD_BITMAP_SPACE ((PVOID)((ULONG_PTR)IMAGE_MAPPING_PTE + PAGE_SIZE))
  254. #define WORKING_SET_LIST ((PVOID)((ULONG_PTR)VAD_BITMAP_SPACE + PAGE_SIZE))
  255. #define MM_MAXIMUM_WORKING_SET \
  256. ((((ULONG_PTR)8 * 1024 * 1024 * 1024 * 1024) - (64 * 1024 * 1024)) >> PAGE_SHIFT) //8Tb-64Mb
  257. #define MmWorkingSetList ((PMMWSL)WORKING_SET_LIST)
  258. #define MmWsle ((PMMWSLE)((PUCHAR)WORKING_SET_LIST + sizeof(MMWSL)))
  259. #define MM_WORKING_SET_END (HYPER_SPACE_END + 1)
  260. //
  261. // Define masks for fields within the PTE.
  262. //
  263. #define MM_PTE_VALID_MASK 0x1
  264. #if defined(NT_UP)
  265. #define MM_PTE_WRITE_MASK 0x2
  266. #else
  267. #define MM_PTE_WRITE_MASK 0x800
  268. #endif
  269. #define MM_PTE_OWNER_MASK 0x4
  270. #define MM_PTE_WRITE_THROUGH_MASK 0x8
  271. #define MM_PTE_CACHE_DISABLE_MASK 0x10
  272. #define MM_PTE_ACCESS_MASK 0x20
  273. #if defined(NT_UP)
  274. #define MM_PTE_DIRTY_MASK 0x40
  275. #else
  276. #define MM_PTE_DIRTY_MASK 0x42
  277. #endif
  278. #define MM_PTE_LARGE_PAGE_MASK 0x80
  279. #define MM_PTE_GLOBAL_MASK 0x100
  280. #define MM_PTE_COPY_ON_WRITE_MASK 0x200
  281. #define MM_PTE_PROTOTYPE_MASK 0x400
  282. #define MM_PTE_TRANSITION_MASK 0x800
  283. //
  284. // Bit fields to or into PTE to make a PTE valid based on the
  285. // protection field of the invalid PTE.
  286. //
  287. #define MM_PTE_NOACCESS 0x0 // not expressable on AMD64
  288. #define MM_PTE_READONLY 0x0
  289. #define MM_PTE_READWRITE MM_PTE_WRITE_MASK
  290. #define MM_PTE_WRITECOPY 0x200 // read-only copy on write bit set.
  291. #define MM_PTE_EXECUTE 0x0 // read-only on AMD64
  292. #define MM_PTE_EXECUTE_READ 0x0
  293. #define MM_PTE_EXECUTE_READWRITE MM_PTE_WRITE_MASK
  294. #define MM_PTE_EXECUTE_WRITECOPY 0x200 // read-only copy on write bit set.
  295. #define MM_PTE_NOCACHE 0x010
  296. #define MM_PTE_GUARD 0x0 // not expressable on AMD64
  297. #define MM_PTE_CACHE 0x0
  298. #define MM_PROTECT_FIELD_SHIFT 5
  299. //
  300. // Bits available for the software working set index within the hardware PTE.
  301. //
  302. #define MI_MAXIMUM_PTE_WORKING_SET_INDEX (1 << _HARDWARE_PTE_WORKING_SET_BITS)
  303. //
  304. // Zero PTE
  305. //
  306. #define MM_ZERO_PTE 0
  307. //
  308. // Zero Kernel PTE
  309. //
  310. #define MM_ZERO_KERNEL_PTE 0
  311. //
  312. // A demand zero PTE with a protection or PAGE_READWRITE.
  313. //
  314. #define MM_DEMAND_ZERO_WRITE_PTE (MM_READWRITE << MM_PROTECT_FIELD_SHIFT)
  315. //
  316. // A demand zero PTE with a protection or PAGE_READWRITE for system space.
  317. //
  318. #define MM_KERNEL_DEMAND_ZERO_PTE (MM_READWRITE << MM_PROTECT_FIELD_SHIFT)
  319. //
  320. // A no access PTE for system space.
  321. //
  322. #define MM_KERNEL_NOACCESS_PTE (MM_NOACCESS << MM_PROTECT_FIELD_SHIFT)
  323. //
  324. // Kernel stack alignment requirements.
  325. //
  326. #define MM_STACK_ALIGNMENT 0x0
  327. #define MM_STACK_OFFSET 0x0
  328. //
  329. // System process definitions
  330. //
  331. #define PXE_PER_PAGE 512
  332. #define PPE_PER_PAGE 512
  333. #define PDE_PER_PAGE 512
  334. #define PTE_PER_PAGE 512
  335. #define PTE_PER_PAGE_BITS 10 // This handles the case where the page is full
  336. #if PTE_PER_PAGE_BITS > 32
  337. error - too many bits to fit into MMPTE_SOFTWARE or MMPFN.u1
  338. #endif
  339. //
  340. // Number of page table pages for user addresses.
  341. //
  342. #define MM_USER_PXES (0x10)
  343. #define MM_USER_PAGE_TABLE_PAGES ((ULONG_PTR)PDE_PER_PAGE * PPE_PER_PAGE * MM_USER_PXES)
  344. #define MM_USER_PAGE_DIRECTORY_PAGES (PPE_PER_PAGE * MM_USER_PXES)
  345. #define MM_USER_PAGE_DIRECTORY_PARENT_PAGES (MM_USER_PXES)
  346. //++
  347. //VOID
  348. //MI_MAKE_VALID_PTE (
  349. // OUT OUTPTE,
  350. // IN FRAME,
  351. // IN PMASK,
  352. // IN PPTE
  353. // );
  354. //
  355. // Routine Description:
  356. //
  357. // This macro makes a valid PTE from a page frame number, protection mask,
  358. // and owner.
  359. //
  360. // Arguments
  361. //
  362. // OUTPTE - Supplies the PTE in which to build the transition PTE.
  363. //
  364. // FRAME - Supplies the page frame number for the PTE.
  365. //
  366. // PMASK - Supplies the protection to set in the transition PTE.
  367. //
  368. // PPTE - Supplies a pointer to the PTE which is being made valid.
  369. // For prototype PTEs NULL should be specified.
  370. //
  371. // Return Value:
  372. //
  373. // None.
  374. //
  375. //--
  376. #define MI_MAKE_VALID_PTE(OUTPTE, FRAME, PMASK, PPTE) { \
  377. (OUTPTE).u.Long = MmProtectToPteMask[PMASK] | MM_PTE_VALID_MASK; \
  378. (OUTPTE).u.Hard.PageFrameNumber = (FRAME); \
  379. (OUTPTE).u.Hard.Accessed = 1; \
  380. if (((PPTE) >= (PMMPTE)PDE_BASE) && ((PPTE) <= (PMMPTE)PDE_TOP)) { \
  381. (OUTPTE).u.Hard.NoExecute = 0; \
  382. } \
  383. if (MI_DETERMINE_OWNER(PPTE)) { \
  384. (OUTPTE).u.Long |= MM_PTE_OWNER_MASK; \
  385. } \
  386. if (((PMMPTE)PPTE) >= MiGetPteAddress(MM_SYSTEM_SPACE_START)) { \
  387. (OUTPTE).u.Hard.Global = 1; \
  388. } \
  389. }
  390. //++
  391. //VOID
  392. //MI_MAKE_VALID_PTE_TRANSITION (
  393. // IN OUT OUTPTE
  394. // IN PROTECT
  395. // );
  396. //
  397. // Routine Description:
  398. //
  399. // This macro takes a valid pte and turns it into a transition PTE.
  400. //
  401. // Arguments
  402. //
  403. // OUTPTE - Supplies the current valid PTE. This PTE is then
  404. // modified to become a transition PTE.
  405. //
  406. // PROTECT - Supplies the protection to set in the transition PTE.
  407. //
  408. // Return Value:
  409. //
  410. // None.
  411. //
  412. //--
  413. #define MI_MAKE_VALID_PTE_TRANSITION(OUTPTE,PROTECT) \
  414. (OUTPTE).u.Soft.Transition = 1; \
  415. (OUTPTE).u.Soft.Valid = 0; \
  416. (OUTPTE).u.Soft.Prototype = 0; \
  417. (OUTPTE).u.Soft.Protection = PROTECT;
  418. //++
  419. //VOID
  420. //MI_MAKE_TRANSITION_PTE (
  421. // OUT OUTPTE,
  422. // IN PAGE,
  423. // IN PROTECT,
  424. // IN PPTE
  425. // );
  426. //
  427. // Routine Description:
  428. //
  429. // This macro takes a valid pte and turns it into a transition PTE.
  430. //
  431. // Arguments
  432. //
  433. // OUTPTE - Supplies the PTE in which to build the transition PTE.
  434. //
  435. // PAGE - Supplies the page frame number for the PTE.
  436. //
  437. // PROTECT - Supplies the protection to set in the transition PTE.
  438. //
  439. // PPTE - Supplies a pointer to the PTE, this is used to determine
  440. // the owner of the PTE.
  441. //
  442. // Return Value:
  443. //
  444. // None.
  445. //
  446. //--
  447. #define MI_MAKE_TRANSITION_PTE(OUTPTE,PAGE,PROTECT,PPTE) \
  448. (OUTPTE).u.Long = 0; \
  449. (OUTPTE).u.Trans.PageFrameNumber = PAGE; \
  450. (OUTPTE).u.Trans.Transition = 1; \
  451. (OUTPTE).u.Trans.Protection = PROTECT; \
  452. (OUTPTE).u.Trans.Owner = MI_DETERMINE_OWNER(PPTE);
  453. //++
  454. //VOID
  455. //MI_MAKE_TRANSITION_PTE_VALID (
  456. // OUT OUTPTE,
  457. // IN PPTE
  458. // );
  459. //
  460. // Routine Description:
  461. //
  462. // This macro takes a transition pte and makes it a valid PTE.
  463. //
  464. // Arguments
  465. //
  466. // OUTPTE - Supplies the PTE in which to build the valid PTE.
  467. //
  468. // PPTE - Supplies a pointer to the transition PTE.
  469. //
  470. // Return Value:
  471. //
  472. // None.
  473. //
  474. //--
  475. #define MI_MAKE_TRANSITION_PTE_VALID(OUTPTE,PPTE) \
  476. ASSERT (((PPTE)->u.Hard.Valid == 0) && \
  477. ((PPTE)->u.Trans.Prototype == 0) && \
  478. ((PPTE)->u.Trans.Transition == 1)); \
  479. (OUTPTE).u.Long = MmProtectToPteMask[(PPTE)->u.Trans.Protection] | MM_PTE_VALID_MASK; \
  480. if (((PPTE) >= (PMMPTE)PDE_BASE) && ((PPTE) <= (PMMPTE)PDE_TOP)) { \
  481. (OUTPTE).u.Hard.NoExecute = 0; \
  482. } \
  483. (OUTPTE).u.Hard.PageFrameNumber = (PPTE)->u.Hard.PageFrameNumber; \
  484. if (MI_DETERMINE_OWNER(PPTE)) { \
  485. (OUTPTE).u.Long |= MM_PTE_OWNER_MASK; \
  486. } \
  487. if (((PMMPTE)PPTE) >= MiGetPteAddress(MM_SYSTEM_SPACE_START)) { \
  488. (OUTPTE).u.Hard.Global = 1; \
  489. } \
  490. (OUTPTE).u.Hard.Accessed = 1;
  491. //++
  492. //VOID
  493. //MI_MAKE_TRANSITION_PROTOPTE_VALID (
  494. // OUT OUTPTE,
  495. // IN PPTE
  496. // );
  497. //
  498. // Routine Description:
  499. //
  500. // This macro takes a transition prototype PTE (in paged pool) and
  501. // makes it a valid PTE. Because we know this is a prototype PTE and
  502. // not a pagetable PTE, this can directly or in the global bit. This
  503. // makes a measurable performance gain since every instruction counts
  504. // when holding the PFN lock.
  505. //
  506. // Arguments
  507. //
  508. // OUTPTE - Supplies the PTE in which to build the valid PTE.
  509. //
  510. // PPTE - Supplies a pointer to the transition PTE.
  511. //
  512. // Return Value:
  513. //
  514. // None.
  515. //
  516. //--
  517. #define MI_MAKE_TRANSITION_PROTOPTE_VALID(OUTPTE,PPTE) \
  518. ASSERT (((PPTE)->u.Hard.Valid == 0) && \
  519. ((PPTE)->u.Trans.Prototype == 0) && \
  520. ((PPTE)->u.Trans.Transition == 1)); \
  521. (OUTPTE).u.Long = MmProtectToPteMask[(PPTE)->u.Trans.Protection] | MM_PTE_VALID_MASK; \
  522. (OUTPTE).u.Hard.PageFrameNumber = (PPTE)->u.Hard.PageFrameNumber; \
  523. (OUTPTE).u.Hard.Global = 1; \
  524. (OUTPTE).u.Hard.Accessed = 1;
  525. #define MI_FAULT_STATUS_INDICATES_EXECUTION(_FaultStatus) (_FaultStatus & 0x8)
  526. #define MI_FAULT_STATUS_INDICATES_WRITE(_FaultStatus) (_FaultStatus & 0x1)
  527. #define MI_CLEAR_FAULT_STATUS(_FaultStatus) (_FaultStatus = 0)
  528. #define MI_IS_PTE_EXECUTABLE(_TempPte) ((_TempPte)->u.Hard.NoExecute == 0)
  529. //++
  530. //VOID
  531. //MI_SET_PTE_IN_WORKING_SET (
  532. // OUT PMMPTE PTE,
  533. // IN ULONG WSINDEX
  534. // );
  535. //
  536. // Routine Description:
  537. //
  538. // This macro inserts the specified working set index into the argument PTE.
  539. //
  540. // No TB invalidation is needed for other processors (or this one) even
  541. // though the entry may already be in a TB - it's just a software field
  542. // update and doesn't affect miss resolution.
  543. //
  544. // Arguments
  545. //
  546. // PTE - Supplies the PTE in which to insert the working set index.
  547. //
  548. // WSINDEX - Supplies the working set index for the PTE.
  549. //
  550. // Return Value:
  551. //
  552. // None.
  553. //
  554. //--
  555. #define MI_SET_PTE_IN_WORKING_SET(PTE, WSINDEX) { \
  556. MMPTE _TempPte; \
  557. _TempPte = *(PTE); \
  558. _TempPte.u.Hard.SoftwareWsIndex = (WSINDEX); \
  559. ASSERT (_TempPte.u.Long != 0); \
  560. *(PTE) = _TempPte; \
  561. }
  562. //++
  563. //ULONG WsIndex
  564. //MI_GET_WORKING_SET_FROM_PTE(
  565. // IN PMMPTE PTE
  566. // );
  567. //
  568. // Routine Description:
  569. //
  570. // This macro returns the working set index from the argument PTE.
  571. // Since the AMD64 PTE has no free bits nothing needs to be done on this
  572. // architecture.
  573. //
  574. // Arguments
  575. //
  576. // PTE - Supplies the PTE to extract the working set index from.
  577. //
  578. // Return Value:
  579. //
  580. // This macro returns the working set index for the argument PTE.
  581. //
  582. //--
  583. #define MI_GET_WORKING_SET_FROM_PTE(PTE) (ULONG)(PTE)->u.Hard.SoftwareWsIndex
  584. //++
  585. //VOID
  586. //MI_SET_PTE_WRITE_COMBINE (
  587. // IN MMPTE PTE
  588. // );
  589. //
  590. // Routine Description:
  591. //
  592. // This macro takes a valid PTE and enables WriteCombining as the
  593. // caching state. Note that the PTE bits may only be set this way
  594. // if the Page Attribute Table is present and the PAT has been
  595. // initialized to provide Write Combining.
  596. //
  597. // If either of the above conditions is not satisfied, then
  598. // the macro enables WEAK UC (PCD = 1, PWT = 0) in the PTE.
  599. //
  600. // Arguments
  601. //
  602. // PTE - Supplies a valid PTE.
  603. //
  604. // Return Value:
  605. //
  606. // None.
  607. //
  608. //--
  609. //
  610. #define MI_SET_PTE_WRITE_COMBINE(PTE) \
  611. { \
  612. if (MiWriteCombiningPtes == TRUE) { \
  613. ((PTE).u.Hard.CacheDisable = 0); \
  614. ((PTE).u.Hard.WriteThrough = 1); \
  615. } else { \
  616. ((PTE).u.Hard.CacheDisable = 1); \
  617. ((PTE).u.Hard.WriteThrough = 0); \
  618. } \
  619. }
  620. #define MI_SET_LARGE_PTE_WRITE_COMBINE(PTE) MI_SET_PTE_WRITE_COMBINE(PTE)
  621. //++
  622. //VOID
  623. //MI_PREPARE_FOR_NONCACHED (
  624. // IN MI_PFN_CACHE_ATTRIBUTE CacheAttribute
  625. // );
  626. //
  627. // Routine Description:
  628. //
  629. // This macro prepares the system prior to noncached PTEs being created.
  630. //
  631. // Arguments
  632. //
  633. // CacheAttribute - Supplies the cache attribute the PTEs will be filled
  634. // with.
  635. //
  636. // Return Value:
  637. //
  638. // None.
  639. //
  640. //--
  641. #define MI_PREPARE_FOR_NONCACHED(_CacheAttribute) \
  642. if (_CacheAttribute != MiCached) { \
  643. KeFlushEntireTb (FALSE, TRUE); \
  644. KeInvalidateAllCaches (); \
  645. }
  646. //++
  647. //VOID
  648. //MI_SWEEP_CACHE (
  649. // IN MI_PFN_CACHE_ATTRIBUTE CacheAttribute,
  650. // IN PVOID StartVa,
  651. // IN ULONG NumberOfBytes
  652. // );
  653. //
  654. // Routine Description:
  655. //
  656. // This macro prepares the system prior to noncached PTEs being created.
  657. // This does nothing on AMD64.
  658. //
  659. // Arguments
  660. //
  661. // CacheAttribute - Supplies the cache attribute the PTEs were filled with.
  662. //
  663. // StartVa - Supplies the starting address that's been mapped.
  664. //
  665. // NumberOfBytes - Supplies the number of bytes that have been mapped.
  666. //
  667. // Return Value:
  668. //
  669. // None.
  670. //
  671. //--
  672. #define MI_SWEEP_CACHE(_CacheType,_StartVa,_NumberOfBytes)
  673. //++
  674. //VOID
  675. //MI_SET_PTE_DIRTY (
  676. // IN MMPTE PTE
  677. // );
  678. //
  679. // Routine Description:
  680. //
  681. // This macro sets the dirty bit(s) in the specified PTE.
  682. //
  683. // Arguments
  684. //
  685. // PTE - Supplies the PTE to set dirty.
  686. //
  687. // Return Value:
  688. //
  689. // None.
  690. //
  691. //--
  692. #define MI_SET_PTE_DIRTY(PTE) (PTE).u.Long |= HARDWARE_PTE_DIRTY_MASK
  693. //++
  694. //VOID
  695. //MI_SET_PTE_CLEAN (
  696. // IN MMPTE PTE
  697. // );
  698. //
  699. // Routine Description:
  700. //
  701. // This macro clears the dirty bit(s) in the specified PTE.
  702. //
  703. // Arguments
  704. //
  705. // PTE - Supplies the PTE to set clear.
  706. //
  707. // Return Value:
  708. //
  709. // None.
  710. //
  711. //--
  712. #define MI_SET_PTE_CLEAN(PTE) (PTE).u.Long &= ~HARDWARE_PTE_DIRTY_MASK
  713. //++
  714. //VOID
  715. //MI_IS_PTE_DIRTY (
  716. // IN MMPTE PTE
  717. // );
  718. //
  719. // Routine Description:
  720. //
  721. // This macro checks the dirty bit(s) in the specified PTE.
  722. //
  723. // Arguments
  724. //
  725. // PTE - Supplies the PTE to check.
  726. //
  727. // Return Value:
  728. //
  729. // TRUE if the page is dirty (modified), FALSE otherwise.
  730. //
  731. //--
  732. #define MI_IS_PTE_DIRTY(PTE) ((PTE).u.Hard.Dirty != 0)
  733. //++
  734. //VOID
  735. //MI_SET_GLOBAL_STATE (
  736. // IN MMPTE PTE,
  737. // IN ULONG STATE
  738. // );
  739. //
  740. // Routine Description:
  741. //
  742. // This macro sets the global bit in the PTE. if the pointer PTE is within
  743. //
  744. // Arguments
  745. //
  746. // PTE - Supplies the PTE to set global state into.
  747. //
  748. // STATE - Supplies 1 if global, 0 if not.
  749. //
  750. // Return Value:
  751. //
  752. // None.
  753. //
  754. //--
  755. #define MI_SET_GLOBAL_STATE(PTE, STATE) (PTE).u.Hard.Global = STATE;
  756. //++
  757. //VOID
  758. //MI_ENABLE_CACHING (
  759. // IN MMPTE PTE
  760. // );
  761. //
  762. // Routine Description:
  763. //
  764. // This macro takes a valid PTE and sets the caching state to be
  765. // enabled. This is performed by clearing the PCD and PWT bits in the PTE.
  766. //
  767. // Semantics of the overlap between PCD, PWT, and the
  768. // USWC memory type in the MTRR are:
  769. //
  770. // PCD PWT Mtrr Mem Type Effective Memory Type
  771. // 1 0 USWC USWC
  772. // 1 1 USWC UC
  773. //
  774. // Arguments
  775. //
  776. // PTE - Supplies a valid PTE.
  777. //
  778. // Return Value:
  779. //
  780. // None.
  781. //
  782. //--
  783. #define MI_ENABLE_CACHING(PTE) \
  784. { \
  785. ((PTE).u.Hard.CacheDisable = 0); \
  786. ((PTE).u.Hard.WriteThrough = 0); \
  787. }
  788. //++
  789. //VOID
  790. //MI_DISABLE_CACHING (
  791. // IN MMPTE PTE
  792. // );
  793. //
  794. // Routine Description:
  795. //
  796. // This macro takes a valid PTE and sets the caching state to be
  797. // disabled. This is performed by setting the PCD and PWT bits in the PTE.
  798. //
  799. // Semantics of the overlap between PCD, PWT, and the
  800. // USWC memory type in the MTRR are:
  801. //
  802. // PCD PWT Mtrr Mem Type Effective Memory Type
  803. // 1 0 USWC USWC
  804. // 1 1 USWC UC
  805. //
  806. // Since an effective memory type of UC is desired here,
  807. // the WT bit is set.
  808. //
  809. // Arguments
  810. //
  811. // PTE - Supplies a pointer to the valid PTE.
  812. //
  813. // Return Value:
  814. //
  815. // None.
  816. //
  817. //--
  818. #define MI_DISABLE_CACHING(PTE) \
  819. { \
  820. ((PTE).u.Hard.CacheDisable = 1); \
  821. ((PTE).u.Hard.WriteThrough = 1); \
  822. }
  823. #define MI_DISABLE_LARGE_PTE_CACHING(PTE) MI_DISABLE_CACHING(PTE)
  824. //++
  825. //BOOLEAN
  826. //MI_IS_CACHING_DISABLED (
  827. // IN PMMPTE PPTE
  828. // );
  829. //
  830. // Routine Description:
  831. //
  832. // This macro takes a valid PTE and returns TRUE if caching is
  833. // disabled.
  834. //
  835. // Arguments
  836. //
  837. // PPTE - Supplies a pointer to the valid PTE.
  838. //
  839. // Return Value:
  840. //
  841. // TRUE if caching is disabled, FALSE if it is enabled.
  842. //
  843. //--
  844. #define MI_IS_CACHING_DISABLED(PPTE) \
  845. ((PPTE)->u.Hard.CacheDisable == 1)
  846. //++
  847. //VOID
  848. //MI_SET_PFN_DELETED (
  849. // IN PMMPFN PPFN
  850. // );
  851. //
  852. // Routine Description:
  853. //
  854. // This macro takes a pointer to a PFN element and indicates that
  855. // the PFN is no longer in use.
  856. //
  857. // Arguments
  858. //
  859. // PPTE - Supplies a pointer to the PFN element.
  860. //
  861. // Return Value:
  862. //
  863. // none.
  864. //
  865. //--
  866. #define MI_SET_PFN_DELETED(PPFN) \
  867. (PPFN)->PteAddress = (PMMPTE)((ULONG_PTR)PPFN->PteAddress | 0x1);
  868. //++
  869. //VOID
  870. //MI_MARK_PFN_UNDELETED (
  871. // IN PMMPFN PPFN
  872. // );
  873. //
  874. // Routine Description:
  875. //
  876. // This macro takes a pointer to a deleted PFN element and mark that
  877. // the PFN is not deleted.
  878. //
  879. // Arguments
  880. //
  881. // PPTE - Supplies a pointer to the PFN element.
  882. //
  883. // Return Value:
  884. //
  885. // none.
  886. //
  887. //--
  888. #define MI_MARK_PFN_UNDELETED(PPFN) \
  889. PPFN->PteAddress = (PMMPTE)((ULONG_PTR)PPFN->PteAddress & ~0x1);
  890. //++
  891. //BOOLEAN
  892. //MI_IS_PFN_DELETED (
  893. // IN PMMPFN PPFN
  894. // );
  895. //
  896. // Routine Description:
  897. //
  898. // This macro takes a pointer to a PFN element and determines if
  899. // the PFN is no longer in use.
  900. //
  901. // Arguments
  902. //
  903. // PPTE - Supplies a pointer to the PFN element.
  904. //
  905. // Return Value:
  906. //
  907. // TRUE if PFN is no longer used, FALSE if it is still being used.
  908. //
  909. //--
  910. #define MI_IS_PFN_DELETED(PPFN) \
  911. ((ULONG_PTR)(PPFN)->PteAddress & 0x1)
  912. //++
  913. //VOID
  914. //MI_CHECK_PAGE_ALIGNMENT (
  915. // IN ULONG PAGE,
  916. // IN PMMPTE PPTE
  917. // );
  918. //
  919. // Routine Description:
  920. //
  921. // This macro takes a PFN element number (Page) and checks to see
  922. // if the virtual alignment for the previous address of the page
  923. // is compatible with the new address of the page. If they are
  924. // not compatible, the D cache is flushed.
  925. //
  926. // Arguments
  927. //
  928. // PAGE - Supplies the PFN element.
  929. // PPTE - Supplies a pointer to the new PTE which will contain the page.
  930. //
  931. // Return Value:
  932. //
  933. // none.
  934. //
  935. //--
  936. // does nothing on AMD64.
  937. #define MI_CHECK_PAGE_ALIGNMENT(PAGE,PPTE)
  938. //++
  939. //VOID
  940. //MI_INITIALIZE_HYPERSPACE_MAP (
  941. // VOID
  942. // );
  943. //
  944. // Routine Description:
  945. //
  946. // This macro initializes the PTEs reserved for double mapping within
  947. // hyperspace.
  948. //
  949. // Arguments
  950. //
  951. // None.
  952. //
  953. // Return Value:
  954. //
  955. // None.
  956. //
  957. //--
  958. // does nothing on AMD64.
  959. #define MI_INITIALIZE_HYPERSPACE_MAP(INDEX)
  960. //++
  961. //ULONG
  962. //MI_GET_PAGE_COLOR_FROM_PTE (
  963. // IN PMMPTE PTEADDRESS
  964. // );
  965. //
  966. // Routine Description:
  967. //
  968. // This macro determines the page's color based on the PTE address
  969. // that maps the page.
  970. //
  971. // Arguments
  972. //
  973. // PTEADDRESS - Supplies the PTE address the page is (or was) mapped at.
  974. //
  975. // Return Value:
  976. //
  977. // The page's color.
  978. //
  979. //--
  980. #define MI_GET_PAGE_COLOR_FROM_PTE(PTEADDRESS) \
  981. (((ULONG)((MI_SYSTEM_PAGE_COLOR++) & MmSecondaryColorMask)) | MI_CURRENT_NODE_COLOR)
  982. //++
  983. //ULONG
  984. //MI_GET_PAGE_COLOR_FROM_VA (
  985. // IN PVOID ADDRESS
  986. // );
  987. //
  988. // Routine Description:
  989. //
  990. // This macro determines the page's color based on the PTE address
  991. // that maps the page.
  992. //
  993. // Arguments
  994. //
  995. // ADDRESS - Supplies the address the page is (or was) mapped at.
  996. //
  997. // Return Value:
  998. //
  999. // The page's color.
  1000. //
  1001. //--
  1002. #define MI_GET_PAGE_COLOR_FROM_VA(ADDRESS) \
  1003. (((ULONG)((MI_SYSTEM_PAGE_COLOR++) & MmSecondaryColorMask)) | MI_CURRENT_NODE_COLOR)
  1004. //++
  1005. //ULONG
  1006. //MI_GET_PAGE_COLOR_FROM_SESSION (
  1007. // IN PMM_SESSION_SPACE SessionSpace
  1008. // );
  1009. //
  1010. // Routine Description:
  1011. //
  1012. // This macro determines the page's color based on the PTE address
  1013. // that maps the page.
  1014. //
  1015. // Arguments
  1016. //
  1017. // SessionSpace - Supplies the session space the page will be mapped into.
  1018. //
  1019. // Return Value:
  1020. //
  1021. // The page's color.
  1022. //
  1023. //--
  1024. #define MI_GET_PAGE_COLOR_FROM_SESSION(_SessionSpace) \
  1025. (((ULONG)((_SessionSpace->Color++) & MmSecondaryColorMask)) | MI_CURRENT_NODE_COLOR)
  1026. //++
  1027. //ULONG
  1028. //MI_PAGE_COLOR_PTE_PROCESS (
  1029. // IN PCHAR COLOR,
  1030. // IN PMMPTE PTE
  1031. // );
  1032. //
  1033. // Routine Description:
  1034. //
  1035. // This macro determines the page's color based on the PTE address
  1036. // that maps the page.
  1037. //
  1038. // Arguments
  1039. //
  1040. //
  1041. // Return Value:
  1042. //
  1043. // The page's color.
  1044. //
  1045. //--
  1046. #define MI_PAGE_COLOR_PTE_PROCESS(PTE,COLOR) \
  1047. (((ULONG)((*(COLOR))++) & MmSecondaryColorMask) | MI_CURRENT_NODE_COLOR)
  1048. //++
  1049. //ULONG
  1050. //MI_PAGE_COLOR_VA_PROCESS (
  1051. // IN PVOID ADDRESS,
  1052. // IN PEPROCESS COLOR
  1053. // );
  1054. //
  1055. // Routine Description:
  1056. //
  1057. // This macro determines the page's color based on the PTE address
  1058. // that maps the page.
  1059. //
  1060. // Arguments
  1061. //
  1062. // ADDRESS - Supplies the address the page is (or was) mapped at.
  1063. //
  1064. // Return Value:
  1065. //
  1066. // The page's color.
  1067. //
  1068. //--
  1069. #define MI_PAGE_COLOR_VA_PROCESS(ADDRESS,COLOR) \
  1070. (((ULONG)((*(COLOR))++) & MmSecondaryColorMask) | MI_CURRENT_NODE_COLOR)
  1071. //++
  1072. //ULONG
  1073. //MI_GET_NEXT_COLOR (
  1074. // IN ULONG COLOR
  1075. // );
  1076. //
  1077. // Routine Description:
  1078. //
  1079. // This macro returns the next color in the sequence.
  1080. //
  1081. // Arguments
  1082. //
  1083. // COLOR - Supplies the color to return the next of.
  1084. //
  1085. // Return Value:
  1086. //
  1087. // Next color in sequence.
  1088. //
  1089. //--
  1090. #define MI_GET_NEXT_COLOR(COLOR) ((COLOR + 1) & MM_COLOR_MASK)
  1091. //++
  1092. //ULONG
  1093. //MI_GET_PREVIOUS_COLOR (
  1094. // IN ULONG COLOR
  1095. // );
  1096. //
  1097. // Routine Description:
  1098. //
  1099. // This macro returns the previous color in the sequence.
  1100. //
  1101. // Arguments
  1102. //
  1103. // COLOR - Supplies the color to return the previous of.
  1104. //
  1105. // Return Value:
  1106. //
  1107. // Previous color in sequence.
  1108. //
  1109. //--
  1110. #define MI_GET_PREVIOUS_COLOR(COLOR) (0)
  1111. #define MI_GET_SECONDARY_COLOR(PAGE,PFN) ((ULONG)(PAGE & MmSecondaryColorMask))
  1112. #define MI_GET_COLOR_FROM_SECONDARY(SECONDARY_COLOR) (0)
  1113. //++
  1114. //VOID
  1115. //MI_GET_MODIFIED_PAGE_BY_COLOR (
  1116. // OUT ULONG PAGE,
  1117. // IN ULONG COLOR
  1118. // );
  1119. //
  1120. // Routine Description:
  1121. //
  1122. // This macro returns the first page destined for a paging
  1123. // file with the desired color. It does NOT remove the page
  1124. // from its list.
  1125. //
  1126. // Arguments
  1127. //
  1128. // PAGE - Returns the page located, the value MM_EMPTY_LIST is
  1129. // returned if there is no page of the specified color.
  1130. //
  1131. // COLOR - Supplies the color of page to locate.
  1132. //
  1133. // Return Value:
  1134. //
  1135. // none.
  1136. //
  1137. //--
  1138. #define MI_GET_MODIFIED_PAGE_BY_COLOR(PAGE,COLOR) \
  1139. PAGE = MmModifiedPageListByColor[COLOR].Flink
  1140. //++
  1141. //VOID
  1142. //MI_GET_MODIFIED_PAGE_ANY_COLOR (
  1143. // OUT ULONG PAGE,
  1144. // IN OUT ULONG COLOR
  1145. // );
  1146. //
  1147. // Routine Description:
  1148. //
  1149. // This macro returns the first page destined for a paging
  1150. // file with the desired color. If not page of the desired
  1151. // color exists, all colored lists are searched for a page.
  1152. // It does NOT remove the page from its list.
  1153. //
  1154. // Arguments
  1155. //
  1156. // PAGE - Returns the page located, the value MM_EMPTY_LIST is
  1157. // returned if there is no page of the specified color.
  1158. //
  1159. // COLOR - Supplies the color of page to locate and returns the
  1160. // color of the page located.
  1161. //
  1162. // Return Value:
  1163. //
  1164. // none.
  1165. //
  1166. //--
  1167. #define MI_GET_MODIFIED_PAGE_ANY_COLOR(PAGE,COLOR) \
  1168. { \
  1169. if (MmTotalPagesForPagingFile == 0) { \
  1170. PAGE = MM_EMPTY_LIST; \
  1171. } else { \
  1172. PAGE = MmModifiedPageListByColor[COLOR].Flink; \
  1173. } \
  1174. }
  1175. //++
  1176. //VOID
  1177. //MI_MAKE_VALID_PTE_WRITE_COPY (
  1178. // IN OUT PMMPTE PTE
  1179. // );
  1180. //
  1181. // Routine Description:
  1182. //
  1183. // This macro checks to see if the PTE indicates that the
  1184. // page is writable and if so it clears the write bit and
  1185. // sets the copy-on-write bit.
  1186. //
  1187. // Arguments
  1188. //
  1189. // PTE - Supplies the PTE to operate upon.
  1190. //
  1191. // Return Value:
  1192. //
  1193. // None.
  1194. //
  1195. //--
  1196. #if defined(NT_UP)
  1197. #define MI_MAKE_VALID_PTE_WRITE_COPY(PPTE) \
  1198. if ((PPTE)->u.Hard.Write == 1) { \
  1199. (PPTE)->u.Hard.CopyOnWrite = 1; \
  1200. (PPTE)->u.Hard.Write = 0; \
  1201. }
  1202. #else
  1203. #define MI_MAKE_VALID_PTE_WRITE_COPY(PPTE) \
  1204. if ((PPTE)->u.Hard.Write == 1) { \
  1205. (PPTE)->u.Hard.CopyOnWrite = 1; \
  1206. (PPTE)->u.Hard.Write = 0; \
  1207. (PPTE)->u.Hard.Writable = 0; \
  1208. }
  1209. #endif
  1210. #define MI_PTE_OWNER_USER 1
  1211. #define MI_PTE_OWNER_KERNEL 0
  1212. //++
  1213. //ULONG
  1214. //MI_DETERMINE_OWNER (
  1215. // IN MMPTE PPTE
  1216. // );
  1217. //
  1218. // Routine Description:
  1219. //
  1220. // This macro examines the virtual address of the PTE and determines
  1221. // if the PTE resides in system space or user space.
  1222. //
  1223. // Arguments
  1224. //
  1225. // PTE - Supplies the PTE to operate upon.
  1226. //
  1227. // Return Value:
  1228. //
  1229. // 1 if the owner is USER_MODE, 0 if the owner is KERNEL_MODE.
  1230. //
  1231. //--
  1232. #define MI_DETERMINE_OWNER(PPTE) \
  1233. ((((PPTE) <= MiHighestUserPte) || \
  1234. ((PPTE) >= MiGetPdeAddress(NULL) && ((PPTE) <= MiHighestUserPde)) || \
  1235. ((PPTE) >= MiGetPpeAddress(NULL) && ((PPTE) <= MiHighestUserPpe)) || \
  1236. ((PPTE) >= MiGetPxeAddress(NULL) && ((PPTE) <= MiHighestUserPxe))) \
  1237. ? MI_PTE_OWNER_USER : MI_PTE_OWNER_KERNEL)
  1238. //++
  1239. //VOID
  1240. //MI_SET_ACCESSED_IN_PTE (
  1241. // IN OUT MMPTE PPTE,
  1242. // IN ULONG ACCESSED
  1243. // );
  1244. //
  1245. // Routine Description:
  1246. //
  1247. // This macro sets the ACCESSED field in the PTE.
  1248. //
  1249. // Arguments
  1250. //
  1251. // PTE - Supplies the PTE to operate upon.
  1252. //
  1253. // Return Value:
  1254. //
  1255. // None
  1256. //
  1257. //--
  1258. #define MI_SET_ACCESSED_IN_PTE(PPTE,ACCESSED) \
  1259. ((PPTE)->u.Hard.Accessed = ACCESSED)
  1260. //++
  1261. //ULONG
  1262. //MI_GET_ACCESSED_IN_PTE (
  1263. // IN OUT MMPTE PPTE
  1264. // );
  1265. //
  1266. // Routine Description:
  1267. //
  1268. // This macro returns the state of the ACCESSED field in the PTE.
  1269. //
  1270. // Arguments
  1271. //
  1272. // PTE - Supplies the PTE to operate upon.
  1273. //
  1274. // Return Value:
  1275. //
  1276. // The state of the ACCESSED field.
  1277. //
  1278. //--
  1279. #define MI_GET_ACCESSED_IN_PTE(PPTE) ((PPTE)->u.Hard.Accessed)
  1280. //++
  1281. //VOID
  1282. //MI_SET_OWNER_IN_PTE (
  1283. // IN PMMPTE PPTE
  1284. // IN ULONG OWNER
  1285. // );
  1286. //
  1287. // Routine Description:
  1288. //
  1289. // This macro sets the owner field in the PTE.
  1290. //
  1291. // Arguments
  1292. //
  1293. // PTE - Supplies the PTE to operate upon.
  1294. //
  1295. // Return Value:
  1296. //
  1297. // None.
  1298. //
  1299. //--
  1300. #define MI_SET_OWNER_IN_PTE(PPTE,OWNER) ((PPTE)->u.Hard.Owner = OWNER)
  1301. //
  1302. // Mask to clear all fields but protection in a PTE to or in paging file
  1303. // location.
  1304. //
  1305. #define CLEAR_FOR_PAGE_FILE 0x000003E0
  1306. //++
  1307. //VOID
  1308. //MI_SET_PAGING_FILE_INFO (
  1309. // OUT MMPTE OUTPTE,
  1310. // IN MMPTE PPTE,
  1311. // IN ULONG FILEINFO,
  1312. // IN ULONG OFFSET
  1313. // );
  1314. //
  1315. // Routine Description:
  1316. //
  1317. // This macro sets into the specified PTE the supplied information
  1318. // to indicate where the backing store for the page is located.
  1319. //
  1320. // Arguments
  1321. //
  1322. // OUTPTE - Supplies the PTE in which to store the result.
  1323. //
  1324. // PTE - Supplies the PTE to operate upon.
  1325. //
  1326. // FILEINFO - Supplies the number of the paging file.
  1327. //
  1328. // OFFSET - Supplies the offset into the paging file.
  1329. //
  1330. // Return Value:
  1331. //
  1332. // None.
  1333. //
  1334. //--
  1335. #define MI_SET_PAGING_FILE_INFO(OUTPTE,PPTE,FILEINFO,OFFSET) \
  1336. (OUTPTE).u.Long = (PPTE).u.Long; \
  1337. (OUTPTE).u.Long &= CLEAR_FOR_PAGE_FILE; \
  1338. (OUTPTE).u.Long |= (FILEINFO << 1); \
  1339. (OUTPTE).u.Soft.PageFileHigh = (OFFSET);
  1340. //++
  1341. //PMMPTE
  1342. //MiPteToProto (
  1343. // IN OUT MMPTE PPTE,
  1344. // IN ULONG FILEINFO,
  1345. // IN ULONG OFFSET
  1346. // );
  1347. //
  1348. // Routine Description:
  1349. //
  1350. // This macro returns the address of the corresponding prototype which
  1351. // was encoded earlier into the supplied PTE.
  1352. //
  1353. // Arguments
  1354. //
  1355. // lpte - Supplies the PTE to operate upon.
  1356. //
  1357. // Return Value:
  1358. //
  1359. // Pointer to the prototype PTE that backs this PTE.
  1360. //
  1361. //--
  1362. #define MiPteToProto(lpte) \
  1363. ((PMMPTE)((lpte)->u.Proto.ProtoAddress))
  1364. //++
  1365. //ULONG
  1366. //MiProtoAddressForPte (
  1367. // IN PMMPTE proto_va
  1368. // );
  1369. //
  1370. // Routine Description:
  1371. //
  1372. // This macro sets into the specified PTE the supplied information
  1373. // to indicate where the backing store for the page is located.
  1374. // MiProtoAddressForPte returns the bit field to OR into the PTE to
  1375. // reference a prototype PTE. And set the protoPTE bit,
  1376. // MM_PTE_PROTOTYPE_MASK.
  1377. //
  1378. // Arguments
  1379. //
  1380. // proto_va - Supplies the address of the prototype PTE.
  1381. //
  1382. // Return Value:
  1383. //
  1384. // Mask to set into the PTE.
  1385. //
  1386. //--
  1387. #define MiProtoAddressForPte(proto_va) \
  1388. (((ULONG_PTR)proto_va << 16) | MM_PTE_PROTOTYPE_MASK)
  1389. //++
  1390. //ULONG
  1391. //MiProtoAddressForKernelPte (
  1392. // IN PMMPTE proto_va
  1393. // );
  1394. //
  1395. // Routine Description:
  1396. //
  1397. // This macro sets into the specified PTE the supplied information
  1398. // to indicate where the backing store for the page is located.
  1399. // MiProtoAddressForPte returns the bit field to OR into the PTE to
  1400. // reference a prototype PTE. And set the protoPTE bit,
  1401. // MM_PTE_PROTOTYPE_MASK.
  1402. //
  1403. // This macro also sets any other information (such as global bits)
  1404. // required for kernel mode PTEs.
  1405. //
  1406. // Arguments
  1407. //
  1408. // proto_va - Supplies the address of the prototype PTE.
  1409. //
  1410. // Return Value:
  1411. //
  1412. // Mask to set into the PTE.
  1413. //
  1414. //--
  1415. // not different on AMD64.
  1416. #define MiProtoAddressForKernelPte(proto_va) MiProtoAddressForPte(proto_va)
  1417. //++
  1418. //PSUBSECTION
  1419. //MiGetSubsectionAddress (
  1420. // IN PMMPTE lpte
  1421. // );
  1422. //
  1423. // Routine Description:
  1424. //
  1425. // This macro takes a PTE and returns the address of the subsection that
  1426. // the PTE refers to. Subsections are quadword structures allocated
  1427. // from nonpaged pool.
  1428. //
  1429. // Arguments
  1430. //
  1431. // lpte - Supplies the PTE to operate upon.
  1432. //
  1433. // Return Value:
  1434. //
  1435. // A pointer to the subsection referred to by the supplied PTE.
  1436. //
  1437. //--
  1438. #define MiGetSubsectionAddress(lpte) \
  1439. ((PSUBSECTION)((lpte)->u.Subsect.SubsectionAddress))
  1440. //++
  1441. //ULONG
  1442. //MiGetSubsectionAddressForPte (
  1443. // IN PSUBSECTION VA
  1444. // );
  1445. //
  1446. // Routine Description:
  1447. //
  1448. // This macro takes the address of a subsection and encodes it for use
  1449. // in a PTE.
  1450. //
  1451. // Arguments
  1452. //
  1453. // VA - Supplies a pointer to the subsection to encode.
  1454. //
  1455. // Return Value:
  1456. //
  1457. // The mask to set into the PTE to make it reference the supplied
  1458. // subsection.
  1459. //
  1460. //--
  1461. #define MiGetSubsectionAddressForPte(VA) ((ULONGLONG)VA << 16)
  1462. //++
  1463. //PMMPTE
  1464. //MiGetPxeAddress (
  1465. // IN PVOID va
  1466. // );
  1467. //
  1468. // Routine Description:
  1469. //
  1470. // MiGetPxeAddress returns the address of the extended page directory parent
  1471. // entry which maps the given virtual address. This is one level above the
  1472. // page parent directory.
  1473. //
  1474. // Arguments
  1475. //
  1476. // Va - Supplies the virtual address to locate the PXE for.
  1477. //
  1478. // Return Value:
  1479. //
  1480. // The address of the PXE.
  1481. //
  1482. //--
  1483. #define MiGetPxeAddress(va) ((PMMPTE)PXE_BASE + MiGetPxeOffset(va))
  1484. //++
  1485. //PMMPTE
  1486. //MiGetPpeAddress (
  1487. // IN PVOID va
  1488. // );
  1489. //
  1490. // Routine Description:
  1491. //
  1492. // MiGetPpeAddress returns the address of the page directory parent entry
  1493. // which maps the given virtual address. This is one level above the
  1494. // page directory.
  1495. //
  1496. // Arguments
  1497. //
  1498. // Va - Supplies the virtual address to locate the PPE for.
  1499. //
  1500. // Return Value:
  1501. //
  1502. // The address of the PPE.
  1503. //
  1504. //--
  1505. #define MiGetPpeAddress(va) \
  1506. ((PMMPTE)(((((ULONG_PTR)(va) & VIRTUAL_ADDRESS_MASK) >> PPI_SHIFT) << PTE_SHIFT) + PPE_BASE))
  1507. //++
  1508. //PMMPTE
  1509. //MiGetPdeAddress (
  1510. // IN PVOID va
  1511. // );
  1512. //
  1513. // Routine Description:
  1514. //
  1515. // MiGetPdeAddress returns the address of the PDE which maps the
  1516. // given virtual address.
  1517. //
  1518. // Arguments
  1519. //
  1520. // Va - Supplies the virtual address to locate the PDE for.
  1521. //
  1522. // Return Value:
  1523. //
  1524. // The address of the PDE.
  1525. //
  1526. //--
  1527. #define MiGetPdeAddress(va) \
  1528. ((PMMPTE)(((((ULONG_PTR)(va) & VIRTUAL_ADDRESS_MASK) >> PDI_SHIFT) << PTE_SHIFT) + PDE_BASE))
  1529. //++
  1530. //PMMPTE
  1531. //MiGetPteAddress (
  1532. // IN PVOID va
  1533. // );
  1534. //
  1535. // Routine Description:
  1536. //
  1537. // MiGetPteAddress returns the address of the PTE which maps the
  1538. // given virtual address.
  1539. //
  1540. // Arguments
  1541. //
  1542. // Va - Supplies the virtual address to locate the PTE for.
  1543. //
  1544. // Return Value:
  1545. //
  1546. // The address of the PTE.
  1547. //
  1548. //--
  1549. #define MiGetPteAddress(va) \
  1550. ((PMMPTE)(((((ULONG_PTR)(va) & VIRTUAL_ADDRESS_MASK) >> PTI_SHIFT) << PTE_SHIFT) + PTE_BASE))
  1551. //++
  1552. //ULONG
  1553. //MiGetPxeOffset (
  1554. // IN PVOID va
  1555. // );
  1556. //
  1557. // Routine Description:
  1558. //
  1559. // MiGetPxeOffset returns the offset into an extended page directory parent
  1560. // for a given virtual address.
  1561. //
  1562. // Arguments
  1563. //
  1564. // Va - Supplies the virtual address to locate the offset for.
  1565. //
  1566. // Return Value:
  1567. //
  1568. // The offset into the extended parent page directory table the corresponding
  1569. // PXE is at.
  1570. //
  1571. //--
  1572. #define MiGetPxeOffset(va) ((ULONG)(((ULONG_PTR)(va) >> PXI_SHIFT) & PXI_MASK))
  1573. //++
  1574. //ULONG
  1575. //MiGetPxeIndex (
  1576. // IN PVOID va
  1577. // );
  1578. //
  1579. // Routine Description:
  1580. //
  1581. // MiGetPxeIndex returns the extended page directory parent index
  1582. // for a given virtual address.
  1583. //
  1584. // N.B. This does not mask off PXE bits.
  1585. //
  1586. // Arguments
  1587. //
  1588. // Va - Supplies the virtual address to locate the index for.
  1589. //
  1590. // Return Value:
  1591. //
  1592. // The index into the extended page directory parent - ie: the virtual page
  1593. // directory parent number. This is different from the extended page
  1594. // directory parent offset because this spans extended page directory
  1595. // parents on supported platforms.
  1596. //
  1597. //--
  1598. #define MiGetPxeIndex(va) ((ULONG)((ULONG_PTR)(va) >> PXI_SHIFT))
  1599. //++
  1600. //ULONG
  1601. //MiGetPpeOffset (
  1602. // IN PVOID va
  1603. // );
  1604. //
  1605. // Routine Description:
  1606. //
  1607. // MiGetPpeOffset returns the offset into a page directory parent for a
  1608. // given virtual address.
  1609. //
  1610. // Arguments
  1611. //
  1612. // Va - Supplies the virtual address to locate the offset for.
  1613. //
  1614. // Return Value:
  1615. //
  1616. // The offset into the parent page directory table the corresponding
  1617. // PPE is at.
  1618. //
  1619. //--
  1620. #define MiGetPpeOffset(va) ((ULONG)(((ULONG_PTR)(va) >> PPI_SHIFT) & PPI_MASK))
  1621. //++
  1622. //ULONG
  1623. //MiGetPpeIndex (
  1624. // IN PVOID va
  1625. // );
  1626. //
  1627. // Routine Description:
  1628. //
  1629. // MiGetPpeIndex returns the page directory parent index
  1630. // for a given virtual address.
  1631. //
  1632. // N.B. This does not mask off PXE bits.
  1633. //
  1634. // Arguments
  1635. //
  1636. // Va - Supplies the virtual address to locate the index for.
  1637. //
  1638. // Return Value:
  1639. //
  1640. // The index into the page directory parent - ie: the virtual page directory
  1641. // number. This is different from the page directory parent offset because
  1642. // this spans page directory parents on supported platforms.
  1643. //
  1644. //--
  1645. #define MiGetPpeIndex(va) ((ULONG)((ULONG_PTR)(va) >> PPI_SHIFT))
  1646. //++
  1647. //ULONG
  1648. //MiGetPdeOffset (
  1649. // IN PVOID va
  1650. // );
  1651. //
  1652. // Routine Description:
  1653. //
  1654. // MiGetPdeOffset returns the offset into a page directory
  1655. // for a given virtual address.
  1656. //
  1657. // Arguments
  1658. //
  1659. // Va - Supplies the virtual address to locate the offset for.
  1660. //
  1661. // Return Value:
  1662. //
  1663. // The offset into the page directory table the corresponding PDE is at.
  1664. //
  1665. //--
  1666. #define MiGetPdeOffset(va) ((ULONG)(((ULONG_PTR)(va) >> PDI_SHIFT) & PDI_MASK))
  1667. //++
  1668. //ULONG
  1669. //MiGetPdeIndex (
  1670. // IN PVOID va
  1671. // );
  1672. //
  1673. // Routine Description:
  1674. //
  1675. // MiGetPdeIndex returns the page directory index
  1676. // for a given virtual address.
  1677. //
  1678. // N.B. This does not mask off PPE or PXE bits.
  1679. //
  1680. // Arguments
  1681. //
  1682. // Va - Supplies the virtual address to locate the index for.
  1683. //
  1684. // Return Value:
  1685. //
  1686. // The index into the page directory - ie: the virtual page table number.
  1687. // This is different from the page directory offset because this spans
  1688. // page directories on supported platforms.
  1689. //
  1690. //--
  1691. #define MiGetPdeIndex(va) ((ULONG)((ULONG_PTR)(va) >> PDI_SHIFT))
  1692. //++
  1693. //ULONG
  1694. //MiGetPteOffset (
  1695. // IN PVOID va
  1696. // );
  1697. //
  1698. // Routine Description:
  1699. //
  1700. // MiGetPteOffset returns the offset into a page table page
  1701. // for a given virtual address.
  1702. //
  1703. // Arguments
  1704. //
  1705. // Va - Supplies the virtual address to locate the offset for.
  1706. //
  1707. // Return Value:
  1708. //
  1709. // The offset into the page table page table the corresponding PTE is at.
  1710. //
  1711. //--
  1712. #define MiGetPteOffset(va) ((ULONG)(((ULONG_PTR)(va) >> PTI_SHIFT) & PTI_MASK))
  1713. //++
  1714. //PVOID
  1715. //MiGetVirtualAddressMappedByPxe (
  1716. // IN PMMPTE PTE
  1717. // );
  1718. //
  1719. // Routine Description:
  1720. //
  1721. // MiGetVirtualAddressMappedByPxe returns the virtual address
  1722. // which is mapped by a given PXE address.
  1723. //
  1724. // Arguments
  1725. //
  1726. // PXE - Supplies the PXE to get the virtual address for.
  1727. //
  1728. // Return Value:
  1729. //
  1730. // Virtual address mapped by the PXE.
  1731. //
  1732. //--
  1733. #define MiGetVirtualAddressMappedByPxe(PXE) \
  1734. MiGetVirtualAddressMappedByPde(MiGetVirtualAddressMappedByPde(PXE))
  1735. //++
  1736. //PVOID
  1737. //MiGetVirtualAddressMappedByPpe (
  1738. // IN PMMPTE PTE
  1739. // );
  1740. //
  1741. // Routine Description:
  1742. //
  1743. // MiGetVirtualAddressMappedByPpe returns the virtual address
  1744. // which is mapped by a given PPE address.
  1745. //
  1746. // Arguments
  1747. //
  1748. // PPE - Supplies the PPE to get the virtual address for.
  1749. //
  1750. // Return Value:
  1751. //
  1752. // Virtual address mapped by the PPE.
  1753. //
  1754. //--
  1755. #define MiGetVirtualAddressMappedByPpe(PPE) \
  1756. MiGetVirtualAddressMappedByPte(MiGetVirtualAddressMappedByPde(PPE))
  1757. //++
  1758. //PVOID
  1759. //MiGetVirtualAddressMappedByPde (
  1760. // IN PMMPTE PTE
  1761. // );
  1762. //
  1763. // Routine Description:
  1764. //
  1765. // MiGetVirtualAddressMappedByPde returns the virtual address
  1766. // which is mapped by a given PDE address.
  1767. //
  1768. // Arguments
  1769. //
  1770. // PDE - Supplies the PDE to get the virtual address for.
  1771. //
  1772. // Return Value:
  1773. //
  1774. // Virtual address mapped by the PDE.
  1775. //
  1776. //--
  1777. #define MiGetVirtualAddressMappedByPde(PDE) \
  1778. MiGetVirtualAddressMappedByPte(MiGetVirtualAddressMappedByPte(PDE))
  1779. //++
  1780. //PVOID
  1781. //MiGetVirtualAddressMappedByPte (
  1782. // IN PMMPTE PTE
  1783. // );
  1784. //
  1785. // Routine Description:
  1786. //
  1787. // MiGetVirtualAddressMappedByPte returns the virtual address
  1788. // which is mapped by a given PTE address.
  1789. //
  1790. // Arguments
  1791. //
  1792. // PTE - Supplies the PTE to get the virtual address for.
  1793. //
  1794. // Return Value:
  1795. //
  1796. // Virtual address mapped by the PTE.
  1797. //
  1798. //--
  1799. #define VA_SHIFT (63 - 47) // address sign extend shift count
  1800. #define MiGetVirtualAddressMappedByPte(PTE) \
  1801. ((PVOID)((LONG_PTR)(((LONG_PTR)(PTE) - PTE_BASE) << (PAGE_SHIFT + VA_SHIFT - PTE_SHIFT)) >> VA_SHIFT))
  1802. //++
  1803. //LOGICAL
  1804. //MiIsVirtualAddressOnPxeBoundary (
  1805. // IN PVOID VA
  1806. // );
  1807. //
  1808. // Routine Description:
  1809. //
  1810. // MiIsVirtualAddressOnPxeBoundary returns TRUE if the virtual address is
  1811. // on an extended page directory parent entry boundary.
  1812. //
  1813. // Arguments
  1814. //
  1815. // VA - Supplies the virtual address to check.
  1816. //
  1817. // Return Value:
  1818. //
  1819. // TRUE if on a boundary, FALSE if not.
  1820. //
  1821. //--
  1822. #define MiIsVirtualAddressOnPxeBoundary(VA) (((ULONG_PTR)(VA) & PAGE_DIRECTORY0_MASK) == 0)
  1823. //++
  1824. //LOGICAL
  1825. //MiIsVirtualAddressOnPpeBoundary (
  1826. // IN PVOID VA
  1827. // );
  1828. //
  1829. // Routine Description:
  1830. //
  1831. // MiIsVirtualAddressOnPpeBoundary returns TRUE if the virtual address is
  1832. // on a page directory entry boundary.
  1833. //
  1834. // Arguments
  1835. //
  1836. // VA - Supplies the virtual address to check.
  1837. //
  1838. // Return Value:
  1839. //
  1840. // TRUE if on a boundary, FALSE if not.
  1841. //
  1842. //--
  1843. #define MiIsVirtualAddressOnPpeBoundary(VA) (((ULONG_PTR)(VA) & PAGE_DIRECTORY1_MASK) == 0)
  1844. //++
  1845. //LOGICAL
  1846. //MiIsVirtualAddressOnPdeBoundary (
  1847. // IN PVOID VA
  1848. // );
  1849. //
  1850. // Routine Description:
  1851. //
  1852. // MiIsVirtualAddressOnPdeBoundary returns TRUE if the virtual address is
  1853. // on a page directory entry boundary.
  1854. //
  1855. // Arguments
  1856. //
  1857. // VA - Supplies the virtual address to check.
  1858. //
  1859. // Return Value:
  1860. //
  1861. // TRUE if on a 2MB PDE boundary, FALSE if not.
  1862. //
  1863. //--
  1864. #define MiIsVirtualAddressOnPdeBoundary(VA) (((ULONG_PTR)(VA) & PAGE_DIRECTORY2_MASK) == 0)
  1865. //++
  1866. //LOGICAL
  1867. //MiIsPteOnPxeBoundary (
  1868. // IN PVOID PTE
  1869. // );
  1870. //
  1871. // Routine Description:
  1872. //
  1873. // MiIsPteOnPxeBoundary returns TRUE if the PTE is
  1874. // on an extended page directory parent entry boundary.
  1875. //
  1876. // Arguments
  1877. //
  1878. // PTE - Supplies the PTE to check.
  1879. //
  1880. // Return Value:
  1881. //
  1882. // TRUE if on a boundary, FALSE if not.
  1883. //
  1884. //--
  1885. #define MiIsPteOnPxeBoundary(PTE) (((ULONG_PTR)(PTE) & (PAGE_DIRECTORY1_MASK)) == 0)
  1886. //++
  1887. //LOGICAL
  1888. //MiIsPteOnPpeBoundary (
  1889. // IN PVOID PTE
  1890. // );
  1891. //
  1892. // Routine Description:
  1893. //
  1894. // MiIsPteOnPpeBoundary returns TRUE if the PTE is
  1895. // on a page directory parent entry boundary.
  1896. //
  1897. // Arguments
  1898. //
  1899. // PTE - Supplies the PTE to check.
  1900. //
  1901. // Return Value:
  1902. //
  1903. // TRUE if on a boundary, FALSE if not.
  1904. //
  1905. //--
  1906. #define MiIsPteOnPpeBoundary(PTE) (((ULONG_PTR)(PTE) & (PAGE_DIRECTORY2_MASK)) == 0)
  1907. //++
  1908. //LOGICAL
  1909. //MiIsPteOnPdeBoundary (
  1910. // IN PVOID PTE
  1911. // );
  1912. //
  1913. // Routine Description:
  1914. //
  1915. // MiIsPteOnPdeBoundary returns TRUE if the PTE is
  1916. // on a page directory entry boundary.
  1917. //
  1918. // Arguments
  1919. //
  1920. // PTE - Supplies the PTE to check.
  1921. //
  1922. // Return Value:
  1923. //
  1924. // TRUE if on a 2MB PDE boundary, FALSE if not.
  1925. //
  1926. //--
  1927. #define MiIsPteOnPdeBoundary(PTE) (((ULONG_PTR)(PTE) & (PAGE_SIZE - 1)) == 0)
  1928. //++
  1929. //ULONG
  1930. //GET_PAGING_FILE_NUMBER (
  1931. // IN MMPTE PTE
  1932. // );
  1933. //
  1934. // Routine Description:
  1935. //
  1936. // This macro extracts the paging file number from a PTE.
  1937. //
  1938. // Arguments
  1939. //
  1940. // PTE - Supplies the PTE to operate upon.
  1941. //
  1942. // Return Value:
  1943. //
  1944. // The paging file number.
  1945. //
  1946. //--
  1947. #define GET_PAGING_FILE_NUMBER(PTE) ((ULONG)(((PTE).u.Soft.PageFileLow)))
  1948. //++
  1949. //ULONG
  1950. //GET_PAGING_FILE_OFFSET (
  1951. // IN MMPTE PTE
  1952. // );
  1953. //
  1954. // Routine Description:
  1955. //
  1956. // This macro extracts the offset into the paging file from a PTE.
  1957. //
  1958. // Arguments
  1959. //
  1960. // PTE - Supplies the PTE to operate upon.
  1961. //
  1962. // Return Value:
  1963. //
  1964. // The paging file offset.
  1965. //
  1966. //--
  1967. #define GET_PAGING_FILE_OFFSET(PTE) ((ULONG)((PTE).u.Soft.PageFileHigh))
  1968. //++
  1969. //ULONG
  1970. //IS_PTE_NOT_DEMAND_ZERO (
  1971. // IN PMMPTE PTE
  1972. // );
  1973. //
  1974. // Routine Description:
  1975. //
  1976. // This macro checks to see if a given PTE is NOT a demand zero PTE.
  1977. //
  1978. // Arguments
  1979. //
  1980. // PTE - Supplies the PTE to operate upon.
  1981. //
  1982. // Return Value:
  1983. //
  1984. // Returns 0 if the PTE is demand zero, non-zero otherwise.
  1985. //
  1986. //--
  1987. #define IS_PTE_NOT_DEMAND_ZERO(PTE) \
  1988. ((PTE).u.Long & ((ULONG_PTR)0xFFFFFFFFFFFFF000 | \
  1989. MM_PTE_VALID_MASK | \
  1990. MM_PTE_PROTOTYPE_MASK | \
  1991. MM_PTE_TRANSITION_MASK))
  1992. //++
  1993. //VOID
  1994. //MI_MAKING_VALID_PTE_INVALID(
  1995. // IN PMMPTE PPTE
  1996. // );
  1997. //
  1998. // Routine Description:
  1999. //
  2000. // Prepare to make a single valid PTE invalid.
  2001. // No action is required on AMD64.
  2002. //
  2003. // Arguments
  2004. //
  2005. // SYSTEM_WIDE - Supplies TRUE if this will happen on all processors.
  2006. //
  2007. // Return Value:
  2008. //
  2009. // None.
  2010. //
  2011. //--
  2012. #define MI_MAKING_VALID_PTE_INVALID(SYSTEM_WIDE)
  2013. //++
  2014. //VOID
  2015. //MI_MAKING_VALID_MULTIPLE_PTES_INVALID(
  2016. // IN PMMPTE PPTE
  2017. // );
  2018. //
  2019. // Routine Description:
  2020. //
  2021. // Prepare to make multiple valid PTEs invalid.
  2022. // No action is required on AMD64.
  2023. //
  2024. // Arguments
  2025. //
  2026. // SYSTEM_WIDE - Supplies TRUE if this will happen on all processors.
  2027. //
  2028. // Return Value:
  2029. //
  2030. // None.
  2031. //
  2032. //--
  2033. #define MI_MAKING_MULTIPLE_PTES_INVALID(SYSTEM_WIDE)
  2034. //++
  2035. //VOID
  2036. //MI_MAKE_PROTECT_WRITE_COPY (
  2037. // IN OUT MMPTE PPTE
  2038. // );
  2039. //
  2040. // Routine Description:
  2041. //
  2042. // This macro makes a writable PTE a writable-copy PTE.
  2043. //
  2044. // Arguments
  2045. //
  2046. // PTE - Supplies the PTE to operate upon.
  2047. //
  2048. // Return Value:
  2049. //
  2050. // NONE
  2051. //
  2052. //--
  2053. #define MI_MAKE_PROTECT_WRITE_COPY(PTE) \
  2054. if ((PTE).u.Soft.Protection & MM_PROTECTION_WRITE_MASK) { \
  2055. (PTE).u.Long |= MM_PROTECTION_COPY_MASK << MM_PROTECT_FIELD_SHIFT; \
  2056. }
  2057. //++
  2058. //VOID
  2059. //MI_SET_PAGE_DIRTY(
  2060. // IN PMMPTE PPTE,
  2061. // IN PVOID VA,
  2062. // IN PVOID PFNHELD
  2063. // );
  2064. //
  2065. // Routine Description:
  2066. //
  2067. // This macro sets the dirty bit (and release page file space).
  2068. //
  2069. // Arguments
  2070. //
  2071. // TEMP - Supplies a temporary for usage.
  2072. //
  2073. // PPTE - Supplies a pointer to the PTE that corresponds to VA.
  2074. //
  2075. // VA - Supplies a the virtual address of the page fault.
  2076. //
  2077. // PFNHELD - Supplies TRUE if the PFN lock is held.
  2078. //
  2079. // Return Value:
  2080. //
  2081. // None.
  2082. //
  2083. //--
  2084. #if defined(NT_UP)
  2085. #define MI_SET_PAGE_DIRTY(PPTE,VA,PFNHELD)
  2086. #else
  2087. #define MI_SET_PAGE_DIRTY(PPTE,VA,PFNHELD) \
  2088. if ((PPTE)->u.Hard.Dirty == 1) { \
  2089. MiSetDirtyBit ((VA),(PPTE),(PFNHELD)); \
  2090. }
  2091. #endif
  2092. //++
  2093. //VOID
  2094. //MI_NO_FAULT_FOUND(
  2095. // IN FAULTSTATUS,
  2096. // IN PMMPTE PPTE,
  2097. // IN PVOID VA,
  2098. // IN PVOID PFNHELD
  2099. // );
  2100. //
  2101. // Routine Description:
  2102. //
  2103. // This macro handles the case when a page fault is taken and no
  2104. // PTE with the valid bit clear is found.
  2105. //
  2106. // Arguments
  2107. //
  2108. // FAULTSTATUS - Supplies the fault status.
  2109. //
  2110. // PPTE - Supplies a pointer to the PTE that corresponds to VA.
  2111. //
  2112. // VA - Supplies a the virtual address of the page fault.
  2113. //
  2114. // PFNHELD - Supplies TRUE if the PFN lock is held.
  2115. //
  2116. // Return Value:
  2117. //
  2118. // None.
  2119. //
  2120. //--
  2121. #if defined(NT_UP)
  2122. #define MI_NO_FAULT_FOUND(FAULTSTATUS,PPTE,VA,PFNHELD)
  2123. #else
  2124. #define MI_NO_FAULT_FOUND(FAULTSTATUS,PPTE,VA,PFNHELD) \
  2125. if ((MI_FAULT_STATUS_INDICATES_WRITE(FAULTSTATUS)) && ((PPTE)->u.Hard.Dirty == 0)) { \
  2126. MiSetDirtyBit ((VA),(PPTE),(PFNHELD)); \
  2127. }
  2128. #endif
  2129. //++
  2130. //ULONG
  2131. //MI_CAPTURE_DIRTY_BIT_TO_PFN (
  2132. // IN PMMPTE PPTE,
  2133. // IN PMMPFN PPFN
  2134. // );
  2135. //
  2136. // Routine Description:
  2137. //
  2138. // This macro gets captures the state of the dirty bit to the PFN
  2139. // and frees any associated page file space if the PTE has been
  2140. // modified element.
  2141. //
  2142. // NOTE - THE PFN LOCK MUST BE HELD!
  2143. //
  2144. // Arguments
  2145. //
  2146. // PPTE - Supplies the PTE to operate upon.
  2147. //
  2148. // PPFN - Supplies a pointer to the PFN database element that corresponds
  2149. // to the page mapped by the PTE.
  2150. //
  2151. // Return Value:
  2152. //
  2153. // None.
  2154. //
  2155. //--
  2156. #define MI_CAPTURE_DIRTY_BIT_TO_PFN(PPTE,PPFN) \
  2157. ASSERT (KeGetCurrentIrql() > APC_LEVEL); \
  2158. if (((PPFN)->u3.e1.Modified == 0) && \
  2159. ((PPTE)->u.Hard.Dirty != 0)) { \
  2160. MI_SET_MODIFIED (PPFN, 1, 0x18); \
  2161. if (((PPFN)->OriginalPte.u.Soft.Prototype == 0) && \
  2162. ((PPFN)->u3.e1.WriteInProgress == 0)) { \
  2163. MiReleasePageFileSpace ((PPFN)->OriginalPte); \
  2164. (PPFN)->OriginalPte.u.Soft.PageFileHigh = 0; \
  2165. } \
  2166. }
  2167. //++
  2168. //BOOLEAN
  2169. //MI_IS_PHYSICAL_ADDRESS (
  2170. // IN PVOID VA
  2171. // );
  2172. //
  2173. // Routine Description:
  2174. //
  2175. // This macro determines if a given virtual address is really a
  2176. // physical address.
  2177. //
  2178. // Arguments
  2179. //
  2180. // VA - Supplies the virtual address.
  2181. //
  2182. // Return Value:
  2183. //
  2184. // FALSE if it is not a physical address, TRUE if it is.
  2185. //
  2186. //--
  2187. #define MI_IS_PHYSICAL_ADDRESS(Va) \
  2188. ((MiGetPxeAddress(Va)->u.Hard.Valid == 1) && \
  2189. (MiGetPpeAddress(Va)->u.Hard.Valid == 1) && \
  2190. ((MiGetPdeAddress(Va)->u.Long & 0x81) == 0x81))
  2191. //++
  2192. //ULONG
  2193. //MI_CONVERT_PHYSICAL_TO_PFN (
  2194. // IN PVOID VA
  2195. // );
  2196. //
  2197. // Routine Description:
  2198. //
  2199. // This macro converts a physical address (see MI_IS_PHYSICAL_ADDRESS)
  2200. // to its corresponding physical frame number.
  2201. //
  2202. // Arguments
  2203. //
  2204. // VA - Supplies a pointer to the physical address.
  2205. //
  2206. // Return Value:
  2207. //
  2208. // Returns the PFN for the page.
  2209. //
  2210. //--
  2211. #define MI_CONVERT_PHYSICAL_TO_PFN(Va) \
  2212. ((PFN_NUMBER)(MiGetPdeAddress(Va)->u.Hard.PageFrameNumber) + (MiGetPteOffset((ULONG_PTR)Va)))
  2213. typedef struct _MMCOLOR_TABLES {
  2214. PFN_NUMBER Flink;
  2215. PVOID Blink;
  2216. PFN_NUMBER Count;
  2217. } MMCOLOR_TABLES, *PMMCOLOR_TABLES;
  2218. extern PMMCOLOR_TABLES MmFreePagesByColor[2];
  2219. extern PFN_NUMBER MmTotalPagesForPagingFile;
  2220. //
  2221. // A VALID Page Table Entry on an AMD64 has the following definition.
  2222. //
  2223. #define MI_MAXIMUM_PAGEFILE_SIZE (((UINT64)4 * 1024 * 1024 * 1024 - 1) * PAGE_SIZE)
  2224. #define MI_PTE_LOOKUP_NEEDED ((ULONG64)0xffffffff)
  2225. typedef struct _MMPTE_SOFTWARE {
  2226. ULONGLONG Valid : 1;
  2227. ULONGLONG PageFileLow : 4;
  2228. ULONGLONG Protection : 5;
  2229. ULONGLONG Prototype : 1;
  2230. ULONGLONG Transition : 1;
  2231. ULONGLONG UsedPageTableEntries : PTE_PER_PAGE_BITS;
  2232. ULONGLONG Reserved : 20 - PTE_PER_PAGE_BITS;
  2233. ULONGLONG PageFileHigh : 32;
  2234. } MMPTE_SOFTWARE;
  2235. typedef struct _MMPTE_TRANSITION {
  2236. ULONGLONG Valid : 1;
  2237. ULONGLONG Write : 1;
  2238. ULONGLONG Owner : 1;
  2239. ULONGLONG WriteThrough : 1;
  2240. ULONGLONG CacheDisable : 1;
  2241. ULONGLONG Protection : 5;
  2242. ULONGLONG Prototype : 1;
  2243. ULONGLONG Transition : 1;
  2244. ULONGLONG PageFrameNumber : 28;
  2245. ULONGLONG Unused : 24;
  2246. } MMPTE_TRANSITION;
  2247. typedef struct _MMPTE_PROTOTYPE {
  2248. ULONGLONG Valid : 1;
  2249. ULONGLONG Unused0: 7;
  2250. ULONGLONG ReadOnly : 1;
  2251. ULONGLONG Unused1: 1;
  2252. ULONGLONG Prototype : 1;
  2253. ULONGLONG Protection : 5;
  2254. LONGLONG ProtoAddress: 48;
  2255. } MMPTE_PROTOTYPE;
  2256. typedef struct _MMPTE_SUBSECTION {
  2257. ULONGLONG Valid : 1;
  2258. ULONGLONG Unused0 : 4;
  2259. ULONGLONG Protection : 5;
  2260. ULONGLONG Prototype : 1;
  2261. ULONGLONG Unused1 : 5;
  2262. LONGLONG SubsectionAddress : 48;
  2263. } MMPTE_SUBSECTION;
  2264. typedef struct _MMPTE_LIST {
  2265. ULONGLONG Valid : 1;
  2266. ULONGLONG OneEntry : 1;
  2267. ULONGLONG filler0 : 3;
  2268. //
  2269. // Note the Prototype bit must not be used for lists like freed nonpaged
  2270. // pool because lookaside pops can legitimately reference bogus addresses
  2271. // (since the pop is unsynchronized) and the fault handler must be able to
  2272. // distinguish lists from protos so a retry status can be returned (vs a
  2273. // fatal bugcheck).
  2274. //
  2275. // The same caveat applies to both the Transition and the Protection
  2276. // fields as they are similarly examined in the fault handler and would
  2277. // be misinterpreted if ever nonzero in the freed nonpaged pool chains.
  2278. //
  2279. ULONGLONG Protection : 5;
  2280. ULONGLONG Prototype : 1; // MUST BE ZERO as per above comment.
  2281. ULONGLONG Transition : 1;
  2282. ULONGLONG filler1 : 20;
  2283. ULONGLONG NextEntry : 32;
  2284. } MMPTE_LIST;
  2285. typedef struct _MMPTE_HIGHLOW {
  2286. ULONG LowPart;
  2287. ULONG HighPart;
  2288. } MMPTE_HIGHLOW;
  2289. typedef struct _MMPTE_HARDWARE_LARGEPAGE {
  2290. ULONGLONG Valid : 1;
  2291. ULONGLONG Write : 1;
  2292. ULONGLONG Owner : 1;
  2293. ULONGLONG WriteThrough : 1;
  2294. ULONGLONG CacheDisable : 1;
  2295. ULONGLONG Accessed : 1;
  2296. ULONGLONG Dirty : 1;
  2297. ULONGLONG LargePage : 1;
  2298. ULONGLONG Global : 1;
  2299. ULONGLONG CopyOnWrite : 1; // software field
  2300. ULONGLONG Prototype : 1; // software field
  2301. ULONGLONG reserved0 : 1; // software field
  2302. ULONGLONG PAT : 1;
  2303. ULONGLONG reserved1 : 8; // software field
  2304. ULONGLONG PageFrameNumber : 19;
  2305. ULONGLONG reserved2 : 24; // software field
  2306. } MMPTE_HARDWARE_LARGEPAGE, *PMMPTE_HARDWARE_LARGEPAGE;
  2307. //
  2308. // A Page Table Entry on AMD64 has the following definition.
  2309. // Note the MP version is to avoid stalls when flushing TBs across processors.
  2310. //
  2311. //
  2312. // Uniprocessor version.
  2313. //
  2314. typedef struct _MMPTE_HARDWARE {
  2315. ULONGLONG Valid : 1;
  2316. #if defined(NT_UP)
  2317. ULONGLONG Write : 1; // UP version
  2318. #else
  2319. ULONGLONG Writable : 1; // changed for MP version
  2320. #endif
  2321. ULONGLONG Owner : 1;
  2322. ULONGLONG WriteThrough : 1;
  2323. ULONGLONG CacheDisable : 1;
  2324. ULONGLONG Accessed : 1;
  2325. ULONGLONG Dirty : 1;
  2326. ULONGLONG LargePage : 1;
  2327. ULONGLONG Global : 1;
  2328. ULONGLONG CopyOnWrite : 1; // software field
  2329. ULONGLONG Prototype : 1; // software field
  2330. #if defined(NT_UP)
  2331. ULONGLONG reserved0 : 1; // software field
  2332. #else
  2333. ULONGLONG Write : 1; // software field - MP change
  2334. #endif
  2335. ULONGLONG PageFrameNumber : 28;
  2336. ULONG64 reserved1 : 24 - (_HARDWARE_PTE_WORKING_SET_BITS+1);
  2337. ULONGLONG SoftwareWsIndex : _HARDWARE_PTE_WORKING_SET_BITS;
  2338. ULONG64 NoExecute : 1;
  2339. } MMPTE_HARDWARE, *PMMPTE_HARDWARE;
  2340. #if defined(NT_UP)
  2341. #define HARDWARE_PTE_DIRTY_MASK 0x40
  2342. #else
  2343. #define HARDWARE_PTE_DIRTY_MASK 0x42
  2344. #endif
  2345. #define MI_PDE_MAPS_LARGE_PAGE(PDE) ((PDE)->u.Hard.LargePage == 1)
  2346. #define MI_MAKE_PDE_MAP_LARGE_PAGE(PDE) ((PDE)->u.Hard.LargePage = 1)
  2347. #define MI_GET_PAGE_FRAME_FROM_PTE(PTE) ((PTE)->u.Hard.PageFrameNumber)
  2348. #define MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE(PTE) ((PTE)->u.Trans.PageFrameNumber)
  2349. #define MI_GET_PROTECTION_FROM_SOFT_PTE(PTE) ((ULONG)(PTE)->u.Soft.Protection)
  2350. #define MI_GET_PROTECTION_FROM_TRANSITION_PTE(PTE) ((ULONG)(PTE)->u.Trans.Protection)
  2351. typedef struct _MMPTE {
  2352. union {
  2353. ULONG_PTR Long;
  2354. MMPTE_HARDWARE Hard;
  2355. MMPTE_HARDWARE_LARGEPAGE HardLarge;
  2356. HARDWARE_PTE Flush;
  2357. MMPTE_PROTOTYPE Proto;
  2358. MMPTE_SOFTWARE Soft;
  2359. MMPTE_TRANSITION Trans;
  2360. MMPTE_SUBSECTION Subsect;
  2361. MMPTE_LIST List;
  2362. } u;
  2363. } MMPTE;
  2364. typedef MMPTE *PMMPTE;
  2365. extern PMMPTE MiFirstReservedZeroingPte;
  2366. #define InterlockedCompareExchangePte(_PointerPte, _NewContents, _OldContents) \
  2367. InterlockedCompareExchange64 ((PLONGLONG)(_PointerPte), (LONGLONG)(_NewContents), (LONGLONG)(_OldContents))
  2368. #define InterlockedExchangePte(_PointerPte, _NewContents) InterlockedExchange64((PLONG64)(_PointerPte), _NewContents)
  2369. //++
  2370. //VOID
  2371. //MI_WRITE_VALID_PTE (
  2372. // IN PMMPTE PointerPte,
  2373. // IN MMPTE PteContents
  2374. // );
  2375. //
  2376. // Routine Description:
  2377. //
  2378. // MI_WRITE_VALID_PTE fills in the specified PTE making it valid with the
  2379. // specified contents.
  2380. //
  2381. // Arguments
  2382. //
  2383. // PointerPte - Supplies a PTE to fill.
  2384. //
  2385. // PteContents - Supplies the contents to put in the PTE.
  2386. //
  2387. // Return Value:
  2388. //
  2389. // None.
  2390. //
  2391. //--
  2392. #define MI_WRITE_VALID_PTE(_PointerPte, _PteContents) \
  2393. ASSERT ((_PointerPte)->u.Hard.Valid == 0); \
  2394. ASSERT ((_PteContents).u.Hard.Valid == 1); \
  2395. MI_LOG_PTE_CHANGE (_PointerPte, _PteContents); \
  2396. (*(_PointerPte) = (_PteContents))
  2397. //++
  2398. //VOID
  2399. //MI_WRITE_INVALID_PTE (
  2400. // IN PMMPTE PointerPte,
  2401. // IN MMPTE PteContents
  2402. // );
  2403. //
  2404. // Routine Description:
  2405. //
  2406. // MI_WRITE_INVALID_PTE fills in the specified PTE making it invalid with the
  2407. // specified contents.
  2408. //
  2409. // Arguments
  2410. //
  2411. // PointerPte - Supplies a PTE to fill.
  2412. //
  2413. // PteContents - Supplies the contents to put in the PTE.
  2414. //
  2415. // Return Value:
  2416. //
  2417. // None.
  2418. //
  2419. //--
  2420. #define MI_WRITE_INVALID_PTE(_PointerPte, _PteContents) \
  2421. ASSERT ((_PteContents).u.Hard.Valid == 0); \
  2422. MI_LOG_PTE_CHANGE (_PointerPte, _PteContents); \
  2423. (*(_PointerPte) = (_PteContents))
  2424. //++
  2425. //VOID
  2426. //MI_WRITE_VALID_PTE_NEW_PROTECTION (
  2427. // IN PMMPTE PointerPte,
  2428. // IN MMPTE PteContents
  2429. // );
  2430. //
  2431. // Routine Description:
  2432. //
  2433. // MI_WRITE_VALID_PTE_NEW_PROTECTION fills in the specified PTE (which was
  2434. // already valid) changing only the protection or the dirty bit.
  2435. //
  2436. // Arguments
  2437. //
  2438. // PointerPte - Supplies a PTE to fill.
  2439. //
  2440. // PteContents - Supplies the contents to put in the PTE.
  2441. //
  2442. // Return Value:
  2443. //
  2444. // None.
  2445. //
  2446. //--
  2447. #define MI_WRITE_VALID_PTE_NEW_PROTECTION(_PointerPte, _PteContents) \
  2448. ASSERT ((_PointerPte)->u.Hard.Valid == 1); \
  2449. ASSERT ((_PteContents).u.Hard.Valid == 1); \
  2450. ASSERT ((_PointerPte)->u.Hard.PageFrameNumber == (_PteContents).u.Hard.PageFrameNumber); \
  2451. MI_LOG_PTE_CHANGE (_PointerPte, _PteContents); \
  2452. (*(_PointerPte) = (_PteContents))
  2453. //++
  2454. //VOID
  2455. //MI_WRITE_VALID_PTE_NEW_PAGE (
  2456. // IN PMMPTE PointerPte,
  2457. // IN MMPTE PteContents
  2458. // );
  2459. //
  2460. // Routine Description:
  2461. //
  2462. // MI_WRITE_VALID_PTE_NEW_PAGE fills in the specified PTE (which was
  2463. // already valid) changing the page and the protection.
  2464. // Note that the contents are very carefully written.
  2465. //
  2466. // Arguments
  2467. //
  2468. // PointerPte - Supplies a PTE to fill.
  2469. //
  2470. // PteContents - Supplies the contents to put in the PTE.
  2471. //
  2472. // Return Value:
  2473. //
  2474. // None.
  2475. //
  2476. //--
  2477. #define MI_WRITE_VALID_PTE_NEW_PAGE(_PointerPte, _PteContents) \
  2478. ASSERT ((_PointerPte)->u.Hard.Valid == 1); \
  2479. ASSERT ((_PteContents).u.Hard.Valid == 1); \
  2480. ASSERT ((_PointerPte)->u.Hard.PageFrameNumber != (_PteContents).u.Hard.PageFrameNumber); \
  2481. MI_LOG_PTE_CHANGE (_PointerPte, _PteContents); \
  2482. (*(_PointerPte) = (_PteContents))
  2483. //++
  2484. //VOID
  2485. //MiFillMemoryPte (
  2486. // IN PMMPTE Destination,
  2487. // IN ULONG NumberOfPtes,
  2488. // IN MMPTE Pattern,
  2489. // };
  2490. //
  2491. // Routine Description:
  2492. //
  2493. // This function fills memory with the specified PTE pattern.
  2494. //
  2495. // Arguments
  2496. //
  2497. // Destination - Supplies a pointer to the memory to fill.
  2498. //
  2499. // NumberOfPtes - Supplies the number of PTEs (not bytes!) to be filled.
  2500. //
  2501. // Pattern - Supplies the PTE fill pattern.
  2502. //
  2503. // Return Value:
  2504. //
  2505. // None.
  2506. //
  2507. //--
  2508. #define MiFillMemoryPte(Destination, Length, Pattern) \
  2509. __stosq((PULONG64)(Destination), Pattern, Length)
  2510. #define MiZeroMemoryPte(Destination, Length) \
  2511. __stosq((PULONG64)(Destination), 0, Length)
  2512. ULONG
  2513. FASTCALL
  2514. MiDetermineUserGlobalPteMask (
  2515. IN PMMPTE Pte
  2516. );
  2517. //++
  2518. //BOOLEAN
  2519. //MI_IS_PAGE_TABLE_ADDRESS (
  2520. // IN PVOID VA
  2521. // );
  2522. //
  2523. // Routine Description:
  2524. //
  2525. // This macro takes a virtual address and determines if
  2526. // it is a page table address.
  2527. //
  2528. // Arguments
  2529. //
  2530. // VA - Supplies a virtual address.
  2531. //
  2532. // Return Value:
  2533. //
  2534. // TRUE if the address is a page table address, FALSE if not.
  2535. //
  2536. //--
  2537. #define MI_IS_PAGE_TABLE_ADDRESS(VA) \
  2538. ((PVOID)(VA) >= (PVOID)PTE_BASE && (PVOID)(VA) <= (PVOID)PTE_TOP)
  2539. //++
  2540. //BOOLEAN
  2541. //MI_IS_PAGE_TABLE_OR_HYPER_ADDRESS (
  2542. // IN PVOID VA
  2543. // );
  2544. //
  2545. // Routine Description:
  2546. //
  2547. // This macro takes a virtual address and determines if
  2548. // it is a page table or hyperspace address.
  2549. //
  2550. // Arguments
  2551. //
  2552. // VA - Supplies a virtual address.
  2553. //
  2554. // Return Value:
  2555. //
  2556. // TRUE if the address is a page table or hyperspace address, FALSE if not.
  2557. //
  2558. //--
  2559. #define MI_IS_PAGE_TABLE_OR_HYPER_ADDRESS(VA) \
  2560. ((PVOID)(VA) >= (PVOID)PTE_BASE && (PVOID)(VA) <= (PVOID)HYPER_SPACE_END)
  2561. //++
  2562. //BOOLEAN
  2563. //MI_IS_KERNEL_PAGE_TABLE_ADDRESS (
  2564. // IN PVOID VA
  2565. // );
  2566. //
  2567. // Routine Description:
  2568. //
  2569. // This macro takes a virtual address and determines if
  2570. // it is a page table address for a kernel address.
  2571. //
  2572. // Arguments
  2573. //
  2574. // VA - Supplies a virtual address.
  2575. //
  2576. // Return Value:
  2577. //
  2578. // TRUE if the address is a kernel page table address, FALSE if not.
  2579. //
  2580. //--
  2581. #define MI_IS_KERNEL_PAGE_TABLE_ADDRESS(VA) \
  2582. ((PVOID)(VA) >= (PVOID)MiGetPteAddress(MM_SYSTEM_RANGE_START) && (PVOID)(VA) <= (PVOID)PTE_TOP)
  2583. //++
  2584. //BOOLEAN
  2585. //MI_IS_PAGE_DIRECTORY_ADDRESS (
  2586. // IN PVOID VA
  2587. // );
  2588. //
  2589. // Routine Description:
  2590. //
  2591. // This macro takes a virtual address and determines if
  2592. // it is a page directory address.
  2593. //
  2594. // Arguments
  2595. //
  2596. // VA - Supplies a virtual address.
  2597. //
  2598. // Return Value:
  2599. //
  2600. // TRUE if the address is a page directory address, FALSE if not.
  2601. //
  2602. //--
  2603. #define MI_IS_PAGE_DIRECTORY_ADDRESS(VA) \
  2604. ((PVOID)(VA) >= (PVOID)PDE_BASE && (PVOID)(VA) <= (PVOID)PDE_TOP)
  2605. //++
  2606. //BOOLEAN
  2607. //MI_IS_HYPER_SPACE_ADDRESS (
  2608. // IN PVOID VA
  2609. // );
  2610. //
  2611. // Routine Description:
  2612. //
  2613. // This macro takes a virtual address and determines if
  2614. // it is a hyper space address.
  2615. //
  2616. // Arguments
  2617. //
  2618. // VA - Supplies a virtual address.
  2619. //
  2620. // Return Value:
  2621. //
  2622. // TRUE if the address is a hyper space address, FALSE if not.
  2623. //
  2624. //--
  2625. #define MI_IS_HYPER_SPACE_ADDRESS(VA) \
  2626. ((PVOID)(VA) >= (PVOID)HYPER_SPACE && (PVOID)(VA) <= (PVOID)HYPER_SPACE_END)
  2627. //++
  2628. //BOOLEAN
  2629. //MI_IS_PROCESS_SPACE_ADDRESS (
  2630. // IN PVOID VA
  2631. // );
  2632. //
  2633. // Routine Description:
  2634. //
  2635. // This macro takes a virtual address and determines if
  2636. // it is a process-specific address. This is an address in user space
  2637. // or page table pages or hyper space.
  2638. //
  2639. // Arguments
  2640. //
  2641. // VA - Supplies a virtual address.
  2642. //
  2643. // Return Value:
  2644. //
  2645. // TRUE if the address is a process-specific address, FALSE if not.
  2646. //
  2647. //--
  2648. #define MI_IS_PROCESS_SPACE_ADDRESS(VA) \
  2649. (((PVOID)(VA) <= (PVOID)MM_HIGHEST_USER_ADDRESS) || \
  2650. ((PVOID)(VA) >= (PVOID)PTE_BASE && (PVOID)(VA) <= (PVOID)HYPER_SPACE_END))
  2651. //++
  2652. //BOOLEAN
  2653. //MI_IS_PTE_PROTOTYPE (
  2654. // IN PMMPTE PTE
  2655. // );
  2656. //
  2657. // Routine Description:
  2658. //
  2659. // This macro takes a PTE address and determines if it is a prototype PTE.
  2660. //
  2661. // Arguments
  2662. //
  2663. // PTE - Supplies the virtual address of the PTE to check.
  2664. //
  2665. // Return Value:
  2666. //
  2667. // TRUE if the PTE is in a segment (ie, a prototype PTE), FALSE if not.
  2668. //
  2669. //--
  2670. #define MI_IS_PTE_PROTOTYPE(PTE) \
  2671. ((PTE) > (PMMPTE)PTE_TOP)
  2672. //++
  2673. //BOOLEAN
  2674. //MI_IS_SYSTEM_CACHE_ADDRESS (
  2675. // IN PVOID VA
  2676. // );
  2677. //
  2678. // Routine Description:
  2679. //
  2680. // This macro takes a virtual address and determines if
  2681. // it is a system cache address.
  2682. //
  2683. // Arguments
  2684. //
  2685. // VA - Supplies a virtual address.
  2686. //
  2687. // Return Value:
  2688. //
  2689. // TRUE if the address is in the system cache, FALSE if not.
  2690. //
  2691. //--
  2692. #define MI_IS_SYSTEM_CACHE_ADDRESS(VA) \
  2693. ((PVOID)(VA) >= (PVOID)MmSystemCacheStart && \
  2694. (PVOID)(VA) <= (PVOID)MmSystemCacheEnd)
  2695. //++
  2696. //VOID
  2697. //MI_BARRIER_SYNCHRONIZE (
  2698. // IN ULONG TimeStamp
  2699. // );
  2700. //
  2701. // Routine Description:
  2702. //
  2703. // MI_BARRIER_SYNCHRONIZE compares the argument timestamp against the
  2704. // current IPI barrier sequence stamp. When equal, all processors will
  2705. // issue memory barriers to ensure that newly created pages remain coherent.
  2706. //
  2707. // When a page is put in the zeroed or free page list the current
  2708. // barrier sequence stamp is read (interlocked - this is necessary
  2709. // to get the correct value - memory barriers won't do the trick)
  2710. // and stored in the pfn entry for the page. The current barrier
  2711. // sequence stamp is maintained by the IPI send logic and is
  2712. // incremented (interlocked) when the target set of an IPI send
  2713. // includes all processors, but the one doing the send. When a page
  2714. // is needed its sequence number is compared against the current
  2715. // barrier sequence number. If it is equal, then the contents of
  2716. // the page may not be coherent on all processors, and an IPI must
  2717. // be sent to all processors to ensure a memory barrier is
  2718. // executed (generic call can be used for this). Sending the IPI
  2719. // automatically updates the barrier sequence number. The compare
  2720. // is for equality as this is the only value that requires the IPI
  2721. // (i.e., the sequence number wraps, values in both directions are
  2722. // older). When a page is removed in this fashion and either found
  2723. // to be coherent or made coherent, it cannot be modified between
  2724. // that time and writing the PTE. If the page is modified between
  2725. // these times, then an IPI must be sent.
  2726. //
  2727. // Arguments
  2728. //
  2729. // TimeStamp - Supplies the timestamp at the time when the page was zeroed.
  2730. //
  2731. // Return Value:
  2732. //
  2733. // None.
  2734. //
  2735. //--
  2736. // does nothing on AMD64.
  2737. #define MI_BARRIER_SYNCHRONIZE(TimeStamp)
  2738. //++
  2739. //VOID
  2740. //MI_BARRIER_STAMP_ZEROED_PAGE (
  2741. // IN PULONG PointerTimeStamp
  2742. // );
  2743. //
  2744. // Routine Description:
  2745. //
  2746. // MI_BARRIER_STAMP_ZEROED_PAGE issues an interlocked read to get the
  2747. // current IPI barrier sequence stamp. This is called AFTER a page is
  2748. // zeroed.
  2749. //
  2750. // Arguments
  2751. //
  2752. // PointerTimeStamp - Supplies a timestamp pointer to fill with the
  2753. // current IPI barrier sequence stamp.
  2754. //
  2755. // Return Value:
  2756. //
  2757. // None.
  2758. //
  2759. //--
  2760. // does nothing on AMD64.
  2761. #define MI_BARRIER_STAMP_ZEROED_PAGE(PointerTimeStamp)
  2762. //++
  2763. //VOID
  2764. //MI_FLUSH_SINGLE_SESSION_TB (
  2765. // IN PVOID Virtual
  2766. // );
  2767. //
  2768. // Routine Description:
  2769. //
  2770. // MI_FLUSH_SINGLE_SESSION_TB flushes the requested single address
  2771. // translation from the TB.
  2772. //
  2773. // Since there are no ASNs on the AMD64, this routine becomes a single
  2774. // TB invalidate.
  2775. //
  2776. // Arguments
  2777. //
  2778. // Virtual - Supplies the virtual address to invalidate.
  2779. //
  2780. // Return Value:
  2781. //
  2782. // None.
  2783. //
  2784. //--
  2785. #define MI_FLUSH_SINGLE_SESSION_TB(Virtual) \
  2786. KeFlushSingleTb (Virtual, TRUE);
  2787. //++
  2788. //VOID
  2789. //MI_FLUSH_ENTIRE_SESSION_TB (
  2790. // IN ULONG Invalid,
  2791. // IN LOGICAL AllProcessors
  2792. // );
  2793. //
  2794. // Routine Description:
  2795. //
  2796. // MI_FLUSH_ENTIRE_SESSION_TB flushes the entire TB on processors which
  2797. // support ASNs.
  2798. //
  2799. // Since there are no ASNs on the AMD64, this routine does nothing.
  2800. //
  2801. // Arguments
  2802. //
  2803. // Invalid - TRUE if invalidating.
  2804. //
  2805. // AllProcessors - TRUE if all processors need to be IPI'd.
  2806. //
  2807. // Return Value:
  2808. //
  2809. // None.
  2810. //
  2811. #define MI_FLUSH_ENTIRE_SESSION_TB(Invalid, AllProcessors) \
  2812. NOTHING;
  2813. //
  2814. //++
  2815. //LOGICAL
  2816. //MI_RESERVED_BITS_CANONICAL (
  2817. // IN PVOID VirtualAddress
  2818. // );
  2819. //
  2820. // Routine Description:
  2821. //
  2822. // This routine checks whether all of the reserved bits are correct.
  2823. //
  2824. // The processor implements at 48 bits of VA and memory management
  2825. // uses them all so the VA is checked against 48 bits to prevent
  2826. // reserved bit faults as our caller is not going to be expecting them.
  2827. //
  2828. // Arguments
  2829. //
  2830. // VirtualAddress - Supplies the virtual address to check.
  2831. //
  2832. // Return Value:
  2833. //
  2834. // TRUE if the address is ok, FALSE if not.
  2835. //
  2836. LOGICAL
  2837. __inline
  2838. MI_RESERVED_BITS_CANONICAL (
  2839. IN PVOID VirtualAddress
  2840. )
  2841. {
  2842. LONG_PTR ReservedBits;
  2843. ULONG_PTR ImplVirtualMsb;
  2844. ImplVirtualMsb = 48;
  2845. ReservedBits = (LONG_PTR) VirtualAddress;
  2846. ReservedBits >>= (ImplVirtualMsb + 1);
  2847. if ((ULONG_PTR)VirtualAddress & ((ULONG_PTR)1 << ImplVirtualMsb)) {
  2848. //
  2849. // All the reserved bits (not including the VRN) must also be set.
  2850. //
  2851. if (ReservedBits != (LONG_PTR)-1) {
  2852. }
  2853. }
  2854. else {
  2855. //
  2856. // All the reserved bits (not including the VRN) must also be clear.
  2857. //
  2858. if (ReservedBits != 0) {
  2859. return FALSE;
  2860. }
  2861. }
  2862. return TRUE;
  2863. }
  2864. //++
  2865. //VOID
  2866. //MI_DISPLAY_TRAP_INFORMATION (
  2867. // IN PVOID TrapInformation
  2868. // );
  2869. //
  2870. // Routine Description:
  2871. //
  2872. // Display any relevant trap information to aid debugging.
  2873. //
  2874. // Arguments
  2875. //
  2876. // TrapInformation - Supplies a pointer to a trap frame.
  2877. //
  2878. // Return Value:
  2879. //
  2880. // None.
  2881. //
  2882. #define MI_DISPLAY_TRAP_INFORMATION(TrapInformation) \
  2883. KdPrint(("MM:***RIP %p, EFL %p\n", \
  2884. ((PKTRAP_FRAME) (TrapInformation))->Rip, \
  2885. ((PKTRAP_FRAME) (TrapInformation))->EFlags)); \
  2886. KdPrint(("MM:***RAX %p, RCX %p RDX %p\n", \
  2887. ((PKTRAP_FRAME) (TrapInformation))->Rax, \
  2888. ((PKTRAP_FRAME) (TrapInformation))->Rcx, \
  2889. ((PKTRAP_FRAME) (TrapInformation))->Rdx)); \
  2890. KdPrint(("MM:***RBX %p, RSI %p RDI %p\n", \
  2891. ((PKTRAP_FRAME) (TrapInformation))->Rbx, \
  2892. ((PKTRAP_FRAME) (TrapInformation))->Rsi, \
  2893. ((PKTRAP_FRAME) (TrapInformation))->Rdi));