2 * Copyright (C) 1998-2005 ReactOS Team (and the authors from the programmers section)
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 * PROJECT: ReactOS kernel
20 * FILE: ntoskrnl/mm/section.c
21 * PURPOSE: Section object page tables
26 /* INCLUDES *****************************************************************/
33 #define DPRINTC DPRINT
35 /* TYPES *********************************************************************/
37 extern KSPIN_LOCK MiSectionPageTableLock
;
42 MiSectionPageTableAllocate(PRTL_GENERIC_TABLE Table
, CLONG Bytes
)
45 Result
= ExAllocatePoolWithTag(NonPagedPool
, Bytes
, 'MmPt');
46 DPRINT("MiSectionPageTableAllocate(%d) => %p\n", Bytes
, Result
);
53 MiSectionPageTableFree(PRTL_GENERIC_TABLE Table
, PVOID Data
)
55 DPRINT("MiSectionPageTableFree(%p)\n", Data
);
56 ExFreePoolWithTag(Data
, 'MmPt');
60 RTL_GENERIC_COMPARE_RESULTS
62 MiSectionPageTableCompare(PRTL_GENERIC_TABLE Table
, PVOID PtrA
, PVOID PtrB
)
64 PLARGE_INTEGER A
= PtrA
, B
= PtrB
;
65 BOOLEAN Result
= (A
->QuadPart
< B
->QuadPart
) ? GenericLessThan
:
66 (A
->QuadPart
== B
->QuadPart
) ? GenericEqual
: GenericGreaterThan
;
69 ("Compare: %08x%08x vs %08x%08x => %s\n",
70 A
->u
.HighPart
, A
->u
.LowPart
,
71 B
->u
.HighPart
, B
->u
.LowPart
,
72 Result
== GenericLessThan
? "GenericLessThan" :
73 Result
== GenericGreaterThan
? "GenericGreaterThan" :
80 PCACHE_SECTION_PAGE_TABLE
83 (PRTL_GENERIC_TABLE Table
,
84 PLARGE_INTEGER FileOffset
)
86 LARGE_INTEGER SearchFileOffset
;
87 PCACHE_SECTION_PAGE_TABLE PageTable
;
88 SearchFileOffset
.QuadPart
= ROUND_DOWN(FileOffset
->QuadPart
, ENTRIES_PER_ELEMENT
* PAGE_SIZE
);
89 PageTable
= RtlLookupElementGenericTable(Table
, &SearchFileOffset
);
91 ("MiSectionPageTableGet(%08x,%08x%08x)\n",
99 PCACHE_SECTION_PAGE_TABLE
101 MiSectionPageTableGetOrAllocate
102 (PRTL_GENERIC_TABLE Table
,
103 PLARGE_INTEGER FileOffset
)
105 LARGE_INTEGER SearchFileOffset
;
106 PCACHE_SECTION_PAGE_TABLE PageTableSlice
=
107 MiSectionPageTableGet(Table
, FileOffset
);
110 CACHE_SECTION_PAGE_TABLE SectionZeroPageTable
= { };
111 SearchFileOffset
.QuadPart
= ROUND_DOWN(FileOffset
->QuadPart
, ENTRIES_PER_ELEMENT
* PAGE_SIZE
);
112 SectionZeroPageTable
.FileOffset
= SearchFileOffset
;
113 SectionZeroPageTable
.Refcount
= 1;
114 PageTableSlice
= RtlInsertElementGenericTable
115 (Table
, &SectionZeroPageTable
, sizeof(SectionZeroPageTable
), NULL
);
117 ("Allocate page table %x (%08x%08x)\n",
119 PageTableSlice
->FileOffset
.u
.HighPart
,
120 PageTableSlice
->FileOffset
.u
.LowPart
);
121 if (!PageTableSlice
) return NULL
;
123 return PageTableSlice
;
128 MiInitializeSectionPageTable(PMM_CACHE_SECTION_SEGMENT Segment
)
130 RtlInitializeGenericTable
131 (&Segment
->PageTable
,
132 MiSectionPageTableCompare
,
133 MiSectionPageTableAllocate
,
134 MiSectionPageTableFree
,
136 DPRINT("MiInitializeSectionPageTable(%p)\n", &Segment
->PageTable
);
141 _MiSetPageEntryCacheSectionSegment
142 (PMM_CACHE_SECTION_SEGMENT Segment
,
143 PLARGE_INTEGER Offset
,
148 ULONG PageIndex
, OldEntry
;
149 PCACHE_SECTION_PAGE_TABLE PageTable
;
151 MiSectionPageTableGetOrAllocate(&Segment
->PageTable
, Offset
);
152 if (!PageTable
) return STATUS_NO_MEMORY
;
153 ASSERT(MiSectionPageTableGet(&Segment
->PageTable
, Offset
));
154 PageTable
->Segment
= Segment
;
156 (Offset
->QuadPart
- PageTable
->FileOffset
.QuadPart
) / PAGE_SIZE
;
157 OldEntry
= PageTable
->PageEntries
[PageIndex
];
158 if (OldEntry
&& !IS_SWAP_FROM_SSE(OldEntry
)) {
159 MmDeleteSectionAssociation(PFN_FROM_SSE(OldEntry
));
161 if (Entry
&& !IS_SWAP_FROM_SSE(Entry
)) {
162 MmSetSectionAssociation(PFN_FROM_SSE(Entry
), Segment
, Offset
);
164 PageTable
->PageEntries
[PageIndex
] = Entry
;
166 ("MiSetPageEntrySectionSegment(%p,%08x%08x,%x) %s:%d\n",
167 Segment
, Offset
->u
.HighPart
, Offset
->u
.LowPart
, Entry
, file
, line
);
168 return STATUS_SUCCESS
;
173 _MiGetPageEntryCacheSectionSegment
174 (PMM_CACHE_SECTION_SEGMENT Segment
,
175 PLARGE_INTEGER Offset
,
179 LARGE_INTEGER FileOffset
;
180 ULONG PageIndex
, Result
;
181 PCACHE_SECTION_PAGE_TABLE PageTable
;
183 FileOffset
.QuadPart
=
184 ROUND_DOWN(Offset
->QuadPart
, ENTRIES_PER_ELEMENT
* PAGE_SIZE
);
185 PageTable
= MiSectionPageTableGet(&Segment
->PageTable
, &FileOffset
);
186 if (!PageTable
) return 0;
188 (Offset
->QuadPart
- PageTable
->FileOffset
.QuadPart
) / PAGE_SIZE
;
189 Result
= PageTable
->PageEntries
[PageIndex
];
192 ("MiGetPageEntrySectionSegment(%p,%08x%08x) => %x %s:%d\n",
194 FileOffset
.u
.HighPart
,
195 FileOffset
.u
.LowPart
+ PageIndex
* PAGE_SIZE
,
204 MiFreePageTablesSectionSegment
205 (PMM_CACHE_SECTION_SEGMENT Segment
, FREE_SECTION_PAGE_FUN FreePage
)
207 PCACHE_SECTION_PAGE_TABLE Element
;
208 DPRINT("MiFreePageTablesSectionSegment(%p)\n", &Segment
->PageTable
);
209 while ((Element
= RtlGetElementGenericTable(&Segment
->PageTable
, 0))) {
211 ("Delete table for %x -> %08x%08x\n",
213 Element
->FileOffset
.u
.HighPart
,
214 Element
->FileOffset
.u
.LowPart
);
218 for (i
= 0; i
< ENTRIES_PER_ELEMENT
; i
++)
221 LARGE_INTEGER Offset
;
222 Offset
.QuadPart
= Element
->FileOffset
.QuadPart
+ i
* PAGE_SIZE
;
223 Entry
= Element
->PageEntries
[i
];
224 if (Entry
&& !IS_SWAP_FROM_SSE(Entry
))
226 DPRINTC("Freeing page %x:%x @ %x\n", Segment
, Entry
, Offset
.LowPart
);
227 FreePage(Segment
, &Offset
);
231 DPRINT("Remove memory\n");
232 RtlDeleteElementGenericTable(&Segment
->PageTable
, Element
);
237 PMM_CACHE_SECTION_SEGMENT
239 MmGetSectionAssociation(PFN_NUMBER Page
, PLARGE_INTEGER Offset
)
242 PMM_CACHE_SECTION_SEGMENT Segment
= NULL
;
243 PCACHE_SECTION_PAGE_TABLE PageTable
;
245 PageTable
= (PCACHE_SECTION_PAGE_TABLE
)MmGetSegmentRmap(Page
, &RawOffset
);
248 Segment
= PageTable
->Segment
;
249 Offset
->QuadPart
= PageTable
->FileOffset
.QuadPart
+ (RawOffset
<< PAGE_SHIFT
);
257 MmSetSectionAssociation(PFN_NUMBER Page
, PMM_CACHE_SECTION_SEGMENT Segment
, PLARGE_INTEGER Offset
)
259 PCACHE_SECTION_PAGE_TABLE PageTable
;
261 PageTable
= MiSectionPageTableGet(&Segment
->PageTable
, Offset
);
263 ActualOffset
= (ULONG
)(Offset
->QuadPart
- PageTable
->FileOffset
.QuadPart
);
264 MmInsertRmap(Page
, (PEPROCESS
)PageTable
, (PVOID
)(RMAP_SEGMENT_MASK
| (ActualOffset
>> PAGE_SHIFT
)));
265 return STATUS_SUCCESS
;