Skip to content

Commit 14f8621

Browse files
author
Sir Richard
committed
[NTOS]: Add MiRemoveZeroPageSafe helper function, when a zero page is required, but the inline zeroing of MiRemoveZeroPage is not. This function will only try grabbing a zero page if one exists, otherwise a free page will be grabbed and zeroed with custom code of the caller's choosing.
[NTOS]: Add concept of process color and system color. Compute correct color to use whenever requesting a page. [NTOS]: Uncondtionally enable the color code when inserting/removing pages. For now, when requesting a page, colors are still ignored, and the global PFN lists are scanned instead. If there are no regressions, we are one patch away from that. svn path=/trunk/; revision=48927
1 parent 71e8fc8 commit 14f8621

File tree

7 files changed

+133
-65
lines changed

7 files changed

+133
-65
lines changed

reactos/ntoskrnl/mm/ARM3/miarm.h

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,13 @@ extern const ULONG MmProtectToPteMask[32];
218218
//
219219
#define MM_NOIRQL (KIRQL)0xFFFFFFFF
220220

221+
//
222+
// Returns the color of a page
223+
//
224+
#define MI_GET_PAGE_COLOR(x) ((x) & MmSecondaryColorMask)
225+
#define MI_GET_NEXT_COLOR(x) (MI_GET_PAGE_COLOR(++MmSystemPageColor))
226+
#define MI_GET_NEXT_PROCESS_COLOR(x) (MI_GET_PAGE_COLOR(++(x)->NextPageColor))
227+
221228
//
222229
// FIXFIX: These should go in ex.h after the pool merge
223230
//
@@ -455,9 +462,8 @@ extern PMMPTE MmSharedUserDataPte;
455462
extern LIST_ENTRY MmProcessList;
456463
extern BOOLEAN MmZeroingPageThreadActive;
457464
extern KEVENT MmZeroingPageEvent;
458-
459-
#define MI_PFN_TO_PFNENTRY(x) (&MmPfnDatabase[1][x])
460-
#define MI_PFNENTRY_TO_PFN(x) (x - MmPfnDatabase[1])
465+
extern ULONG MmSystemPageColor;
466+
extern ULONG MmProcessColorSeed;
461467

462468
//
463469
// Figures out the hardware bits for a PTE
@@ -1093,4 +1099,19 @@ MiGetNextNode(
10931099
IN PMMADDRESS_NODE Node
10941100
);
10951101

1102+
//
1103+
// MiRemoveZeroPage will use inline code to zero out the page manually if only
1104+
// free pages are available. In some scenarios, we don't/can't run that piece of
1105+
// code and would rather only have a real zero page. If we can't have a zero page,
1106+
// then we'd like to have our own code to grab a free page and zero it out, by
1107+
// using MiRemoveAnyPage. This macro implements this.
1108+
//
1109+
PFN_NUMBER
1110+
FORCEINLINE
1111+
MiRemoveZeroPageSafe(IN ULONG Color)
1112+
{
1113+
if (MmFreePagesByColor[ZeroedPageList][Color].Flink != LIST_HEAD) return MiRemoveZeroPage(Color);
1114+
return 0;
1115+
}
1116+
10961117
/* EOF */

