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.

3188 lines
76 KiB

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