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

2821 lines
64 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Copyright (c) 1992 Digital Equipment Corporation
  4. Module Name:
  5. mialpha.h
  6. Abstract:
  7. This module contains the private data structures and procedure
  8. prototypes for the hardware dependent portion of the
  9. memory management system.
  10. It is specifically tailored for the DEC ALPHA architecture.
  11. Author:
  12. Lou Perazzoli (loup) 12-Mar-1990
  13. Joe Notarangelo 23-Apr-1992 ALPHA version
  14. Revision History:
  15. Landy Wang (landyw) 02-June-1998 : Modifications for full 3-level 64-bit NT.
  16. --*/
  17. /*++
  18. Virtual Memory Layout on the AXP64 is:
  19. +------------------------------------+
  20. 0000000000000000 | User mode addresses - 4tb |
  21. | |
  22. 000003FFFFFEFFFF | | MM_HIGHEST_USER_ADDRESS
  23. +------------------------------------+
  24. 000003FFFFFF0000 | 64k No Access Region | MM_USER_PROBE_ADDRESS
  25. +------------------------------------+
  26. +------------------------------------+
  27. FFFFFC0000000000 | Start of System space and 2tb of | MM_SYSTEM_RANGE_START
  28. | physically addressable memory. | KSEG43_BASE
  29. | |
  30. +------------------------------------+
  31. FFFFFE0000000000 | 8gb three level page table map. | PTE_BASE
  32. +------------------------------------+ KSEG43_LIMIT
  33. FFFFFE0200000000 | HyperSpace - working set lists | HYPER_SPACE
  34. | and per process memory management |
  35. | structures mapped in this 8gb |
  36. | region. | HYPER_SPACE_END
  37. +------------------------------------+ MM_WORKING_SET_END
  38. FFFFFE0400000000 | win32k.sys |
  39. | |
  40. | Hydra configurations have session |
  41. | data structures. |
  42. | |
  43. | This is an 8gb region. |
  44. +------------------------------------+
  45. FFFFFE0600000000 | The system cache working set | MM_SYSTEM_CACHE_WORKING_SET
  46. MM_SYSTEM_SPACE_START
  47. | information resides in this 8gb |
  48. | region. |
  49. +------------------------------------+
  50. FFFFFE0800000000 | System cache resides here. | MM_SYSTEM_CACHE_START
  51. | Kernel mode access only. |
  52. | 1tb. |
  53. | | MM_SYSTEM_CACHE_END
  54. +------------------------------------+
  55. FFFFFF0800000000 | Start of paged system area. | MM_PAGED_POOL_START
  56. | Kernel mode access only. |
  57. | 128gb. |
  58. +------------------------------------+
  59. | System mapped views start just |
  60. | after paged pool. Default is |
  61. | 104MB, can be registry-overridden. |
  62. | 8GB maximum. |
  63. +------------------------------------+
  64. | |
  65. .
  66. .
  67. In general, the next two areas (system PTE pool and nonpaged pool) will both
  68. be shifted upwards to conserve a PPE...
  69. .
  70. .
  71. +------------------------------------+
  72. FFFFFF2800000000 | System PTE pool. | MM_LOWEST_NONPAGED_SYSTEM_START
  73. | Kernel mode access only. |
  74. | 128gb. |
  75. +------------------------------------+
  76. FFFFFF4800000000 | NonPaged pool. | MM_NON_PAGED_POOL_START
  77. | Kernel mode access only. |
  78. | 128gb. |
  79. | |
  80. FFFFFF67FFFFFFFF | NonPaged System area | MM_NONPAGED_POOL_END
  81. +------------------------------------+
  82. | |
  83. .
  84. .
  85. .
  86. +------------------------------------+
  87. FFFFFFFF80000000 | The HAL, kernel, initial drivers, | KSEG0_BASE
  88. | NLS data, and registry load in the |
  89. | first 16mb of this region which |
  90. | physically addresses memory. |
  91. | |
  92. | Kernel mode access only. |
  93. | |
  94. | Initial NonPaged Pool is within |
  95. | KSEG0 |
  96. | |
  97. +------------------------------------+
  98. FFFFFFFFC0000000 | Unused. | KSEG2_BASE
  99. | |
  100. | |
  101. | |
  102. +------------------------------------+
  103. FFFFFFFFFF000000 | Shared system page | KI_USER_SHARED_DATA
  104. +------------------------------------+
  105. FFFFFFFFFF002000 | Reserved for the HAL. |
  106. | |
  107. | |
  108. FFFFFFFFFFFFFFFF | | MM_SYSTEM_SPACE_END
  109. +------------------------------------+
  110. --*/
  111. #define _MI_PAGING_LEVELS 3
  112. //
  113. // Define empty list marker.
  114. //
  115. #define MM_EMPTY_LIST (-1) //
  116. #define MM_EMPTY_PTE_LIST 0xFFFFFFFFUI64 // N.B. tied to MMPTE definition
  117. #define MI_PTE_BASE_FOR_LOWEST_KERNEL_ADDRESS (MiGetPteAddress (PTE_BASE))
  118. //
  119. // Define start of KSEG0.
  120. //
  121. #define MM_KSEG0_BASE KSEG0_BASE //
  122. //
  123. // 43-Bit virtual address mask.
  124. //
  125. #define MASK_43 0x7FFFFFFFFFFUI64 //
  126. //
  127. // Top level page parent is the same for both kernel and user in AXP64.
  128. //
  129. #define PDE_KTBASE PDE_TBASE
  130. //
  131. // Address space definitions.
  132. //
  133. #define PTE_TOP 0xFFFFFE01FFFFFFFFUI64
  134. #define PDE_TOP 0xFFFFFE01FFFFFFFFUI64
  135. #define MM_PAGES_IN_KSEG0 (ULONG)(((KSEG2_BASE - KSEG0_BASE) >> PAGE_SHIFT))
  136. #define MM_USER_ADDRESS_RANGE_LIMIT 0xFFFFFFFFFFFFFFFF // user address range limit
  137. #define MM_MAXIMUM_ZERO_BITS 53 // maximum number of zero bits
  138. #define MM_SYSTEM_SPACE_START 0xFFFFFE0600000000UI64
  139. #define MM_SYSTEM_CACHE_START 0xFFFFFE0800000000UI64
  140. #define MM_SYSTEM_CACHE_END 0xFFFFFF0800000000UI64
  141. #define MM_MAXIMUM_SYSTEM_CACHE_SIZE \
  142. ((MM_SYSTEM_CACHE_END - MM_SYSTEM_CACHE_START) >> PAGE_SHIFT)
  143. #define MM_SYSTEM_CACHE_WORKING_SET 0xFFFFFE0600000000UI64
  144. //
  145. // Define area for mapping views into system space.
  146. //
  147. #define MM_SESSION_SPACE_DEFAULT 0xFFFFFE0400000000UI64
  148. #define MM_SYSTEM_VIEW_SIZE (48 * 1024 * 1024)
  149. #define MM_PAGED_POOL_START ((PVOID)0xFFFFFF0800000000)
  150. #define MM_LOWEST_NONPAGED_SYSTEM_START ((PVOID)0xFFFFFF2800000000)
  151. #define MM_NONPAGED_POOL_END ((PVOID)(0xFFFFFF6800000000 - (16 * PAGE_SIZE)))
  152. #define NON_PAGED_SYSTEM_END ((PVOID)0xFFFFFFFFFFFFFFF0) //quadword aligned.
  153. #define MM_SYSTEM_SPACE_END 0xFFFFFFFFFFFFFFFFUI64
  154. //
  155. // Define absolute minimum and maximum count for system PTEs.
  156. //
  157. #define MM_MINIMUM_SYSTEM_PTES 5000
  158. #define MM_MAXIMUM_SYSTEM_PTES (16*1024*1024)
  159. #define MM_DEFAULT_SYSTEM_PTES 11000
  160. //
  161. // Pool limits.
  162. //
  163. // The maximum amount of nonpaged pool that can be initially created.
  164. //
  165. #define MM_MAX_INITIAL_NONPAGED_POOL (96 * 1024 * 1024)
  166. //
  167. // The total amount of nonpaged pool.
  168. //
  169. #define MM_MAX_ADDITIONAL_NONPAGED_POOL (((SIZE_T)128 * 1024 * 1024 * 1024) - 16)
  170. //
  171. // The maximum amount of paged pool that can be created.
  172. //
  173. #define MM_MAX_PAGED_POOL ((SIZE_T)128 * 1024 * 1024 * 1024)
  174. //
  175. // Define the maximum default for pool (user specified 0 in registry).
  176. //
  177. #define MM_MAX_DEFAULT_NONPAGED_POOL ((SIZE_T)8 * 1024 * 1024 * 1024)
  178. //
  179. // Granularity Hint definitions.
  180. //
  181. //
  182. // Granularity Hint = 3, page size = 8**3 * PAGE_SIZE
  183. //
  184. #define GH3 (3)
  185. #define GH3_PAGE_SIZE (PAGE_SIZE << 9)
  186. //
  187. // Granularity Hint = 2, page size = 8**2 * PAGE_SIZE
  188. //
  189. #define GH2 (2)
  190. #define GH2_PAGE_SIZE (PAGE_SIZE << 6)
  191. //
  192. // Granularity Hint = 1, page size = 8**1 * PAGE_SIZE
  193. //
  194. #define GH1 (1)
  195. #define GH1_PAGE_SIZE (PAGE_SIZE << 3)
  196. //
  197. // Granularity Hint = 0, page size = PAGE_SIZE
  198. //
  199. #define GH0 (0)
  200. #define GH0_PAGE_SIZE PAGE_SIZE
  201. //
  202. // Physical memory size and boundary constants.
  203. //
  204. #define __1GB (0x40000000)
  205. //
  206. // PAGE_SIZE for ALPHA (at least current implementation) is 8k
  207. // PAGE_SHIFT bytes for an offset leaves 19
  208. //
  209. #define MM_VIRTUAL_PAGE_FILLER (13 - 12)
  210. #define MM_VIRTUAL_PAGE_SIZE (43 - 13)
  211. #define MM_PROTO_PTE_ALIGNMENT ((ULONG)MM_MAXIMUM_NUMBER_OF_COLORS * (ULONG)PAGE_SIZE)
  212. //
  213. // Define maximum number of paging files
  214. //
  215. #define MAX_PAGE_FILES (8)
  216. //
  217. // Define the address bits mapped by one PPE entry.
  218. //
  219. #define PAGE_PARENT_MASK 0x1FFFFFFFFUI64
  220. #define MM_VA_MAPPED_BY_PPE (0x200000000UI64)
  221. //
  222. // Define the address bits mapped by PPE and PDE entries.
  223. //
  224. // A PPE entry maps 10+10+13 = 33 bits of address space.
  225. // A PDE entry maps 10+13 = 23 bits of address space.
  226. //
  227. #define PAGE_DIRECTORY1_MASK 0x1FFFFFFFFUI64
  228. #define PAGE_DIRECTORY2_MASK 0x7FFFFFUI64
  229. #define MM_VA_MAPPED_BY_PDE (0x800000)
  230. #define LOWEST_IO_ADDRESS (0)
  231. #define PTE_SHIFT (3)
  232. //
  233. // Number of physical address bits, maximum for ALPHA architecture = 48.
  234. //
  235. #define PHYSICAL_ADDRESS_BITS (48)
  236. #define MM_MAXIMUM_NUMBER_OF_COLORS 1
  237. //
  238. // Alpha does not require support for colored pages.
  239. //
  240. #define MM_NUMBER_OF_COLORS (1)
  241. //
  242. // Mask for obtaining color from a physical page number.
  243. //
  244. #define MM_COLOR_MASK (0)
  245. //
  246. // Boundary for aligned pages of like color upon.
  247. //
  248. #define MM_COLOR_ALIGNMENT (0)
  249. //
  250. // Mask for isolating color from virtual address.
  251. //
  252. #define MM_COLOR_MASK_VIRTUAL (0)
  253. //
  254. // Define 1mb worth of secondary colors.
  255. //
  256. #define MM_SECONDARY_COLORS_DEFAULT ((1024 * 1024) >> PAGE_SHIFT)
  257. #define MM_SECONDARY_COLORS_MIN (2)
  258. #define MM_SECONDARY_COLORS_MAX (2048)
  259. //
  260. // Hyper space definitions.
  261. //
  262. // Hyper space consists of a single top level page directory parent entry
  263. // that maps a series of PDE/PTEs that can be used for temporary per process
  264. // mapping and the working set list.
  265. //
  266. #define HYPER_SPACE ((PVOID)0xFFFFFE0200000000)
  267. #define FIRST_MAPPING_PTE 0xFFFFFE0200000000UI64
  268. #define NUMBER_OF_MAPPING_PTES 639
  269. #define LAST_MAPPING_PTE \
  270. (FIRST_MAPPING_PTE + (NUMBER_OF_MAPPING_PTES * PAGE_SIZE))
  271. #define IMAGE_MAPPING_PTE ((PMMPTE)((ULONG_PTR)LAST_MAPPING_PTE + PAGE_SIZE))
  272. #define ZEROING_PAGE_PTE ((PMMPTE)((ULONG_PTR)IMAGE_MAPPING_PTE + PAGE_SIZE))
  273. #define WORKING_SET_LIST ((PVOID)((ULONG_PTR)ZEROING_PAGE_PTE + PAGE_SIZE))
  274. #define MM_MAXIMUM_WORKING_SET \
  275. ((((ULONG_PTR)4 * 1024 * 1024 * 1024 * 1024) - (64 * 1024 * 1024)) >> PAGE_SHIFT) //4Tb-64Mb
  276. #define MmWorkingSetList ((PMMWSL)WORKING_SET_LIST)
  277. #define MmWsle ((PMMWSLE)((PUCHAR)WORKING_SET_LIST + sizeof(MMWSL)))
  278. #define HYPER_SPACE_END 0xFFFFFE03FFFFFFFFUI64
  279. #define MM_WORKING_SET_END 0xFFFFFE0400000000UI64
  280. //
  281. // Define PTE mask bits.
  282. //
  283. // These definitions are derived from the hardware PTE format and from the
  284. // software PTE formats. They are defined as masks to avoid the cost of
  285. // shifting and masking to insert and extract these fields.
  286. //
  287. #define MM_PTE_VALID_MASK 0x1105 // kernel read-write, fault-on-write, valid
  288. #define MM_PTE_PROTOTYPE_MASK 0x2 // not valid and prototype
  289. #define MM_PTE_DIRTY_MASK 0x4 // fault on write
  290. #define MM_PTE_TRANSITION_MASK 0x4 // not valid and transition
  291. #define MM_PTE_GLOBAL_MASK 0x10 // global
  292. #define MM_PTE_WRITE_MASK 0x10000 // software write
  293. #define MM_PTE_COPY_ON_WRITE_MASK 0x20000 // software copy-on-write
  294. #define MM_PTE_OWNER_MASK 0x2200 // user read-write
  295. //
  296. // Bit fields to or into PTE to make a PTE valid based on the protection
  297. // field of the invalid PTE.
  298. //
  299. #define MM_PTE_NOACCESS 0x0 // not expressable on ALPHA
  300. #define MM_PTE_READONLY 0x4 // fault on write
  301. #define MM_PTE_READWRITE (MM_PTE_WRITE_MASK) // software write enable
  302. #define MM_PTE_WRITECOPY (MM_PTE_WRITE_MASK | MM_PTE_COPY_ON_WRITE_MASK) //
  303. #define MM_PTE_EXECUTE 0x4 // fault on write
  304. #define MM_PTE_EXECUTE_READ 0x4 // fault on write
  305. #define MM_PTE_EXECUTE_READWRITE (MM_PTE_WRITE_MASK) // software write enable
  306. #define MM_PTE_EXECUTE_WRITECOPY (MM_PTE_WRITE_MASK | MM_PTE_COPY_ON_WRITE_MASK) //
  307. #define MM_PTE_NOCACHE 0x0 // not expressable on ALPHA
  308. #define MM_PTE_GUARD 0x0 // not expressable on ALPHA
  309. #define MM_PTE_CACHE 0x0 //
  310. #define MM_PROTECT_FIELD_SHIFT 3
  311. //
  312. // Bits available for the software working set index within the hardware PTE.
  313. //
  314. #define MI_MAXIMUM_PTE_WORKING_SET_INDEX (1 << _HARDWARE_PTE_WORKING_SET_BITS)
  315. //
  316. // Zero PTE
  317. //
  318. #define MM_ZERO_PTE 0
  319. //
  320. // Zero Kernel PTE
  321. //
  322. #define MM_ZERO_KERNEL_PTE 0
  323. //
  324. // A demand zero PTE with a protection or PAGE_READWRITE.
  325. //
  326. #define MM_DEMAND_ZERO_WRITE_PTE (MM_READWRITE << MM_PROTECT_FIELD_SHIFT)
  327. //
  328. // A demand zero PTE with a protection or PAGE_READWRITE for system space.
  329. //
  330. #define MM_KERNEL_DEMAND_ZERO_PTE (MM_READWRITE << MM_PROTECT_FIELD_SHIFT)
  331. //
  332. // A no access PTE for system space.
  333. //
  334. #define MM_KERNEL_NOACCESS_PTE (MM_NOACCESS << MM_PROTECT_FIELD_SHIFT)
  335. //
  336. // Dirty bit definitions for clean and dirty.
  337. //
  338. #define MM_PTE_CLEAN 1
  339. #define MM_PTE_DIRTY 0
  340. //
  341. // Kernel stack alignment requirements.
  342. //
  343. #define MM_STACK_ALIGNMENT 0x0
  344. #define MM_STACK_OFFSET 0x0
  345. //
  346. // System process definitions
  347. //
  348. #define PDE_PER_PAGE 1024
  349. #define PTE_PER_PAGE 1024
  350. #define PTE_PER_PAGE_BITS 11 // This handles the case where the page is full
  351. #if PTE_PER_PAGE_BITS > 32
  352. error - too many bits to fit into MMPTE_SOFTWARE or MMPFN.u1
  353. #endif
  354. //
  355. // Number of page table pages for user addresses.
  356. //
  357. #define MM_USER_PAGE_TABLE_PAGES (PTE_PER_PAGE * PDE_PER_PAGE / 2)
  358. #define MM_USER_PAGE_DIRECTORY_PAGES (PDE_PER_PAGE / 2)
  359. //++
  360. //VOID
  361. //MI_MAKE_VALID_PTE (
  362. // OUT OUTPTE,
  363. // IN FRAME,
  364. // IN PMASK,
  365. // IN PPTE
  366. // );
  367. //
  368. // Routine Description:
  369. //
  370. // This macro makes a valid PTE from a page frame number, protection
  371. // mask, and owner.
  372. //
  373. // Arguments
  374. //
  375. // OUTPTE - Supplies the PTE in which to build the transition PTE.
  376. //
  377. // FRAME - Supplies the page frame number for the PTE.
  378. //
  379. // PMASK - Supplies the protection to set in the transition PTE.
  380. //
  381. // PPTE - Supplies a pointer to the PTE which is being made valid.
  382. // For prototype PTEs NULL should be specified.
  383. //
  384. // Return Value:
  385. //
  386. // None.
  387. //
  388. //--
  389. #define MI_MAKE_VALID_PTE(OUTPTE, FRAME, PMASK, PPTE) { \
  390. (OUTPTE).u.Long = MmProtectToPteMask[PMASK] | MM_PTE_VALID_MASK; \
  391. (OUTPTE).u.Hard.PageFrameNumber = (FRAME); \
  392. if (MI_DETERMINE_OWNER(PPTE)) { \
  393. (OUTPTE).u.Long |= MM_PTE_OWNER_MASK; \
  394. } \
  395. if (((PMMPTE)PPTE) >= MiGetPteAddress(MM_SYSTEM_SPACE_START)) { \
  396. (OUTPTE).u.Hard.Global = 1; \
  397. } \
  398. }
  399. //++
  400. //VOID
  401. //MI_MAKE_VALID_PTE_TRANSITION (
  402. // IN OUT OUTPTE
  403. // IN PROTECT
  404. // );
  405. //
  406. // Routine Description:
  407. //
  408. // This macro takes a valid pte and turns it into a transition PTE.
  409. //
  410. // Arguments
  411. //
  412. // OUTPTE - Supplies the current valid PTE. This PTE is then
  413. // modified to become a transition PTE.
  414. //
  415. // PROTECT - Supplies the protection to set in the transition PTE.
  416. //
  417. // Return Value:
  418. //
  419. // None.
  420. //
  421. //--
  422. #define MI_MAKE_VALID_PTE_TRANSITION(OUTPTE, PROTECT) \
  423. (OUTPTE).u.Soft.Transition = 1; \
  424. (OUTPTE).u.Soft.Valid = 0; \
  425. (OUTPTE).u.Soft.Prototype = 0; \
  426. (OUTPTE).u.Soft.Protection = PROTECT;
  427. //++
  428. //VOID
  429. //MI_MAKE_TRANSITION_PTE (
  430. // OUT OUTPTE,
  431. // IN PAGE,
  432. // IN PROTECT,
  433. // IN PPTE
  434. // );
  435. //
  436. // Routine Description:
  437. //
  438. // This macro takes a valid pte and turns it into a transition PTE.
  439. //
  440. // Arguments
  441. //
  442. // OUTPTE - Supplies the PTE in which to build the transition PTE.
  443. //
  444. // PAGE - Supplies the page frame number for the PTE.
  445. //
  446. // PROTECT - Supplies the protection to set in the transition PTE.
  447. //
  448. // PPTE - Supplies a pointer to the PTE, this is used to determine
  449. // the owner of the PTE.
  450. //
  451. // Return Value:
  452. //
  453. // None.
  454. //
  455. //--
  456. #define MI_MAKE_TRANSITION_PTE(OUTPTE,PAGE,PROTECT,PPTE) \
  457. (OUTPTE).u.Long = 0; \
  458. (OUTPTE).u.Trans.PageFrameNumber = PAGE; \
  459. (OUTPTE).u.Trans.Transition = 1; \
  460. (OUTPTE).u.Trans.Protection = PROTECT;
  461. //++
  462. //VOID
  463. //MI_MAKE_TRANSITION_PTE_VALID (
  464. // OUT OUTPTE,
  465. // IN PPTE
  466. // );
  467. //
  468. // Routine Description:
  469. //
  470. // This macro takes a transition pte and makes it a valid PTE.
  471. //
  472. // Arguments
  473. //
  474. // OUTPTE - Supplies the PTE in which to build the valid PTE.
  475. //
  476. // PPTE - Supplies a pointer to the transition PTE.
  477. //
  478. // Return Value:
  479. //
  480. // None.
  481. //
  482. //--
  483. #define MI_MAKE_TRANSITION_PTE_VALID(OUTPTE, PPTE) { \
  484. (OUTPTE).u.Long = MmProtectToPteMask[(PPTE)->u.Trans.Protection] | MM_PTE_VALID_MASK; \
  485. (OUTPTE).u.Hard.PageFrameNumber = (PPTE)->u.Hard.PageFrameNumber; \
  486. if (MI_DETERMINE_OWNER(PPTE)) { \
  487. (OUTPTE).u.Long |= MM_PTE_OWNER_MASK; \
  488. } \
  489. if (((PMMPTE)PPTE) >= MiGetPteAddress(MM_SYSTEM_SPACE_START)) { \
  490. (OUTPTE).u.Hard.Global = 1; \
  491. } \
  492. }
  493. //++
  494. //VOID
  495. //MI_SET_PTE_IN_WORKING_SET (
  496. // OUT PMMPTE PTE,
  497. // IN ULONG WSINDEX
  498. // );
  499. //
  500. // Routine Description:
  501. //
  502. // This macro inserts the specified working set index into the argument PTE.
  503. //
  504. // No TB invalidation is needed for other processors (or this one) even
  505. // though the entry may already be in a TB - it's just a software field
  506. // update and doesn't affect miss resolution.
  507. //
  508. // Arguments
  509. //
  510. // OUTPTE - Supplies the PTE in which to insert the working set index.
  511. //
  512. // WSINDEX - Supplies the working set index for the PTE.
  513. //
  514. // Return Value:
  515. //
  516. // None.
  517. //
  518. //--
  519. #define MI_SET_PTE_IN_WORKING_SET(PTE, WSINDEX) { \
  520. MMPTE _TempPte; \
  521. _TempPte = *(PTE); \
  522. _TempPte.u.Hard.SoftwareWsIndex = (WSINDEX); \
  523. ASSERT (_TempPte.u.Long != 0); \
  524. *(PTE) = _TempPte; \
  525. }
  526. //++
  527. //ULONG WsIndex
  528. //MI_GET_WORKING_SET_FROM_PTE(
  529. // IN PMMPTE PTE
  530. // );
  531. //
  532. // Routine Description:
  533. //
  534. // This macro returns the working set index from the argument PTE.
  535. //
  536. // Arguments
  537. //
  538. // PTE - Supplies the PTE to extract the working set index from.
  539. //
  540. // Return Value:
  541. //
  542. // This macro returns the working set index for the argument PTE.
  543. //
  544. //--
  545. #define MI_GET_WORKING_SET_FROM_PTE(PTE) (ULONG)(PTE)->u.Hard.SoftwareWsIndex
  546. //++
  547. //VOID
  548. //MI_SET_PTE_WRITE_COMBINE (
  549. // IN MMPTE PTE
  550. // );
  551. //
  552. // Routine Description:
  553. //
  554. // This macro sets the write combined bit(s) in the specified PTE.
  555. //
  556. // Arguments
  557. //
  558. // PTE - Supplies the PTE to set dirty.
  559. //
  560. // Return Value:
  561. //
  562. // None.
  563. //
  564. //--
  565. #define MI_SET_PTE_WRITE_COMBINE(PTE)
  566. //++
  567. //VOID
  568. //MI_SET_PTE_DIRTY (
  569. // IN MMPTE PTE
  570. // );
  571. //
  572. // Routine Description:
  573. //
  574. // This macro sets the dirty bit(s) in the specified PTE.
  575. //
  576. // Arguments
  577. //
  578. // PTE - Supplies the PTE to set dirty.
  579. //
  580. // Return Value:
  581. //
  582. // None.
  583. //
  584. //--
  585. #define MI_SET_PTE_DIRTY(PTE) (PTE).u.Hard.FaultOnWrite = MM_PTE_DIRTY
  586. //++
  587. //VOID
  588. //MI_SET_PTE_CLEAN (
  589. // IN MMPTE PTE
  590. // );
  591. //
  592. // Routine Description:
  593. //
  594. // This macro clears the dirty bit(s) in the specified PTE.
  595. //
  596. // Arguments
  597. //
  598. // PTE - Supplies the PTE to set clear.
  599. //
  600. // Return Value:
  601. //
  602. // None.
  603. //
  604. //--
  605. #define MI_SET_PTE_CLEAN(PTE) (PTE).u.Hard.FaultOnWrite = MM_PTE_CLEAN
  606. //++
  607. //VOID
  608. //MI_IS_PTE_DIRTY (
  609. // IN MMPTE PTE
  610. // );
  611. //
  612. // Routine Description:
  613. //
  614. // This macro checks the dirty bit(s) in the specified PTE.
  615. //
  616. // Arguments
  617. //
  618. // PTE - Supplies the PTE to check.
  619. //
  620. // Return Value:
  621. //
  622. // TRUE if the page is dirty (modified), FALSE otherwise.
  623. //
  624. //--
  625. #define MI_IS_PTE_DIRTY(PTE) ((PTE).u.Hard.FaultOnWrite != MM_PTE_CLEAN)
  626. //++
  627. // VOID
  628. // MI_SET_GLOBAL_BIT_IF_SYSTEM (
  629. // OUT OUTPTE,
  630. // IN PPTE
  631. // );
  632. //
  633. // Routine Description:
  634. //
  635. // This macro sets the global bit if the pointer PTE is within
  636. // system space.
  637. //
  638. // Arguments
  639. //
  640. // OUTPTE - Supplies the PTE in which to build the valid PTE.
  641. //
  642. // PPTE - Supplies a pointer to the PTE becoming valid.
  643. //
  644. // Return Value:
  645. //
  646. // None.
  647. //
  648. //--
  649. #define MI_SET_GLOBAL_BIT_IF_SYSTEM(OUTPTE, PPTE)
  650. //++
  651. // VOID
  652. // MI_SET_GLOBAL_STATE (
  653. // IN MMPTE PTE,
  654. // IN ULONG STATE
  655. // );
  656. //
  657. // Routine Description:
  658. //
  659. // This macro sets the global bit in the PTE.
  660. //
  661. // Arguments
  662. //
  663. // PTE - Supplies the PTE to set global state into.
  664. //
  665. // Return Value:
  666. //
  667. // None.
  668. //
  669. //--
  670. #define MI_SET_GLOBAL_STATE(PTE, STATE) (PTE).u.Hard.Global = STATE;
  671. //++
  672. // VOID
  673. // MI_ENABLE_CACHING (
  674. // IN MMPTE PTE
  675. // );
  676. //
  677. // Routine Description:
  678. //
  679. // This macro takes a valid PTE and sets the caching state to be
  680. // enabled.
  681. //
  682. // Arguments
  683. //
  684. // PTE - Supplies a valid PTE.
  685. //
  686. // Return Value:
  687. //
  688. // None.
  689. //
  690. //--
  691. #define MI_ENABLE_CACHING(PTE)
  692. //++
  693. // VOID
  694. // MI_DISABLE_CACHING (
  695. // IN MMPTE PTE
  696. // );
  697. //
  698. // Routine Description:
  699. //
  700. // This macro takes a valid PTE and sets the caching state to be
  701. // disabled.
  702. //
  703. // N.B. This function performs no operation on Alpha. Caching is
  704. // never disabled.
  705. //
  706. // Arguments
  707. //
  708. // PTE - Supplies a valid PTE.
  709. //
  710. // Return Value:
  711. //
  712. // None.
  713. //
  714. //--
  715. #define MI_DISABLE_CACHING(PTE)
  716. //++
  717. // BOOLEAN
  718. // MI_IS_CACHING_DISABLED (
  719. // IN PMMPTE PPTE
  720. // );
  721. //
  722. // Routine Description:
  723. //
  724. // This macro takes a valid PTE and returns TRUE if caching is
  725. // disabled.
  726. //
  727. // N.B. This function always return FALSE for alpha.
  728. //
  729. // Arguments
  730. //
  731. // PPTE - Supplies a pointer to the valid PTE.
  732. //
  733. // Return Value:
  734. //
  735. // FALSE.
  736. //
  737. //--
  738. #define MI_IS_CACHING_DISABLED(PPTE) FALSE
  739. //++
  740. // VOID
  741. // MI_SET_PFN_DELETED (
  742. // IN PMMPFN PPFN
  743. // );
  744. //
  745. // Routine Description:
  746. //
  747. // This macro takes a pointer to a PFN element and indicates that
  748. // the PFN is no longer in use.
  749. //
  750. // Arguments
  751. //
  752. // PPTE - Supplies a pointer to the PFN element.
  753. //
  754. // Return Value:
  755. //
  756. // none.
  757. //
  758. //--
  759. #define MI_SET_PFN_DELETED(PPFN) \
  760. (((ULONG_PTR)(PPFN)->PteAddress) = ((((ULONG_PTR)(PPFN)->PteAddress) << 1) >> 1))
  761. //++
  762. //BOOLEAN
  763. //MI_IS_PFN_DELETED (
  764. // IN PMMPFN PPFN
  765. // );
  766. //
  767. // Routine Description:
  768. //
  769. // This macro takes a pointer to a PFN element and determines if
  770. // the PFN is no longer in use.
  771. //
  772. // Arguments
  773. //
  774. // PPTE - Supplies a pointer to the PFN element.
  775. //
  776. // Return Value:
  777. //
  778. // TRUE if PFN is no longer used, FALSE if it is still being used.
  779. //
  780. //--
  781. #define MI_IS_PFN_DELETED(PPFN) \
  782. ((((ULONG_PTR)(PPFN)->PteAddress) >> 63) == 0)
  783. //++
  784. // VOID
  785. // MI_CHECK_PAGE_ALIGNMENT (
  786. // IN ULONG PAGE,
  787. // IN ULONG COLOR
  788. // );
  789. //
  790. // Routine Description:
  791. //
  792. // This macro takes a PFN element number (Page) and checks to see
  793. // if the virtual alignment for the previous address of the page
  794. // is compatible with the new address of the page. If they are
  795. // not compatible, the D cache is flushed.
  796. //
  797. // Arguments
  798. //
  799. // PAGE - Supplies the PFN element.
  800. // COLOR - Supplies the new page color of the page.
  801. //
  802. // Return Value:
  803. //
  804. // none.
  805. //
  806. //--
  807. #define MI_CHECK_PAGE_ALIGNMENT(PAGE, COLOR)
  808. //++
  809. //VOID
  810. //MI_INITIALIZE_HYPERSPACE_MAP (
  811. // VOID
  812. // );
  813. //
  814. // Routine Description:
  815. //
  816. // This macro initializes the PTEs reserved for double mapping within
  817. // hyperspace.
  818. //
  819. // Arguments
  820. //
  821. // None.
  822. //
  823. // Return Value:
  824. //
  825. // None.
  826. //
  827. //--
  828. #define MI_INITIALIZE_HYPERSPACE_MAP(HYPER_PAGE)
  829. //++
  830. //ULONG
  831. //MI_GET_PAGE_COLOR_FROM_PTE (
  832. // IN PMMPTE PTEADDRESS
  833. // );
  834. //
  835. // Routine Description:
  836. //
  837. // This macro determines the pages color based on the PTE address
  838. // that maps the page.
  839. //
  840. // Arguments
  841. //
  842. // PTEADDRESS - Supplies the PTE address the page is (or was) mapped at.
  843. //
  844. // Return Value:
  845. //
  846. // The page's color.
  847. //
  848. //--
  849. #define MI_GET_PAGE_COLOR_FROM_PTE(PTEADDRESS) \
  850. ((ULONG)((MI_SYSTEM_PAGE_COLOR++) & MmSecondaryColorMask))
  851. //++
  852. //ULONG
  853. //MI_GET_PAGE_COLOR_FROM_VA (
  854. // IN PVOID ADDRESS
  855. // );
  856. //
  857. // Routine Description:
  858. //
  859. // This macro determines the pages color based on the PTE address
  860. // that maps the page.
  861. //
  862. // Arguments
  863. //
  864. // ADDRESS - Supplies the address the page is (or was) mapped at.
  865. //
  866. // Return Value:
  867. //
  868. // The pages color.
  869. //
  870. //--
  871. #define MI_GET_PAGE_COLOR_FROM_VA(ADDRESS) \
  872. ((ULONG)((MI_SYSTEM_PAGE_COLOR++) & MmSecondaryColorMask))
  873. //++
  874. //ULONG
  875. //MI_GET_PAGE_COLOR_FROM_SESSION (
  876. // IN PMM_SESSION_SPACE SessionSpace
  877. // );
  878. //
  879. // Routine Description:
  880. //
  881. // This macro determines the page's color based on the PTE address
  882. // that maps the page.
  883. //
  884. // Arguments
  885. //
  886. // SessionSpace - Supplies the session space the page will be mapped into.
  887. //
  888. // Return Value:
  889. //
  890. // The page's color.
  891. //
  892. //--
  893. #define MI_GET_PAGE_COLOR_FROM_SESSION(_SessionSpace) \
  894. ((ULONG)((_SessionSpace->Color++) & MmSecondaryColorMask))
  895. //++
  896. //ULONG
  897. //MI_PAGE_COLOR_PTE_PROCESS (
  898. // IN PMMPTE PTE,
  899. // IN PUSHORT COLOR
  900. // );
  901. //
  902. // Routine Description:
  903. //
  904. // Select page color for this process.
  905. //
  906. // Arguments
  907. //
  908. // PTE Not used.
  909. // COLOR Value from which color is determined. This
  910. // variable is incremented.
  911. //
  912. // Return Value:
  913. //
  914. // Page color.
  915. //
  916. //--
  917. #define MI_PAGE_COLOR_PTE_PROCESS(PTE,COLOR) \
  918. ((ULONG)((*(COLOR))++) & MmSecondaryColorMask)
  919. //++
  920. //ULONG
  921. //MI_PAGE_COLOR_VA_PROCESS (
  922. // IN PVOID ADDRESS,
  923. // IN PEPROCESS COLOR
  924. // );
  925. //
  926. // Routine Description:
  927. //
  928. // This macro determines the pages color based on the PTE address
  929. // that maps the page.
  930. //
  931. // Arguments
  932. //
  933. // ADDRESS - Supplies the address the page is (or was) mapped at.
  934. //
  935. // Return Value:
  936. //
  937. // The pages color.
  938. //
  939. //--
  940. #define MI_PAGE_COLOR_VA_PROCESS(ADDRESS,COLOR) \
  941. ((ULONG)((*(COLOR))++) & MmSecondaryColorMask)
  942. //++
  943. //ULONG
  944. //MI_GET_NEXT_COLOR (
  945. // IN ULONG COLOR
  946. // );
  947. //
  948. // Routine Description:
  949. //
  950. // This macro returns the next color in the sequence.
  951. //
  952. // Arguments
  953. //
  954. // COLOR - Supplies the color to return the next of.
  955. //
  956. // Return Value:
  957. //
  958. // Next color in sequence.
  959. //
  960. //--
  961. #define MI_GET_NEXT_COLOR(COLOR) ((COLOR+1) & MM_COLOR_MASK)
  962. //++
  963. //ULONG
  964. //MI_GET_PREVIOUS_COLOR (
  965. // IN ULONG COLOR
  966. // );
  967. //
  968. // Routine Description:
  969. //
  970. // This macro returns the previous color in the sequence.
  971. //
  972. // Arguments
  973. //
  974. // COLOR - Supplies the color to return the previous of.
  975. //
  976. // Return Value:
  977. //
  978. // Previous color in sequence.
  979. //
  980. //--
  981. #define MI_GET_PREVIOUS_COLOR(COLOR) ((COLOR-1) & MM_COLOR_MASK)
  982. #define MI_GET_SECONDARY_COLOR(PAGE,PFN) (PAGE & MmSecondaryColorMask)
  983. #define MI_GET_COLOR_FROM_SECONDARY(SECONDARY_COLOR) (0)
  984. //++
  985. //VOID
  986. //MI_GET_MODIFIED_PAGE_BY_COLOR (
  987. // OUT ULONG PAGE,
  988. // IN ULONG COLOR
  989. // );
  990. //
  991. // Routine Description:
  992. //
  993. // This macro returns the first page destined fro a paging
  994. // file with the desired color. It does NOT remove the page
  995. // from its list.
  996. //
  997. // Arguments
  998. //
  999. // PAGE - Returns the page located, the value MM_EMPTY_LIST is
  1000. // returned if there is no page of the specified color.
  1001. //
  1002. // COLOR - Supplies the color of page to locate.
  1003. //
  1004. // Return Value:
  1005. //
  1006. // None.
  1007. //
  1008. //--
  1009. #define MI_GET_MODIFIED_PAGE_BY_COLOR(PAGE,COLOR) \
  1010. PAGE = MmModifiedPageListByColor[COLOR].Flink
  1011. //++
  1012. //VOID
  1013. //MI_GET_MODIFIED_PAGE_ANY_COLOR (
  1014. // OUT ULONG PAGE,
  1015. // IN OUT ULONG COLOR
  1016. // );
  1017. //
  1018. // Routine Description:
  1019. //
  1020. // This macro returns the first page destined for a paging
  1021. // file with the desired color. If not page of the desired
  1022. // color exists, all colored lists are searched for a page.
  1023. // It does NOT remove the page from its list.
  1024. //
  1025. // Arguments
  1026. //
  1027. // PAGE - Returns the page located, the value MM_EMPTY_LIST is
  1028. // returned if there is no page of the specified color.
  1029. //
  1030. // COLOR - Supplies the color of the page to locate and returns the
  1031. // color of the page located.
  1032. //
  1033. // Return Value:
  1034. //
  1035. // None.
  1036. //
  1037. //--
  1038. #define MI_GET_MODIFIED_PAGE_ANY_COLOR(PAGE,COLOR) \
  1039. { \
  1040. if( MmTotalPagesForPagingFile == 0 ){ \
  1041. PAGE = MM_EMPTY_LIST; \
  1042. } else { \
  1043. while( MmModifiedPageListByColor[COLOR].Flink == MM_EMPTY_LIST ){ \
  1044. COLOR = MI_GET_NEXT_COLOR(COLOR); \
  1045. } \
  1046. PAGE = MmModifiedPageListByColor[COLOR].Flink; \
  1047. } \
  1048. }
  1049. //++
  1050. //VOID
  1051. //MI_MAKE_VALID_PTE_WRITE_COPY (
  1052. // IN OUT PMMPTE PTE
  1053. // );
  1054. //
  1055. // Routine Description:
  1056. //
  1057. // This macro checks to see if the PTE indicates that the
  1058. // page is writable and if so it clears the write bit and
  1059. // sets the copy-on-write bit.
  1060. //
  1061. // Arguments
  1062. //
  1063. // PTE - Supplies the PTE to operate upon.
  1064. //
  1065. // Return Value:
  1066. //
  1067. // None.
  1068. //
  1069. //--
  1070. #define MI_MAKE_VALID_PTE_WRITE_COPY(PPTE) \
  1071. if ((PPTE)->u.Hard.Write == 1) { \
  1072. (PPTE)->u.Hard.CopyOnWrite = 1; \
  1073. (PPTE)->u.Hard.FaultOnWrite = MM_PTE_CLEAN;\
  1074. }
  1075. //++
  1076. //ULONG
  1077. //MI_DETERMINE_OWNER (
  1078. // IN MMPTE PPTE
  1079. // );
  1080. //
  1081. // Routine Description:
  1082. //
  1083. // This macro examines the virtual address of the PTE and determines
  1084. // if the PTE resides in system space or user space.
  1085. //
  1086. // Arguments
  1087. //
  1088. // PTE - Supplies the PTE to operate upon.
  1089. //
  1090. // Return Value:
  1091. //
  1092. // 1 if the owner is USER_MODE, 0 if the owner is KERNEL_MODE.
  1093. //
  1094. //--
  1095. #define MI_DETERMINE_OWNER(PPTE) \
  1096. ((PMMPTE)(PPTE) <= MiHighestUserPte)
  1097. //++
  1098. //VOID
  1099. //MI_SET_ACCESSED_IN_PTE (
  1100. // IN OUT MMPTE PPTE
  1101. // );
  1102. //
  1103. // Routine Description:
  1104. //
  1105. // This macro sets the ACCESSED field in the PTE.
  1106. //
  1107. // Arguments
  1108. //
  1109. // PTE - Supplies the PTE to operate upon.
  1110. //
  1111. // Return Value:
  1112. //
  1113. // 1 if the owner is USER_MODE, 0 if the owner is KERNEL_MODE.
  1114. //
  1115. //--
  1116. #define MI_SET_ACCESSED_IN_PTE(PPTE,ACCESSED)
  1117. //++
  1118. //ULONG
  1119. //MI_GET_ACCESSED_IN_PTE (
  1120. // IN OUT MMPTE PPTE
  1121. // );
  1122. //
  1123. // Routine Description:
  1124. //
  1125. // This macro returns the state of the ACCESSED field in the PTE.
  1126. //
  1127. // Arguments
  1128. //
  1129. // PTE - Supplies the PTE to operate upon.
  1130. //
  1131. // Return Value:
  1132. //
  1133. // The state of the ACCESSED field.
  1134. //
  1135. //--
  1136. #define MI_GET_ACCESSED_IN_PTE(PPTE) 0
  1137. //++
  1138. //VOID
  1139. //MI_SET_OWNER_IN_PTE (
  1140. // IN PMMPTE PPTE
  1141. // IN ULONG OWNER
  1142. // );
  1143. //
  1144. // Routine Description:
  1145. //
  1146. // This macro sets the owner field in the PTE.
  1147. //
  1148. // Arguments
  1149. //
  1150. // PTE - Supplies the PTE to operate upon.
  1151. //
  1152. // Return Value:
  1153. //
  1154. // None.
  1155. //
  1156. //--
  1157. #define MI_SET_OWNER_IN_PTE(PPTE, OWNER) \
  1158. ((PPTE)->u.Hard.UserReadAccess = (PPTE)->u.Hard.UserWriteAccess = OWNER)
  1159. //++
  1160. //ULONG
  1161. //MI_GET_OWNER_IN_PTE (
  1162. // IN PMMPTE PPTE
  1163. // );
  1164. //
  1165. // Routine Description:
  1166. //
  1167. // This macro gets the owner field from the PTE.
  1168. //
  1169. // Arguments
  1170. //
  1171. // PTE - Supplies the PTE to operate upon.
  1172. //
  1173. // Return Value:
  1174. //
  1175. // The state of the OWNER field.
  1176. //
  1177. //--
  1178. #define MI_GET_OWNER_IN_PTE(PPTE) ((PPTE)->u.Hard.UserReadAccess)
  1179. //
  1180. // Mask to clear all fields but protection in a PTE to or in paging file
  1181. // location.
  1182. //
  1183. #define CLEAR_FOR_PAGE_FILE 0xF8
  1184. //++
  1185. // ULONG_PTR
  1186. // MI_SET_PAGING_FILE_INFO (
  1187. // OUT MMPTE OUTPTE,
  1188. // IN MMPTE PPTE,
  1189. // IN ULONG FILEINFO,
  1190. // IN ULONG OFFSET
  1191. // );
  1192. //
  1193. // Routine Description:
  1194. //
  1195. // This macro sets into the specified PTE the supplied information
  1196. // to indicate where the backing store for the page is located.
  1197. //
  1198. // Arguments
  1199. //
  1200. // OUTPTE - Supplies the PTE in which to store the result.
  1201. //
  1202. // PTE - Supplies the PTE to operate upon.
  1203. //
  1204. // FILEINFO - Supplies the number of the paging file.
  1205. //
  1206. // OFFSET - Supplies the offset into the paging file.
  1207. //
  1208. // Return Value:
  1209. //
  1210. // PTE Value.
  1211. //
  1212. //--
  1213. #define MI_SET_PAGING_FILE_INFO(OUTPTE,PPTE,FILEINFO,OFFSET) \
  1214. (OUTPTE).u.Long = (PPTE).u.Long; \
  1215. (OUTPTE).u.Long &= CLEAR_FOR_PAGE_FILE; \
  1216. (OUTPTE).u.Long |= ((((FILEINFO) & 0xF) << 28) | \
  1217. (((ULONG64)(OFFSET) & 0xFFFFFFFF) << 32));
  1218. //++
  1219. // PMMPTE
  1220. // MiPteToProto (
  1221. // IN OUT MMPTE PPTE
  1222. // );
  1223. //
  1224. // Routine Description:
  1225. //
  1226. // This macro returns the address of the corresponding prototype which
  1227. // was encoded earlier into the supplied PTE.
  1228. //
  1229. // Arguments
  1230. //
  1231. // lpte - Supplies the PTE to operate upon.
  1232. //
  1233. // Return Value:
  1234. //
  1235. // Pointer to the prototype PTE that backs this PTE.
  1236. //
  1237. //--
  1238. #define MiPteToProto(lpte) \
  1239. ((PMMPTE)((lpte)->u.Proto.ProtoAddress))
  1240. //++
  1241. // ULONG_PTR
  1242. // MiProtoAddressForPte (
  1243. // IN PMMPTE proto_va
  1244. // );
  1245. //
  1246. // Routine Description:
  1247. //
  1248. // This macro sets into the specified PTE the supplied information
  1249. // to indicate where the backing store for the page is located.
  1250. // MiProtoAddressForPte returns the bit field to OR into the PTE to
  1251. // reference a prototype PTE. And set the MM_PTE_PROTOTYPE_MASK PTE
  1252. // bit.
  1253. //
  1254. // N.B. This macro is dependent on the layout of the prototype PTE.
  1255. //
  1256. // Arguments
  1257. //
  1258. // proto_va - Supplies the address of the prototype PTE.
  1259. //
  1260. // Return Value:
  1261. //
  1262. // Mask to set into the PTE.
  1263. //
  1264. //--
  1265. #define MiProtoAddressForPte(proto_va) \
  1266. (((ULONG_PTR)proto_va << 16) | MM_PTE_PROTOTYPE_MASK)
  1267. //++
  1268. // ULONG_PTR
  1269. // MiProtoAddressForKernelPte (
  1270. // IN PMMPTE proto_va
  1271. // );
  1272. //
  1273. // Routine Description:
  1274. //
  1275. // This macro sets into the specified PTE the supplied information
  1276. // to indicate where the backing store for the page is located.
  1277. // MiProtoAddressForPte returns the bit field to OR into the PTE to
  1278. // reference a prototype PTE. And set the MM_PTE_PROTOTYPE_MASK PTE
  1279. // bit.
  1280. //
  1281. // This macro also sets any other information (such as global bits)
  1282. // required for kernel mode PTEs.
  1283. //
  1284. // Arguments
  1285. //
  1286. // proto_va - Supplies the address of the prototype PTE.
  1287. //
  1288. // Return Value:
  1289. //
  1290. // Mask to set into the PTE.
  1291. //
  1292. //--
  1293. #define MiProtoAddressForKernelPte(proto_va) MiProtoAddressForPte(proto_va)
  1294. //++
  1295. // PSUBSECTION
  1296. // MiGetSubsectionAddress (
  1297. // IN PMMPTE lpte
  1298. // );
  1299. //
  1300. // Routine Description:
  1301. //
  1302. // This macro takes a PTE and returns the address of the subsection that
  1303. // the PTE refers to. Subsections are quadword structures allocated from
  1304. // paged and nonpaged pool.
  1305. //
  1306. // Arguments
  1307. //
  1308. // lpte - Supplies the PTE to operate upon.
  1309. //
  1310. // Return Value:
  1311. //
  1312. // A pointer to the subsection referred to by the supplied PTE.
  1313. //
  1314. //--
  1315. #define MiGetSubsectionAddress(lpte) \
  1316. ((PSUBSECTION)((lpte)->u.Subsect.SubsectionAddress))
  1317. //++
  1318. // ULONG_PTR
  1319. // MiGetSubsectionAddressForPte (
  1320. // IN PSUBSECTION VA
  1321. // );
  1322. //
  1323. // N.B. This macro is dependent on the layout of the subsection PTE.
  1324. //
  1325. // Routine Description:
  1326. //
  1327. // This macro takes the address of a subsection and encodes it for use
  1328. // in a PTE.
  1329. //
  1330. // Arguments
  1331. //
  1332. // VA - Supplies a pointer to the subsection to encode.
  1333. //
  1334. // Return Value:
  1335. //
  1336. // The mask to set into the PTE to make it reference the supplied
  1337. // subsection.
  1338. //
  1339. //--
  1340. #define MiGetSubsectionAddressForPte(VA) ((ULONG_PTR)VA << 16)
  1341. //++
  1342. //PMMPTE
  1343. //MiGetPpeAddress (
  1344. // IN PVOID va
  1345. // );
  1346. //
  1347. // Routine Description:
  1348. //
  1349. // MiGetPpeAddress returns the address of the page directory parent entry
  1350. // which maps the given virtual address. This is one level above the
  1351. // page directory.
  1352. //
  1353. // Arguments
  1354. //
  1355. // Va - Supplies the virtual address to locate the PPE for.
  1356. //
  1357. // Return Value:
  1358. //
  1359. // The address of the PPE.
  1360. //
  1361. //--
  1362. #define MiGetPpeAddress(va) ((PMMPTE)PDE_TBASE + MiGetPpeOffset(va))
  1363. //++
  1364. //PMMPTE
  1365. //MiGetPdeAddress (
  1366. // IN PVOID va
  1367. // );
  1368. //
  1369. // Routine Description:
  1370. //
  1371. // This funtion computes the address of the second level PDE which maps
  1372. // the given virtual address. The computation is done by recursively
  1373. // applying the computation to find the PTE that maps the virtual address.
  1374. //
  1375. // Arguments
  1376. //
  1377. // Va - Supplies the virtual address for which to compute the second level
  1378. // PDE address.
  1379. //
  1380. // Return Value:
  1381. //
  1382. // The address of the PDE.
  1383. //
  1384. //--
  1385. #define MiGetPdeAddress(va) \
  1386. MiGetPteAddress(MiGetPteAddress(va))
  1387. #define MiGetPdeAddress64(va) \
  1388. MiGetPteAddress(MiGetPteAddress(va))
  1389. //++
  1390. //PMMPTE
  1391. //MiGetPteAddress (
  1392. // IN PVOID va
  1393. // );
  1394. //
  1395. // Routine Description:
  1396. //
  1397. // MiGetPteAddress returns the address of the PTE which maps the
  1398. // given virtual address.
  1399. //
  1400. // Arguments
  1401. //
  1402. // Va - Supplies the virtual address to locate the PTE for.
  1403. //
  1404. // Return Value:
  1405. //
  1406. // The address of the PTE.
  1407. //
  1408. //--
  1409. #define MiGetPteAddress(va) \
  1410. ((PMMPTE)(((((ULONG_PTR)(va) & MASK_43) >> PTI_SHIFT) << 3) + PTE_BASE))
  1411. #define MiGetPteAddress64(va) \
  1412. ((PMMPTE)(((((ULONG_PTR)(va) & MASK_43) >> PTI_SHIFT) << 3) + PTE_BASE))
  1413. //++
  1414. // ULONG
  1415. // MiGetPpeOffset (
  1416. // IN PVOID va
  1417. // );
  1418. //
  1419. // Routine Description:
  1420. //
  1421. // MiGetPpeOffset returns the offset into a page directory parent for a
  1422. // given virtual address.
  1423. //
  1424. // Arguments
  1425. //
  1426. // Va - Supplies the virtual address to locate the offset for.
  1427. //
  1428. // Return Value:
  1429. //
  1430. // The offset into the parent page directory table the corresponding
  1431. // PPE is at.
  1432. //
  1433. //--
  1434. #define MiGetPpeOffset(va) ((ULONG)(((ULONG_PTR)(va) >> PDI1_SHIFT) & PDI_MASK))
  1435. //++
  1436. //ULONG
  1437. //MiGetPpeIndex (
  1438. // IN PVOID va
  1439. // );
  1440. //
  1441. // Routine Description:
  1442. //
  1443. // MiGetPpeIndex returns the page directory parent index
  1444. // for a given virtual address.
  1445. //
  1446. // N.B. This does not mask off PXE bits.
  1447. //
  1448. // Arguments
  1449. //
  1450. // Va - Supplies the virtual address to locate the index for.
  1451. //
  1452. // Return Value:
  1453. //
  1454. // The index into the page directory parent - ie: the virtual page directory
  1455. // number. This is different from the page directory parent offset because
  1456. // this spans page directory parents on supported platforms.
  1457. //--
  1458. #define MiGetPpeIndex(va) ((ULONG)((ULONG_PTR)(va) >> PDI1_SHIFT))
  1459. //++
  1460. // ULONG
  1461. // MiGetPdeOffset (
  1462. // IN PVOID va
  1463. // );
  1464. //
  1465. // Routine Description:
  1466. //
  1467. // MiGetPdeOffset returns the offset into a page directory for a given
  1468. // virtual address.
  1469. //
  1470. // Arguments
  1471. //
  1472. // Va - Supplies the virtual address to locate the offset for.
  1473. //
  1474. // Return Value:
  1475. //
  1476. // The offset into the page directory table the corresponding PDE is at.
  1477. //
  1478. //--
  1479. #define MiGetPdeOffset(va) ((ULONG)(((ULONG_PTR)(va) >> PDI2_SHIFT) & PDI_MASK))
  1480. //++
  1481. //ULONG
  1482. //MiGetPdeIndex (
  1483. // IN PVOID va
  1484. // );
  1485. //
  1486. // Routine Description:
  1487. //
  1488. // MiGetPdeIndex returns the page directory index
  1489. // for a given virtual address.
  1490. //
  1491. // N.B. This does not mask off PPE bits.
  1492. //
  1493. // Arguments
  1494. //
  1495. // Va - Supplies the virtual address to locate the offset for.
  1496. //
  1497. // Return Value:
  1498. //
  1499. // The index into the page directory - ie: the virtual page table number.
  1500. // This is different from the page directory offset because this spans
  1501. // page directories on supported platforms.
  1502. //
  1503. //--
  1504. #define MiGetPdeIndex(va) ((ULONG)((ULONG_PTR)(va) >> PDI2_SHIFT))
  1505. //++
  1506. // ULONG
  1507. // MiGetPteOffset (
  1508. // IN PVOID va
  1509. // );
  1510. //
  1511. // Routine Description:
  1512. //
  1513. // MiGetPteOffset returns the offset into a page table page for a given
  1514. // virtual address.
  1515. //
  1516. // Arguments
  1517. //
  1518. // Va - Supplies the virtual address to locate the offset for.
  1519. //
  1520. // Return Value:
  1521. //
  1522. // The offset into the page table page table the corresponding PTE is at.
  1523. //
  1524. //--
  1525. #define MiGetPteOffset(va) ((ULONG)(((ULONG_PTR)(va) >> PTI_SHIFT) & PDI_MASK))
  1526. //++
  1527. //PVOID
  1528. //MiGetVirtualAddressMappedByPpe (
  1529. // IN PMMPTE PTE
  1530. // );
  1531. //
  1532. // Routine Description:
  1533. //
  1534. // MiGetVirtualAddressMappedByPpe returns the virtual address
  1535. // which is mapped by a given PPE address.
  1536. //
  1537. // Arguments
  1538. //
  1539. // PPE - Supplies the PPE to get the virtual address for.
  1540. //
  1541. // Return Value:
  1542. //
  1543. // Virtual address mapped by the PPE.
  1544. //
  1545. //--
  1546. #define MiGetVirtualAddressMappedByPpe(PPE) \
  1547. MiGetVirtualAddressMappedByPte(MiGetVirtualAddressMappedByPde(PPE))
  1548. //++
  1549. //PVOID
  1550. //MiGetVirtualAddressMappedByPde (
  1551. // IN PMMPTE PDE
  1552. // );
  1553. //
  1554. // Routine Description:
  1555. //
  1556. // MiGetVirtualAddressMappedByPde returns the virtual address
  1557. // which is mapped by a given PDE address.
  1558. //
  1559. // Arguments
  1560. //
  1561. // PDE - Supplies the PDE to get the virtual address for.
  1562. //
  1563. // Return Value:
  1564. //
  1565. // Virtual address mapped by the PDE.
  1566. //
  1567. //--
  1568. #define MiGetVirtualAddressMappedByPde(Pde) \
  1569. MiGetVirtualAddressMappedByPte(MiGetVirtualAddressMappedByPte(Pde))
  1570. //++
  1571. //PVOID
  1572. //MiGetVirtualAddressMappedByPte (
  1573. // IN PMMPTE PTE
  1574. // );
  1575. //
  1576. // Routine Description:
  1577. //
  1578. // MiGetVirtualAddressMappedByPte returns the virtual address
  1579. // which is mapped by a given PTE address.
  1580. //
  1581. // Arguments
  1582. //
  1583. // PTE - Supplies the PTE to get the virtual address for.
  1584. //
  1585. // Return Value:
  1586. //
  1587. // Virtual address mapped by the PTE.
  1588. //
  1589. //--
  1590. #define MiGetVirtualAddressMappedByPte(Pte) \
  1591. ((PVOID)((LONG_PTR)(((LONG_PTR)(Pte) - PTE_BASE) << (PAGE_SHIFT + VA_SHIFT - 3)) >> VA_SHIFT))
  1592. #define MiGetVirtualAddressMappedByPte64(Pte) \
  1593. ((PVOID)((LONG_PTR)(((LONG_PTR)(Pte) - PTE_BASE64) << (PAGE_SHIFT + VA_SHIFT - 3)) >> VA_SHIFT))
  1594. #define MiGetVirtualPageNumberMappedByPte64(Pte) \
  1595. ((PVOID)(((ULONG_PTR)(Pte) - PTE_BASE64) >> 3))
  1596. //++
  1597. //LOGICAL
  1598. //MiIsVirtualAddressOnPpeBoundary (
  1599. // IN PVOID VA
  1600. // );
  1601. //
  1602. // Routine Description:
  1603. //
  1604. // MiIsVirtualAddressOnPpeBoundary returns TRUE if the virtual address is
  1605. // on a page directory entry boundary.
  1606. //
  1607. // Arguments
  1608. //
  1609. // VA - Supplies the virtual address to check.
  1610. //
  1611. // Return Value:
  1612. //
  1613. // TRUE if on a boundary, FALSE if not.
  1614. //
  1615. //--
  1616. #define MiIsVirtualAddressOnPpeBoundary(VA) (((ULONG_PTR)(VA) & PAGE_DIRECTORY1_MASK) == 0)
  1617. //++
  1618. //LOGICAL
  1619. //MiIsVirtualAddressOnPdeBoundary (
  1620. // IN PVOID VA
  1621. // );
  1622. //
  1623. // Routine Description:
  1624. //
  1625. // MiIsVirtualAddressOnPdeBoundary returns TRUE if the virtual address is
  1626. // on a page directory entry boundary.
  1627. //
  1628. // Arguments
  1629. //
  1630. // VA - Supplies the virtual address to check.
  1631. //
  1632. // Return Value:
  1633. //
  1634. // TRUE if on an 8MB PDE boundary, FALSE if not.
  1635. //
  1636. //--
  1637. #define MiIsVirtualAddressOnPdeBoundary(VA) (((ULONG_PTR)(VA) & PAGE_DIRECTORY2_MASK) == 0)
  1638. //++
  1639. //LOGICAL
  1640. //MiIsPteOnPpeBoundary (
  1641. // IN PVOID VA
  1642. // );
  1643. //
  1644. // Routine Description:
  1645. //
  1646. // MiIsPteOnPpeBoundary returns TRUE if the PTE is
  1647. // on a page directory parent entry boundary.
  1648. //
  1649. // Arguments
  1650. //
  1651. // VA - Supplies the virtual address to check.
  1652. //
  1653. // Return Value:
  1654. //
  1655. // TRUE if on a boundary, FALSE if not.
  1656. //
  1657. //--
  1658. #define MiIsPteOnPpeBoundary(PTE) (((ULONG_PTR)(PTE) & (MM_VA_MAPPED_BY_PDE - 1)) == 0)
  1659. //++
  1660. //LOGICAL
  1661. //MiIsPteOnPdeBoundary (
  1662. // IN PVOID PTE
  1663. // );
  1664. //
  1665. // Routine Description:
  1666. //
  1667. // MiIsPteOnPdeBoundary returns TRUE if the PTE is
  1668. // on a page directory entry boundary.
  1669. //
  1670. // Arguments
  1671. //
  1672. // PTE - Supplies the PTE to check.
  1673. //
  1674. // Return Value:
  1675. //
  1676. // TRUE if on a 8MB PDE boundary, FALSE if not.
  1677. //
  1678. //--
  1679. #define MiIsPteOnPdeBoundary(PTE) (((ULONG_PTR)(PTE) & (PAGE_SIZE - 1)) == 0)
  1680. //++
  1681. //ULONG
  1682. //GET_PAGING_FILE_NUMBER (
  1683. // IN MMPTE PTE
  1684. // );
  1685. //
  1686. // Routine Description:
  1687. //
  1688. // This macro extracts the paging file number from a PTE.
  1689. //
  1690. // Arguments
  1691. //
  1692. // PTE - Supplies the PTE to operate upon.
  1693. //
  1694. // Return Value:
  1695. //
  1696. // The paging file number.
  1697. //
  1698. //--
  1699. #define GET_PAGING_FILE_NUMBER(PTE) ((ULONG)(((PTE).u.Soft.PageFileLow)))
  1700. //++
  1701. //ULONG
  1702. //GET_PAGING_FILE_OFFSET (
  1703. // IN MMPTE PTE
  1704. // );
  1705. //
  1706. // Routine Description:
  1707. //
  1708. // This macro extracts the offset into the paging file from a PTE.
  1709. //
  1710. // Arguments
  1711. //
  1712. // PTE - Supplies the PTE to operate upon.
  1713. //
  1714. // Return Value:
  1715. //
  1716. // The paging file offset.
  1717. //
  1718. //--
  1719. #define GET_PAGING_FILE_OFFSET(PTE) ((ULONG)(((PTE).u.Soft.PageFileHigh)))
  1720. //++
  1721. //ULONG
  1722. //IS_PTE_NOT_DEMAND_ZERO (
  1723. // IN PMMPTE PPTE
  1724. // );
  1725. //
  1726. // Routine Description:
  1727. //
  1728. // This macro checks to see if a given PTE is NOT a demand zero PTE.
  1729. //
  1730. // Arguments
  1731. //
  1732. // PTE - Supplies the PTE to operate upon.
  1733. //
  1734. // Return Value:
  1735. //
  1736. // Returns 0 if the PTE is demand zero, non-zero otherwise.
  1737. //
  1738. //--
  1739. #define IS_PTE_NOT_DEMAND_ZERO(PTE) ((PTE).u.Long & ~0xFE)
  1740. //++
  1741. //VOID
  1742. //MI_MAKING_VALID_PTE_INVALID(
  1743. // IN PMMPTE PPTE
  1744. // );
  1745. //
  1746. // Routine Description:
  1747. //
  1748. // Prepare to make a single valid PTE invalid.
  1749. // No action is required on x86.
  1750. //
  1751. // Arguments
  1752. //
  1753. // SYSTEM_WIDE - Supplies TRUE if this will happen on all processors.
  1754. //
  1755. // Return Value:
  1756. //
  1757. // None.
  1758. //
  1759. //--
  1760. #define MI_MAKING_VALID_PTE_INVALID(SYSTEM_WIDE)
  1761. //++
  1762. //VOID
  1763. //MI_MAKING_VALID_MULTIPLE_PTES_INVALID(
  1764. // IN PMMPTE PPTE
  1765. // );
  1766. //
  1767. // Routine Description:
  1768. //
  1769. // Prepare to make multiple valid PTEs invalid.
  1770. // No action is required on x86.
  1771. //
  1772. // Arguments
  1773. //
  1774. // SYSTEM_WIDE - Supplies TRUE if this will happen on all processors.
  1775. //
  1776. // Return Value:
  1777. //
  1778. // None.
  1779. //
  1780. //--
  1781. #define MI_MAKING_MULTIPLE_PTES_INVALID(SYSTEM_WIDE)
  1782. //++
  1783. //VOID
  1784. //MI_MAKE_PROTECT_WRITE_COPY (
  1785. // IN OUT MMPTE PPTE
  1786. // );
  1787. //
  1788. // Routine Description:
  1789. //
  1790. // This macro makes a writable PTE a writable-copy PTE.
  1791. //
  1792. // Arguments
  1793. //
  1794. // PTE - Supplies the PTE to operate upon.
  1795. //
  1796. // Return Value:
  1797. //
  1798. // NONE
  1799. //
  1800. //--
  1801. #define MI_MAKE_PROTECT_WRITE_COPY(PTE) \
  1802. if ((PTE).u.Long & 0x20) { \
  1803. ((PTE).u.Long |= 0x8); \
  1804. }
  1805. //++
  1806. //VOID
  1807. //MI_SET_PAGE_DIRTY(
  1808. // IN PMMPTE PPTE,
  1809. // IN PVOID VA,
  1810. // IN PVOID PFNHELD
  1811. // );
  1812. //
  1813. // Routine Description:
  1814. //
  1815. // This macro sets the dirty bit (and release page file space).
  1816. //
  1817. // Arguments
  1818. //
  1819. // TEMP - Supplies a temporary for usage.
  1820. //
  1821. // PPTE - Supplies a pointer to the PTE that corresponds to VA.
  1822. //
  1823. // VA - Supplies a the virtual address of the page fault.
  1824. //
  1825. // PFNHELD - Supplies TRUE if the PFN lock is held.
  1826. //
  1827. // Return Value:
  1828. //
  1829. // None.
  1830. //
  1831. //--
  1832. #define MI_SET_PAGE_DIRTY(PPTE,VA,PFNHELD) \
  1833. if ((PPTE)->u.Hard.FaultOnWrite == MM_PTE_CLEAN) { \
  1834. MiSetDirtyBit ((VA),(PPTE),(PFNHELD)); \
  1835. }
  1836. //++
  1837. //VOID
  1838. //MI_NO_FAULT_FOUND(
  1839. // IN TEMP,
  1840. // IN PMMPTE PPTE,
  1841. // IN PVOID VA,
  1842. // IN PVOID PFNHELD
  1843. // );
  1844. //
  1845. // Routine Description:
  1846. //
  1847. // This macro handles the case when a page fault is taken and no
  1848. // PTE with the valid bit clear is found.
  1849. //
  1850. // Arguments
  1851. //
  1852. // TEMP - Supplies a temporary for usage.
  1853. //
  1854. // PPTE - Supplies a pointer to the PTE that corresponds to VA.
  1855. //
  1856. // VA - Supplies a the virtual address of the page fault.
  1857. //
  1858. // PFNHELD - Supplies TRUE if the PFN lock is held.
  1859. //
  1860. // Return Value:
  1861. //
  1862. // None.
  1863. //
  1864. //--
  1865. #define MI_NO_FAULT_FOUND(TEMP, PPTE, VA, PFNHELD) \
  1866. if (StoreInstruction && ((PPTE)->u.Hard.FaultOnWrite == MM_PTE_CLEAN)) { \
  1867. MiSetDirtyBit((VA),(PPTE), (PFNHELD)); \
  1868. } else { \
  1869. KiFlushSingleTb(1, VA); \
  1870. }
  1871. //++
  1872. //ULONG
  1873. //MI_CAPTURE_DIRTY_BIT_TO_PFN (
  1874. // IN PMMPTE PPTE,
  1875. // IN PMMPFN PPFN
  1876. // );
  1877. //
  1878. // Routine Description:
  1879. //
  1880. // This macro gets captures the state of the dirty bit to the PFN
  1881. // and frees any associated page file space if the PTE has been
  1882. // modified element.
  1883. //
  1884. // NOTE - THE PFN LOCK MUST BE HELD!
  1885. //
  1886. // Arguments
  1887. //
  1888. // PPTE - Supplies the PTE to operate upon.
  1889. //
  1890. // PPFN - Supplies a pointer to the PFN database element that corresponds
  1891. // to the page mapped by the PTE.
  1892. //
  1893. // Return Value:
  1894. //
  1895. // None.
  1896. //
  1897. //--
  1898. #define MI_CAPTURE_DIRTY_BIT_TO_PFN(PPTE,PPFN) \
  1899. if (((PPFN)->u3.e1.Modified == 0) && \
  1900. ((PPTE)->u.Hard.FaultOnWrite == MM_PTE_DIRTY)) { \
  1901. (PPFN)->u3.e1.Modified = 1; \
  1902. if (((PPFN)->OriginalPte.u.Soft.Prototype == 0) && \
  1903. ((PPFN)->u3.e1.WriteInProgress == 0)) { \
  1904. MiReleasePageFileSpace ((PPFN)->OriginalPte); \
  1905. (PPFN)->OriginalPte.u.Soft.PageFileHigh = 0; \
  1906. } \
  1907. }
  1908. //++
  1909. //BOOLEAN
  1910. //MI_IS_PHYSICAL_ADDRESS (
  1911. // IN PVOID VA
  1912. // );
  1913. //
  1914. // Routine Description:
  1915. //
  1916. // This macro determines if a give virtual address is really a
  1917. // physical address.
  1918. //
  1919. // Arguments
  1920. //
  1921. // VA - Supplies the virtual address.
  1922. //
  1923. // Return Value:
  1924. //
  1925. // FALSE if it is not a physical address, TRUE if it is.
  1926. //
  1927. //--
  1928. #define MI_IS_PHYSICAL_ADDRESS(Va) \
  1929. ((((ULONG_PTR)(Va) >= KSEG43_BASE) && ((ULONG_PTR)(Va) < KSEG43_LIMIT)) || \
  1930. (((ULONG_PTR)(Va) >= KSEG0_BASE) && ((ULONG_PTR)(Va) < KSEG2_BASE)))
  1931. //++
  1932. //PFN_NUMBER
  1933. //MI_CONVERT_PHYSICAL_TO_PFN (
  1934. // IN PVOID VA
  1935. // );
  1936. //
  1937. // Routine Description:
  1938. //
  1939. // This macro converts a physical address (see MI_IS_PHYSICAL_ADDRESS)
  1940. // to its corresponding physical frame number.
  1941. //
  1942. // Arguments
  1943. //
  1944. // VA - Supplies a pointer to the physical address.
  1945. //
  1946. // Return Value:
  1947. //
  1948. // Returns the PFN for the page.
  1949. //
  1950. //--
  1951. #define MI_CONVERT_PHYSICAL_TO_PFN(Va) \
  1952. (((ULONG_PTR)(Va) < KSEG0_BASE) ? \
  1953. ((PFN_NUMBER)(((ULONG_PTR)(Va) - KSEG43_BASE) >> PAGE_SHIFT)) : \
  1954. ((PFN_NUMBER)(((ULONG_PTR)(Va) - KSEG0_BASE) >> PAGE_SHIFT)))
  1955. //++
  1956. // PFN_NUMBER
  1957. // MI_CONVERT_PHYSICAL_BUS_TO_PFN(
  1958. // PHYSICAL_ADDRESS Pa,
  1959. // )
  1960. //
  1961. // Routine Description:
  1962. //
  1963. // This macro takes a physical address and returns the pfn to which
  1964. // it corresponds.
  1965. //
  1966. // Arguments
  1967. //
  1968. // Pa - Supplies the physical address to convert.
  1969. //
  1970. // Return Value:
  1971. //
  1972. // The Pfn that corresponds to the physical address is returned.
  1973. //
  1974. //--
  1975. #define MI_CONVERT_PHYSICAL_BUS_TO_PFN(Pa) \
  1976. ((PFN_NUMBER)((Pa).QuadPart >> ((CCHAR)PAGE_SHIFT)))
  1977. typedef struct _MMCOLOR_TABLES {
  1978. PFN_NUMBER Flink;
  1979. PVOID Blink;
  1980. } MMCOLOR_TABLES, *PMMCOLOR_TABLES;
  1981. typedef struct _MMPRIMARY_COLOR_TABLES {
  1982. LIST_ENTRY ListHead;
  1983. } MMPRIMARY_COLOR_TABLES, *PMMPRIMARY_COLOR_TABLES;
  1984. #if MM_MAXIMUM_NUMBER_OF_COLORS > 1
  1985. extern MMPFNLIST MmFreePagesByPrimaryColor[2][MM_MAXIMUM_NUMBER_OF_COLORS];
  1986. #endif
  1987. extern PMMCOLOR_TABLES MmFreePagesByColor[2];
  1988. extern PFN_NUMBER MmTotalPagesForPagingFile;
  1989. #define MI_PTE_LOOKUP_NEEDED ((ULONG64)0xffffffff)
  1990. //
  1991. // The hardware PTE is defined in ntos\inc\alpha.h.
  1992. //
  1993. // Invalid PTEs have the following definition.
  1994. //
  1995. typedef struct _MMPTE_SOFTWARE {
  1996. ULONGLONG Valid: 1;
  1997. ULONGLONG Prototype : 1;
  1998. ULONGLONG Transition : 1;
  1999. ULONGLONG Protection : 5;
  2000. ULONGLONG UsedPageTableEntries : PTE_PER_PAGE_BITS;
  2001. ULONGLONG Reserved : 20 - PTE_PER_PAGE_BITS;
  2002. ULONGLONG PageFileLow: 4;
  2003. ULONGLONG PageFileHigh : 32;
  2004. } MMPTE_SOFTWARE;
  2005. typedef struct _MMPTE_TRANSITION {
  2006. ULONGLONG Valid : 1;
  2007. ULONGLONG Prototype : 1;
  2008. ULONGLONG Transition : 1;
  2009. ULONGLONG Protection : 5;
  2010. ULONGLONG filler01 : 24;
  2011. ULONGLONG PageFrameNumber : 32;
  2012. } MMPTE_TRANSITION;
  2013. typedef struct _MMPTE_PROTOTYPE {
  2014. ULONGLONG Valid : 1;
  2015. ULONGLONG Prototype : 1;
  2016. ULONGLONG ReadOnly : 1;
  2017. ULONGLONG Protection : 5;
  2018. ULONGLONG filler02 : 8;
  2019. LONGLONG ProtoAddress : 48;
  2020. } MMPTE_PROTOTYPE;
  2021. typedef struct _MMPTE_LIST {
  2022. ULONGLONG Valid : 1;
  2023. ULONGLONG filler07 : 7;
  2024. ULONGLONG OneEntry : 1;
  2025. ULONGLONG filler03 : 23;
  2026. ULONGLONG NextEntry : 32;
  2027. } MMPTE_LIST;
  2028. typedef struct _MMPTE_SUBSECTION {
  2029. ULONGLONG Valid : 1;
  2030. ULONGLONG Prototype : 1;
  2031. ULONGLONG WhichPool : 1;
  2032. ULONGLONG Protection : 5;
  2033. ULONGLONG Filler04 : 8;
  2034. LONGLONG SubsectionAddress : 48;
  2035. } MMPTE_SUBSECTION;
  2036. //
  2037. // A Valid Page Table Entry on a DEC AXP64 system has the following format.
  2038. //
  2039. // typedef struct _HARDWARE_PTE {
  2040. // ULONGLONG Valid : 1;
  2041. // ULONGLONG Reserved1 : 1;
  2042. // ULONGLONG FaultOnWrite : 1;
  2043. // ULONGLONG Reserved2 : 1;
  2044. // ULONGLONG Global : 1;
  2045. // ULONGLONG GranularityHint : 2;
  2046. // ULONGLONG Reserved3 : 1;
  2047. // ULONGLONG KernelReadAccess : 1;
  2048. // ULONGLONG UserReadAccess : 1;
  2049. // ULONGLONG Reserved4 : 2;
  2050. // ULONGLONG KernelWriteAccess : 1;
  2051. // ULONGLONG UserWriteAccess : 1;
  2052. // ULONGLONG Reserved5 : 2;
  2053. // ULONGLONG Write : 1;
  2054. // ULONGLONG CopyOnWrite: 1;
  2055. // ULONGLONG SoftwareWsIndex : 14;
  2056. // ULONGLONG PageFrameNumber : 32;
  2057. // } HARDWARE_PTE, *PHARDWARE_PTE;
  2058. //
  2059. #define MI_GET_PAGE_FRAME_FROM_PTE(PTE) ((PFN_NUMBER)(PTE)->u.Hard.PageFrameNumber)
  2060. #define MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE(PTE) ((PFN_NUMBER)(PTE)->u.Trans.PageFrameNumber)
  2061. #define MI_GET_PROTECTION_FROM_SOFT_PTE(PTE) ((ULONG)(PTE)->u.Soft.Protection)
  2062. #define MI_GET_PROTECTION_FROM_TRANSITION_PTE(PTE) ((ULONG)(PTE)->u.Trans.Protection)
  2063. //
  2064. // A Page Table Entry on a DEC ALPHA has the following definition.
  2065. //
  2066. typedef struct _MMPTE {
  2067. union {
  2068. ULONG_PTR Long;
  2069. HARDWARE_PTE Hard;
  2070. HARDWARE_PTE Flush;
  2071. MMPTE_PROTOTYPE Proto;
  2072. MMPTE_SOFTWARE Soft;
  2073. MMPTE_TRANSITION Trans;
  2074. MMPTE_LIST List;
  2075. MMPTE_SUBSECTION Subsect;
  2076. } u;
  2077. } MMPTE, *PMMPTE;
  2078. //++
  2079. //VOID
  2080. //MI_WRITE_VALID_PTE (
  2081. // IN PMMPTE PointerPte,
  2082. // IN MMPTE PteContents
  2083. // );
  2084. //
  2085. // Routine Description:
  2086. //
  2087. // MI_WRITE_VALID_PTE fills in the specified PTE making it valid with the
  2088. // specified contents.
  2089. //
  2090. // Arguments
  2091. //
  2092. // PointerPte - Supplies a PTE to fill.
  2093. //
  2094. // PteContents - Supplies the contents to put in the PTE.
  2095. //
  2096. // Return Value:
  2097. //
  2098. // None.
  2099. //
  2100. //--
  2101. #define MI_WRITE_VALID_PTE(_PointerPte, _PteContents) \
  2102. (*(_PointerPte) = (_PteContents))
  2103. //++
  2104. //VOID
  2105. //MI_WRITE_INVALID_PTE (
  2106. // IN PMMPTE PointerPte,
  2107. // IN MMPTE PteContents
  2108. // );
  2109. //
  2110. // Routine Description:
  2111. //
  2112. // MI_WRITE_INVALID_PTE fills in the specified PTE making it invalid with the
  2113. // specified contents.
  2114. //
  2115. // Arguments
  2116. //
  2117. // PointerPte - Supplies a PTE to fill.
  2118. //
  2119. // PteContents - Supplies the contents to put in the PTE.
  2120. //
  2121. // Return Value:
  2122. //
  2123. // None.
  2124. //
  2125. //--
  2126. #define MI_WRITE_INVALID_PTE(_PointerPte, _PteContents) \
  2127. (*(_PointerPte) = (_PteContents))
  2128. //++
  2129. //VOID
  2130. //MI_WRITE_VALID_PTE_NEW_PROTECTION (
  2131. // IN PMMPTE PointerPte,
  2132. // IN MMPTE PteContents
  2133. // );
  2134. //
  2135. // Routine Description:
  2136. //
  2137. // MI_WRITE_VALID_PTE_NEW_PROTECTION fills in the specified PTE (which was
  2138. // already valid) changing only the protection or the dirty bit.
  2139. //
  2140. // Arguments
  2141. //
  2142. // PointerPte - Supplies a PTE to fill.
  2143. //
  2144. // PteContents - Supplies the contents to put in the PTE.
  2145. //
  2146. // Return Value:
  2147. //
  2148. // None.
  2149. //
  2150. //--
  2151. #define MI_WRITE_VALID_PTE_NEW_PROTECTION(_PointerPte, _PteContents) \
  2152. (*(_PointerPte) = (_PteContents))
  2153. //++
  2154. //VOID
  2155. //MiFillMemoryPte (
  2156. // IN PMMPTE Destination,
  2157. // IN ULONG Length,
  2158. // IN MMPTE Pattern,
  2159. // };
  2160. //
  2161. // Routine Description:
  2162. //
  2163. // This function fills memory with the specified PTE pattern.
  2164. //
  2165. // Arguments
  2166. //
  2167. // Destination - Supplies a pointer to the memory to fill.
  2168. //
  2169. // Length - Supplies the length, in bytes, of the memory to be
  2170. // filled.
  2171. //
  2172. // Pattern - Supplies the PTE fill pattern.
  2173. //
  2174. // Return Value:
  2175. //
  2176. // None.
  2177. //
  2178. //--
  2179. #define MiFillMemoryPte(Destination, Length, Pattern) \
  2180. RtlFillMemoryUlonglong((Destination), (Length), (Pattern))
  2181. //++
  2182. //BOOLEAN
  2183. //MI_IS_PAGE_TABLE_ADDRESS (
  2184. // IN PVOID VA
  2185. // );
  2186. //
  2187. // Routine Description:
  2188. //
  2189. // This macro takes a virtual address and determines if
  2190. // it is a page table address.
  2191. //
  2192. // Arguments
  2193. //
  2194. // VA - Supplies a virtual address.
  2195. //
  2196. // Return Value:
  2197. //
  2198. // TRUE if the address is a page table address, FALSE if not.
  2199. //
  2200. //--
  2201. #define MI_IS_PAGE_TABLE_ADDRESS(VA) \
  2202. ((PVOID)(VA) >= (PVOID)PTE_BASE && (PVOID)(VA) <= (PVOID)PDE_TOP)
  2203. //++
  2204. //BOOLEAN
  2205. //MI_IS_KERNEL_PAGE_TABLE_ADDRESS (
  2206. // IN PVOID VA
  2207. // );
  2208. //
  2209. // Routine Description:
  2210. //
  2211. // This macro takes a virtual address and determines if
  2212. // it is a page table address for a kernel address.
  2213. //
  2214. // Arguments
  2215. //
  2216. // VA - Supplies a virtual address.
  2217. //
  2218. // Return Value:
  2219. //
  2220. // TRUE if the address is a kernel page table address, FALSE if not.
  2221. //
  2222. //--
  2223. #define MI_IS_KERNEL_PAGE_TABLE_ADDRESS(VA) \
  2224. ((PVOID)(VA) >= (PVOID)MiGetPteAddress(MmSystemRangeStart) && (PVOID)(VA) <= (PVOID)PDE_TOP)
  2225. //++
  2226. //BOOLEAN
  2227. //MI_IS_PAGE_DIRECTORY_ADDRESS (
  2228. // IN PVOID VA
  2229. // );
  2230. //
  2231. // Routine Description:
  2232. //
  2233. // This macro takes a virtual address and determines if
  2234. // it is a page directory address.
  2235. //
  2236. // Arguments
  2237. //
  2238. // VA - Supplies a virtual address.
  2239. //
  2240. // Return Value:
  2241. //
  2242. // TRUE if the address is a page directory address, FALSE if not.
  2243. //
  2244. //--
  2245. #define MI_IS_PAGE_DIRECTORY_ADDRESS(VA) \
  2246. ((PVOID)(VA) >= (PVOID)PDE_UBASE && (PVOID)(VA) <= (PVOID)PDE_TOP)
  2247. //++
  2248. //BOOLEAN
  2249. //MI_IS_HYPER_SPACE_ADDRESS (
  2250. // IN PVOID VA
  2251. // );
  2252. //
  2253. // Routine Description:
  2254. //
  2255. // This macro takes a virtual address and determines if
  2256. // it is a hyper space address.
  2257. //
  2258. // Arguments
  2259. //
  2260. // VA - Supplies a virtual address.
  2261. //
  2262. // Return Value:
  2263. //
  2264. // TRUE if the address is a hyper space address, FALSE if not.
  2265. //
  2266. //--
  2267. #define MI_IS_HYPER_SPACE_ADDRESS(VA) \
  2268. ((PVOID)(VA) >= (PVOID)HYPER_SPACE && (PVOID)(VA) <= (PVOID)HYPER_SPACE_END)
  2269. //++
  2270. //BOOLEAN
  2271. //MI_IS_PROCESS_SPACE_ADDRESS (
  2272. // IN PVOID VA
  2273. // );
  2274. //
  2275. // Routine Description:
  2276. //
  2277. // This macro takes a virtual address and determines if
  2278. // it is a process-specific address. This is an address in user space
  2279. // or page table pages or hyper space.
  2280. //
  2281. // Arguments
  2282. //
  2283. // VA - Supplies a virtual address.
  2284. //
  2285. // Return Value:
  2286. //
  2287. // TRUE if the address is a process-specific address, FALSE if not.
  2288. //
  2289. //--
  2290. #define MI_IS_PROCESS_SPACE_ADDRESS(VA) \
  2291. (((PVOID)(VA) <= (PVOID)MM_HIGHEST_USER_ADDRESS) || \
  2292. ((PVOID)(VA) >= (PVOID)PTE_BASE && (PVOID)(VA) <= (PVOID)HYPER_SPACE_END))
  2293. //++
  2294. //BOOLEAN
  2295. //MI_IS_PTE_PROTOTYPE (
  2296. // IN PMMPTE PTE
  2297. // );
  2298. //
  2299. // Routine Description:
  2300. //
  2301. // This macro takes a PTE address and determines if it is a prototype PTE.
  2302. //
  2303. // Arguments
  2304. //
  2305. // PTE - Supplies the virtual address of the PTE to check.
  2306. //
  2307. // Return Value:
  2308. //
  2309. // TRUE if the PTE is in a segment (ie, a prototype PTE), FALSE if not.
  2310. //
  2311. //--
  2312. #define MI_IS_PTE_PROTOTYPE(PTE) \
  2313. ((PTE) > (PMMPTE)PDE_TOP)
  2314. //++
  2315. //BOOLEAN
  2316. //MI_IS_SYSTEM_CACHE_ADDRESS (
  2317. // IN PVOID VA
  2318. // );
  2319. //
  2320. // Routine Description:
  2321. //
  2322. // This macro takes a virtual address and determines if
  2323. // it is a system cache address.
  2324. //
  2325. // Arguments
  2326. //
  2327. // VA - Supplies a virtual address.
  2328. //
  2329. // Return Value:
  2330. //
  2331. // TRUE if the address is in the system cache, FALSE if not.
  2332. //
  2333. //--
  2334. #define MI_IS_SYSTEM_CACHE_ADDRESS(VA) \
  2335. (((PVOID)(VA) >= (PVOID)MmSystemCacheStart && \
  2336. (PVOID)(VA) <= (PVOID)MmSystemCacheEnd))
  2337. //++
  2338. //VOID
  2339. //MI_BARRIER_SYNCHRONIZE (
  2340. // IN ULONG TimeStamp
  2341. // );
  2342. //
  2343. // Routine Description:
  2344. //
  2345. // MI_BARRIER_SYNCHRONIZE compares the argument timestamp against the
  2346. // current IPI barrier sequence stamp. When equal, all processors will
  2347. // issue memory barriers to ensure that newly created pages remain coherent.
  2348. //
  2349. // When a page is put in the zeroed or free page list the current
  2350. // barrier sequence stamp is read (interlocked - this is necessary
  2351. // to get the correct value - memory barriers won't do the trick)
  2352. // and stored in the pfn entry for the page. The current barrier
  2353. // sequence stamp is maintained by the IPI send logic and is
  2354. // incremented (interlocked) when the target set of an IPI send
  2355. // includes all processors, but the one doing the send. When a page
  2356. // is needed its sequence number is compared against the current
  2357. // barrier sequence number. If it is equal, then the contents of
  2358. // the page may not be coherent on all processors, and an IPI must
  2359. // be sent to all processors to ensure a memory barrier is
  2360. // executed (generic call can be used for this). Sending the IPI
  2361. // automatically updates the barrier sequence number. The compare
  2362. // is for equality as this is the only value that requires the IPI
  2363. // (i.e., the sequence number wraps, values in both directions are
  2364. // older). When a page is removed in this fashion and either found
  2365. // to be coherent or made coherent, it cannot be modified between
  2366. // that time and writing the PTE. If the page is modified between
  2367. // these times, then an IPI must be sent.
  2368. //
  2369. // Arguments
  2370. //
  2371. // TimeStamp - Supplies the timestamp at the time when the page was zeroed.
  2372. //
  2373. // Return Value:
  2374. //
  2375. // None.
  2376. //
  2377. //--
  2378. #if defined(NT_UP)
  2379. #define MI_BARRIER_SYNCHRONIZE(TimeStamp) \
  2380. __MB();
  2381. #else
  2382. #define MI_BARRIER_SYNCHRONIZE(TimeStamp) \
  2383. if ((ULONG)TimeStamp == KeReadMbTimeStamp()) { \
  2384. KeSynchronizeMemoryAccess(); \
  2385. }
  2386. #endif
  2387. //++
  2388. //VOID
  2389. //MI_BARRIER_STAMP_ZEROED_PAGE (
  2390. // IN PULONG PointerTimeStamp
  2391. // );
  2392. //
  2393. // Routine Description:
  2394. //
  2395. // MI_BARRIER_STAMP_ZEROED_PAGE issues an interlocked read to get the
  2396. // current IPI barrier sequence stamp. This is called AFTER a page is
  2397. // zeroed.
  2398. //
  2399. // Arguments
  2400. //
  2401. // PointerTimeStamp - Supplies a timestamp pointer to fill with the
  2402. // current IPI barrier sequence stamp.
  2403. //
  2404. // Return Value:
  2405. //
  2406. // None.
  2407. //
  2408. //--
  2409. #if defined(NT_UP)
  2410. #define MI_BARRIER_STAMP_ZEROED_PAGE(PointerTimeStamp) NOTHING
  2411. #else
  2412. #define MI_BARRIER_SUPPORTED 1
  2413. #define MI_BARRIER_STAMP_ZEROED_PAGE(PointerTimeStamp) (*(PULONG)PointerTimeStamp = KeReadMbTimeStamp())
  2414. #endif
  2415. //++
  2416. //VOID
  2417. //MI_FLUSH_SINGLE_SESSION_TB (
  2418. // IN PVOID Virtual,
  2419. // IN ULONG Invalid,
  2420. // IN LOGICAL AllProcessors,
  2421. // IN PMMPTE PtePointer,
  2422. // IN MMPTE PteValue,
  2423. // IN MMPTE PreviousPte
  2424. // );
  2425. //
  2426. // Routine Description:
  2427. //
  2428. // MI_FLUSH_SINGLE_SESSION_TB flushes the requested single address
  2429. // translation from the TB.
  2430. //
  2431. // Since Alpha supports ASNs and session space doesn't have one, the entire
  2432. // TB needs to be flushed.
  2433. //
  2434. // Arguments
  2435. //
  2436. // Virtual - Supplies the virtual address to invalidate.
  2437. //
  2438. // Invalid - TRUE if invalidating.
  2439. //
  2440. // AllProcessors - TRUE if all processors need to be IPI'd.
  2441. //
  2442. // PtePointer - Supplies the PTE to invalidate.
  2443. //
  2444. // PteValue - Supplies the new PTE value.
  2445. //
  2446. // PreviousPte - The previous PTE value is returned here.
  2447. //
  2448. // Return Value:
  2449. //
  2450. // None.
  2451. //
  2452. //--
  2453. #define MI_FLUSH_SINGLE_SESSION_TB(Virtual, Invalid, AllProcessors, PtePointer, PteValue, PreviousPte) \
  2454. PreviousPte.u.Flush = *PtePointer; \
  2455. *PtePointer = PteValue; \
  2456. KeFlushEntireTb (TRUE, TRUE);
  2457. //++
  2458. //VOID
  2459. //MI_FLUSH_ENTIRE_SESSION_TB (
  2460. // IN ULONG Invalid,
  2461. // IN LOGICAL AllProcessors
  2462. // );
  2463. //
  2464. // Routine Description:
  2465. //
  2466. // MI_FLUSH_ENTIRE_SESSION_TB flushes the entire TB on Alphas since
  2467. // the Alpha supports ASNs.
  2468. //
  2469. // Arguments
  2470. //
  2471. // Invalid - TRUE if invalidating.
  2472. //
  2473. // AllProcessors - TRUE if all processors need to be IPI'd.
  2474. //
  2475. // Return Value:
  2476. //
  2477. // None.
  2478. //
  2479. #define MI_FLUSH_ENTIRE_SESSION_TB(Invalid, AllProcessors) \
  2480. KeFlushEntireTb (Invalid, AllProcessors);