reactos/ntoskrnl/mm/ARM3/pagfault.c

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -179,9 +179,10 @@ MiResolveDemandZeroFault(IN PVOID Address,
179179
IN PEPROCESS Process,
180180
IN KIRQL OldIrql)
181181
{
182-
PFN_NUMBER PageFrameNumber;
182+
PFN_NUMBER PageFrameNumber = 0;
183183
MMPTE TempPte;
184184
BOOLEAN NeedZero = FALSE;
185+
ULONG Color;
185186
DPRINT("ARM3 Demand Zero Page Fault Handler for address: %p in process: %p\n",
186187
Address,
187188
Process);
@@ -196,19 +197,39 @@ MiResolveDemandZeroFault(IN PVOID Address,
196197
/* No forking yet */
197198
ASSERT(Process->ForkInProgress == NULL);
198199

200+
/* Get process color */
201+
Color = MI_GET_NEXT_PROCESS_COLOR(Process);
202+
199203
/* We'll need a zero page */
200204
NeedZero = TRUE;
201205
}
206+
else
207+
{
208+
/* Get the next system page color */
209+
Color = MI_GET_NEXT_COLOR();
210+
}
202211

203212
//
204213
// Lock the PFN database
205214
//
206215
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
207216
ASSERT(PointerPte->u.Hard.Valid == 0);
208217

209-
/* Get a page */
210-
PageFrameNumber = MiRemoveAnyPage(0);
211-
DPRINT("New pool page: %lx\n", PageFrameNumber);
218+
/* Do we need a zero page? */
219+
if (NeedZero)
220+
{
221+
/* Try to get one, if we couldn't grab a free page and zero it */
222+
PageFrameNumber = MiRemoveZeroPageSafe(Color);
223+
if (PageFrameNumber) NeedZero = FALSE;
224+
}
225+
226+
/* Did we get a page? */
227+
if (!PageFrameNumber)
228+
{
229+
/* We either failed to find a zero page, or this is a system request */
230+
PageFrameNumber = MiRemoveAnyPage(Color);
231+
DPRINT("New pool page: %lx\n", PageFrameNumber);
232+
}
212233

213234
/* Initialize it */
214235
MiInitializePfn(PageFrameNumber, PointerPte, TRUE);
@@ -463,6 +484,7 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
463484
ULONG ProtectionCode;
464485
PMMVAD Vad;
465486
PFN_NUMBER PageFrameIndex;
487+
ULONG Color;
466488
DPRINT("ARM3 FAULT AT: %p\n", Address);
467489

468490
//
@@ -756,19 +778,25 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
756778

757779
/* Lock the PFN database since we're going to grab a page */
758780
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
781+
782+
/* Try to get a zero page */
783+
Color = MI_GET_NEXT_PROCESS_COLOR(CurrentProcess);
784+
PageFrameIndex = MiRemoveZeroPageSafe(Color);
785+
if (!PageFrameIndex)
786+
{
787+
/* Grab a page out of there. Later we should grab a colored zero page */
788+
PageFrameIndex = MiRemoveAnyPage(Color);
789+
ASSERT(PageFrameIndex);
759790

760-
/* Grab a page out of there. Later we should grab a colored zero page */
761-
PageFrameIndex = MiRemoveAnyPage(0);
762-
ASSERT(PageFrameIndex);
791+
/* Release the lock since we need to do some zeroing */
792+
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
763793

764-
/* Release the lock since we need to do some zeroing */
765-
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
794+
/* Zero out the page, since it's for user-mode */
795+
MiZeroPfn(PageFrameIndex);
766796

767-
/* Zero out the page, since it's for user-mode */
768-
MiZeroPfn(PageFrameIndex);
769-
770-
/* Grab the lock again so we can initialize the PFN entry */
771-
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
797+
/* Grab the lock again so we can initialize the PFN entry */
798+
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
799+
}
772800

773801
/* Initialize the PFN entry now */
774802
MiInitializePfn(PageFrameIndex, PointerPte, 1);

reactos/ntoskrnl/mm/ARM3/pfnlist.c

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,11 @@ do { \
3030
#define ASSERT_LIST_INVARIANT(x)
3131
#endif
3232

33-
#define ARM3_COLORS 1
34-
3533
/* GLOBALS ********************************************************************/
3634

3735
BOOLEAN MmDynamicPfn;
3836
BOOLEAN MmMirroring;
37+
ULONG MmSystemPageColor;
3938

4039
MMPFNLIST MmZeroedPageListHead = {0, ZeroedPageList, LIST_HEAD, LIST_HEAD};
4140
MMPFNLIST MmFreePageListHead = {0, FreePageList, LIST_HEAD, LIST_HEAD};
@@ -80,11 +79,9 @@ MiUnlinkFreeOrZeroedPage(IN PMMPFN Entry)
8079
PFN_NUMBER OldFlink, OldBlink;
8180
PMMPFNLIST ListHead;
8281
MMLISTS ListName;
83-
#ifdef ARM3_COLORS
8482
ULONG Color;
8583
PMMCOLOR_TABLES ColorTable;
8684
PMMPFN Pfn1;
87-
#endif
8885

8986
/* Make sure the PFN lock is held */
9087
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
@@ -131,7 +128,7 @@ MiUnlinkFreeOrZeroedPage(IN PMMPFN Entry)
131128
/* Set the list head's backlink instead */
132129
ListHead->Flink = OldFlink;
133130
}
134-
#ifdef ARM3_COLORS
131+
135132
/* Get the page color */
136133
OldBlink = MiGetPfnEntryIndex(Entry);
137134
Color = OldBlink & MmSecondaryColorMask;
@@ -185,7 +182,7 @@ MiUnlinkFreeOrZeroedPage(IN PMMPFN Entry)
185182

186183
/* ReactOS Hack */
187184
Entry->OriginalPte.u.Long = 0;
188-
#endif
185+
189186
/* We are not on a list anymore */
190187
Entry->u1.Flink = Entry->u2.Blink = 0;
191188
ASSERT_LIST_INVARIANT(ListHead);
@@ -219,9 +216,8 @@ MiRemovePageByColor(IN PFN_NUMBER PageIndex,
219216
MMLISTS ListName;
220217
PFN_NUMBER OldFlink, OldBlink;
221218
ULONG OldColor, OldCache;
222-
#ifdef ARM3_COLORS
223219
PMMCOLOR_TABLES ColorTable;
224-
#endif
220+
225221
/* Make sure PFN lock is held */
226222
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
227223
ASSERT(Color < MmSecondaryColors);
@@ -280,7 +276,7 @@ MiRemovePageByColor(IN PFN_NUMBER PageIndex,
280276
Pfn1->u3.e2.ShortFlags = 0;
281277
Pfn1->u3.e1.PageColor = OldColor;
282278
Pfn1->u3.e1.CacheAttribute = OldCache;
283-
#ifdef ARM3_COLORS
279+
284280
/* Get the first page on the color list */
285281
ASSERT(Color < MmSecondaryColors);
286282
ColorTable = &MmFreePagesByColor[ListName][Color];
@@ -306,7 +302,7 @@ MiRemovePageByColor(IN PFN_NUMBER PageIndex,
306302

307303
/* ReactOS Hack */
308304
Pfn1->OriginalPte.u.Long = 0;
309-
#endif
305+
310306
/* See if we hit any thresholds */
311307
if (MmAvailablePages == MmHighMemoryThreshold)
312308
{
@@ -340,9 +336,8 @@ MiRemoveAnyPage(IN ULONG Color)
340336
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
341337
ASSERT(MmAvailablePages != 0);
342338
ASSERT(Color < MmSecondaryColors);
343-
339+
#if 0
344340
/* Check the colored free list */
345-
#if 0 // Enable when using ARM3 database */
346341
PageIndex = MmFreePagesByColor[FreePageList][Color].Flink;
347342
if (PageIndex == LIST_HEAD)
348343
{
@@ -368,11 +363,10 @@ MiRemoveAnyPage(IN ULONG Color)
368363
ASSERT(MmZeroedPageListHead.Total == 0);
369364
}
370365
}
371-
#if 0 // Enable when using ARM3 database */
366+
#if 0
372367
}
373368
}
374369
#endif
375-
376370
/* Remove the page from its list */
377371
PageIndex = MiRemovePageByColor(PageIndex, Color);
378372

@@ -403,7 +397,7 @@ MiRemoveZeroPage(IN ULONG Color)
403397
ASSERT(Color < MmSecondaryColors);
404398

405399
/* Check the colored zero list */
406-
#if 0 // Enable when using ARM3 database */
400+
#if 0
407401
PageIndex = MmFreePagesByColor[ZeroedPageList][Color].Flink;
408402
if (PageIndex == LIST_HEAD)
409403
{
@@ -414,9 +408,10 @@ MiRemoveZeroPage(IN ULONG Color)
414408
Color = PageIndex & MmSecondaryColorMask;
415409
if (PageIndex == LIST_HEAD)
416410
{
411+
/* This means there's no zero pages, we have to look for free ones */
417412
ASSERT(MmZeroedPageListHead.Total == 0);
418413
Zero = TRUE;
419-
#if 0 // Enable when using ARM3 database */
414+
#if 0
420415
/* Check the colored free list */
421416
PageIndex = MmFreePagesByColor[ZeroedPageList][Color].Flink;
422417
if (PageIndex == LIST_HEAD)
@@ -432,13 +427,14 @@ MiRemoveZeroPage(IN ULONG Color)
432427
/* FIXME: Should check the standby list */
433428
ASSERT(MmZeroedPageListHead.Total == 0);
434429
}
435-
#if 0 // Enable when using ARM3 database */
430+
#if 0
436431
}
437432
#endif
438433
}
439-
#if 0 // Enable when using ARM3 database */
434+
#if 0
440435
}
441436
#endif
437+
442438
/* Sanity checks */
443439
Pfn1 = MiGetPfnEntry(PageIndex);
444440
ASSERT((Pfn1->u3.e1.PageLocation == FreePageList) ||
@@ -468,11 +464,10 @@ MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex)
468464
PMMPFNLIST ListHead;
469465
PFN_NUMBER LastPage;
470466
PMMPFN Pfn1;
471-
#ifdef ARM3_COLORS
472467
ULONG Color;
473468
PMMPFN Blink;
474469
PMMCOLOR_TABLES ColorTable;
475-
#endif
470+
476471
/* Make sure the page index is valid */
477472
ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
478473
ASSERT((PageFrameIndex != 0) &&
@@ -537,7 +532,7 @@ MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex)
537532
/* Otherwise check if we reached the high threshold and signal the event */
538533
KeSetEvent(MiHighMemoryEvent, 0, FALSE);
539534
}
540-
#ifdef ARM3_COLORS
535+
541536
/* Get the page color */
542537
Color = PageFrameIndex & MmSecondaryColorMask;
543538

@@ -571,7 +566,7 @@ MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex)
571566

572567
/* And increase the count in the colored list */
573568
ColorTable->Count++;
574-
#endif
569+
575570
/* Notify zero page thread if enough pages are on the free list now */
576571
if ((ListHead->Total >= 8) && !(MmZeroingPageThreadActive))
577572
{
@@ -590,10 +585,9 @@ MiInsertPageInList(IN PMMPFNLIST ListHead,
590585
PFN_NUMBER Flink;
591586
PMMPFN Pfn1, Pfn2;
592587
MMLISTS ListName;
593-
#ifdef ARM3_COLORS
594588
PMMCOLOR_TABLES ColorHead;
595589
ULONG Color;
596-
#endif
590+
597591
/* For free pages, use MiInsertPageInFreeList */
598592
ASSERT(ListHead != &MmFreePageListHead);
599593

@@ -657,7 +651,7 @@ MiInsertPageInList(IN PMMPFNLIST ListHead,
657651
KeSetEvent(MiHighMemoryEvent, 0, FALSE);
658652
}
659653

660-
#ifdef ARM3_COLORS
654+
/* Sanity checks */
661655
ASSERT(ListName == ZeroedPageList);
662656
ASSERT(Pfn1->u4.InPageError == 0);
663657

@@ -695,7 +689,6 @@ MiInsertPageInList(IN PMMPFNLIST ListHead,
695689

696690
/* One more paged on the colored list */
697691
ColorHead->Count++;
698-
#endif
699692
}
700693

701694
VOID
@@ -783,7 +776,7 @@ MiAllocatePfn(IN PMMPTE PointerPte,
783776
/* Grab a page */
784777
ASSERT_LIST_INVARIANT(&MmFreePageListHead);
785778
ASSERT_LIST_INVARIANT(&MmZeroedPageListHead);
786-
PageFrameIndex = MiRemoveAnyPage(0);
779+
PageFrameIndex = MiRemoveAnyPage(MI_GET_NEXT_COLOR());
787780

788781
/* Write the software PTE */
789782
MI_WRITE_INVALID_PTE(PointerPte, TempPte);

reactos/ntoskrnl/mm/ARM3/pool.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ MiAllocatePoolPages(IN POOL_TYPE PoolType,
473473
ASSERT(PointerPte->u.Hard.Valid == 0);
474474

475475
/* Request a page */
476-
PageFrameNumber = MiRemoveAnyPage(0);
476+
PageFrameNumber = MiRemoveAnyPage(MI_GET_NEXT_COLOR());
477477
TempPte.u.Hard.PageFrameNumber = PageFrameNumber;
478478

479479
#if (_MI_PAGING_LEVELS >= 3)
@@ -768,7 +768,7 @@ MiAllocatePoolPages(IN POOL_TYPE PoolType,
768768
do
769769
{
770770
/* Allocate a page */
771-
PageFrameNumber = MiRemoveAnyPage(0);
771+
PageFrameNumber = MiRemoveAnyPage(MI_GET_NEXT_COLOR());
772772

773773
/* Get the PFN entry for it and fill it out */
774774
Pfn1 = MiGetPfnEntry(PageFrameNumber);

0 commit comments

Comments
 (0)