Skip to content

Commit 69bf140

Browse files
authored
[NTOS:MM][NTOS:CC] Rewrite some cache memory management functions (reactos#7510)
Use section object pointer with byte offset instead of using base address. This simplifies the Mm functions themselves and also the code in Cc that calls them. Also add minor fixes for MmFlushSegment and MmPurgeSegment.
1 parent 541cb0d commit 69bf140

File tree

5 files changed

+138
-24
lines changed

5 files changed

+138
-24
lines changed

ntoskrnl/cc/copy.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -653,7 +653,9 @@ CcCopyWrite (
653653
CurrentOffset += VacbLength;
654654

655655
/* Tell Mm */
656-
Status = MmMakePagesDirty(NULL, Add2Ptr(Vacb->BaseAddress, VacbOffset), VacbLength);
656+
Status = MmMakeSegmentDirty(FileObject->SectionObjectPointer,
657+
Vacb->FileOffset.QuadPart + VacbOffset,
658+
VacbLength);
657659
if (!NT_SUCCESS(Status))
658660
ExRaiseStatus(Status);
659661
}
@@ -913,7 +915,9 @@ CcZeroData (
913915
Length -= VacbLength;
914916

915917
/* Tell Mm */
916-
Status = MmMakePagesDirty(NULL, Add2Ptr(Vacb->BaseAddress, VacbOffset), VacbLength);
918+
Status = MmMakeSegmentDirty(FileObject->SectionObjectPointer,
919+
Vacb->FileOffset.QuadPart + VacbOffset,
920+
VacbLength);
917921
if (!NT_SUCCESS(Status))
918922
ExRaiseStatus(Status);
919923
}

ntoskrnl/cc/pin.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -551,17 +551,18 @@ CcSetDirtyPinnedData (
551551
IN PLARGE_INTEGER Lsn)
552552
{
553553
PINTERNAL_BCB iBcb = CONTAINING_RECORD(Bcb, INTERNAL_BCB, PFCB);
554+
PROS_VACB Vacb = iBcb->Vacb;
554555

555556
CCTRACE(CC_API_DEBUG, "Bcb=%p Lsn=%p\n", Bcb, Lsn);
556557

557558
/* Tell Mm */
558-
MmMakePagesDirty(NULL,
559-
Add2Ptr(iBcb->Vacb->BaseAddress, iBcb->PFCB.MappedFileOffset.QuadPart - iBcb->Vacb->FileOffset.QuadPart),
560-
iBcb->PFCB.MappedLength);
559+
MmMakeSegmentDirty(Vacb->SharedCacheMap->FileObject->SectionObjectPointer,
560+
iBcb->PFCB.MappedFileOffset.QuadPart,
561+
iBcb->PFCB.MappedLength);
561562

562-
if (!iBcb->Vacb->Dirty)
563+
if (!Vacb->Dirty)
563564
{
564-
CcRosMarkDirtyVacb(iBcb->Vacb);
565+
CcRosMarkDirtyVacb(Vacb);
565566
}
566567
}
567568

ntoskrnl/cc/view.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -936,22 +936,22 @@ CcRosEnsureVacbResident(
936936
_In_ ULONG Length
937937
)
938938
{
939-
PVOID BaseAddress;
939+
PROS_SHARED_CACHE_MAP SharedCacheMap = Vacb->SharedCacheMap;
940940

941941
ASSERT((Offset + Length) <= VACB_MAPPING_GRANULARITY);
942942

943943
#if 0
944-
if ((Vacb->FileOffset.QuadPart + Offset) > Vacb->SharedCacheMap->SectionSize.QuadPart)
944+
if ((Vacb->FileOffset.QuadPart + Offset) > SharedCacheMap->SectionSize.QuadPart)
945945
{
946946
DPRINT1("Vacb read beyond the file size!\n");
947947
return FALSE;
948948
}
949949
#endif
950950

951-
BaseAddress = (PVOID)((ULONG_PTR)Vacb->BaseAddress + Offset);
952-
953951
/* Check if the pages are resident */
954-
if (!MmArePagesResident(NULL, BaseAddress, Length))
952+
if (!MmIsDataSectionResident(SharedCacheMap->FileObject->SectionObjectPointer,
953+
Vacb->FileOffset.QuadPart + Offset,
954+
Length))
955955
{
956956
if (!Wait)
957957
{
@@ -960,7 +960,6 @@ CcRosEnsureVacbResident(
960960

961961
if (!NoRead)
962962
{
963-
PROS_SHARED_CACHE_MAP SharedCacheMap = Vacb->SharedCacheMap;
964963
NTSTATUS Status = MmMakeDataSectionResident(SharedCacheMap->FileObject->SectionObjectPointer,
965964
Vacb->FileOffset.QuadPart + Offset,
966965
Length,

ntoskrnl/include/internal/mm.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1502,16 +1502,16 @@ MmMapViewInSystemSpaceEx(
15021502

15031503
BOOLEAN
15041504
NTAPI
1505-
MmArePagesResident(
1506-
_In_ PEPROCESS Process,
1507-
_In_ PVOID BaseAddress,
1505+
MmIsDataSectionResident(
1506+
_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer,
1507+
_In_ LONGLONG Offset,
15081508
_In_ ULONG Length);
15091509

15101510
NTSTATUS
15111511
NTAPI
1512-
MmMakePagesDirty(
1513-
_In_ PEPROCESS Process,
1514-
_In_ PVOID Address,
1512+
MmMakeSegmentDirty(
1513+
_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer,
1514+
_In_ LONGLONG Offset,
15151515
_In_ ULONG Length);
15161516

15171517
NTSTATUS

ntoskrnl/mm/section.c

Lines changed: 115 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4775,10 +4775,13 @@ MmCreateSection (OUT PVOID * Section,
47754775
return Status;
47764776
}
47774777

4778+
/* This function is not used. It is left for future use, when per-process
4779+
* address space is considered. */
4780+
#if 0
47784781
BOOLEAN
47794782
NTAPI
47804783
MmArePagesResident(
4781-
_In_ PEPROCESS Process,
4784+
_In_opt_ PEPROCESS Process,
47824785
_In_ PVOID Address,
47834786
_In_ ULONG Length)
47844787
{
@@ -4826,6 +4829,7 @@ MmArePagesResident(
48264829
MmUnlockAddressSpace(AddressSpace);
48274830
return Ret;
48284831
}
4832+
#endif
48294833

48304834
/* Like CcPurgeCache but for the in-memory segment */
48314835
BOOLEAN
@@ -4859,9 +4863,9 @@ MmPurgeSegment(
48594863
/* We must calculate the length for ourselves */
48604864
/* FIXME: All of this is suboptimal */
48614865
ULONG ElemCount = RtlNumberGenericTableElements(&Segment->PageTable);
4862-
/* No page. Nothing to purge */
48634866
if (!ElemCount)
48644867
{
4868+
/* No page. Nothing to purge */
48654869
MmUnlockSectionSegment(Segment);
48664870
MmDereferenceSegment(Segment);
48674871
return TRUE;
@@ -4871,6 +4875,9 @@ MmPurgeSegment(
48714875
PurgeEnd.QuadPart = PageTable->FileOffset.QuadPart + _countof(PageTable->PageEntries) * PAGE_SIZE;
48724876
}
48734877

4878+
/* Find byte offset of the page to start */
4879+
PurgeStart.QuadPart = PAGE_ROUND_DOWN(PurgeStart.QuadPart);
4880+
48744881
while (PurgeStart.QuadPart < PurgeEnd.QuadPart)
48754882
{
48764883
ULONG_PTR Entry = MmGetPageEntrySectionSegment(Segment, &PurgeStart);
@@ -4920,6 +4927,48 @@ MmPurgeSegment(
49204927
return TRUE;
49214928
}
49224929

4930+
BOOLEAN
4931+
NTAPI
4932+
MmIsDataSectionResident(
4933+
_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer,
4934+
_In_ LONGLONG Offset,
4935+
_In_ ULONG Length)
4936+
{
4937+
PMM_SECTION_SEGMENT Segment;
4938+
LARGE_INTEGER RangeStart, RangeEnd;
4939+
BOOLEAN Ret = TRUE;
4940+
4941+
RangeStart.QuadPart = Offset;
4942+
if (!NT_SUCCESS(RtlLongLongAdd(RangeStart.QuadPart, Length, &RangeEnd.QuadPart)))
4943+
return FALSE;
4944+
4945+
Segment = MiGrabDataSection(SectionObjectPointer);
4946+
if (!Segment)
4947+
return FALSE;
4948+
4949+
/* Find byte offset of the page to start */
4950+
RangeStart.QuadPart = PAGE_ROUND_DOWN(RangeStart.QuadPart);
4951+
4952+
MmLockSectionSegment(Segment);
4953+
4954+
while (RangeStart.QuadPart < RangeEnd.QuadPart)
4955+
{
4956+
ULONG_PTR Entry = MmGetPageEntrySectionSegment(Segment, &RangeStart);
4957+
if ((Entry == 0) || IS_SWAP_FROM_SSE(Entry))
4958+
{
4959+
Ret = FALSE;
4960+
break;
4961+
}
4962+
4963+
RangeStart.QuadPart += PAGE_SIZE;
4964+
}
4965+
4966+
MmUnlockSectionSegment(Segment);
4967+
MmDereferenceSegment(Segment);
4968+
4969+
return Ret;
4970+
}
4971+
49234972
NTSTATUS
49244973
NTAPI
49254974
MmMakeDataSectionResident(
@@ -4940,6 +4989,63 @@ MmMakeDataSectionResident(
49404989
return Status;
49414990
}
49424991

4992+
NTSTATUS
4993+
NTAPI
4994+
MmMakeSegmentDirty(
4995+
_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer,
4996+
_In_ LONGLONG Offset,
4997+
_In_ ULONG Length)
4998+
{
4999+
PMM_SECTION_SEGMENT Segment;
5000+
LARGE_INTEGER RangeStart, RangeEnd;
5001+
NTSTATUS Status;
5002+
5003+
RangeStart.QuadPart = Offset;
5004+
Status = RtlLongLongAdd(RangeStart.QuadPart, Length, &RangeEnd.QuadPart);
5005+
if (!NT_SUCCESS(Status))
5006+
return Status;
5007+
5008+
Segment = MiGrabDataSection(SectionObjectPointer);
5009+
if (!Segment)
5010+
return STATUS_NOT_MAPPED_VIEW;
5011+
5012+
/* Find byte offset of the page to start */
5013+
RangeStart.QuadPart = PAGE_ROUND_DOWN(RangeStart.QuadPart);
5014+
5015+
MmLockSectionSegment(Segment);
5016+
5017+
while (RangeStart.QuadPart < RangeEnd.QuadPart)
5018+
{
5019+
ULONG_PTR Entry = MmGetPageEntrySectionSegment(Segment, &RangeStart);
5020+
5021+
/* Let any pending read proceed */
5022+
while (MM_IS_WAIT_PTE(Entry))
5023+
{
5024+
MmUnlockSectionSegment(Segment);
5025+
KeDelayExecutionThread(KernelMode, FALSE, &TinyTime);
5026+
MmLockSectionSegment(Segment);
5027+
Entry = MmGetPageEntrySectionSegment(Segment, &RangeStart);
5028+
}
5029+
5030+
/* We are called from Cc, this can't be backed by the page files */
5031+
ASSERT(!IS_SWAP_FROM_SSE(Entry));
5032+
5033+
/* If there is no page there, there is nothing to make dirty */
5034+
if (Entry != 0)
5035+
{
5036+
/* Dirtify the entry */
5037+
MmSetPageEntrySectionSegment(Segment, &RangeStart, DIRTY_SSE(Entry));
5038+
}
5039+
5040+
RangeStart.QuadPart += PAGE_SIZE;
5041+
}
5042+
5043+
MmUnlockSectionSegment(Segment);
5044+
MmDereferenceSegment(Segment);
5045+
5046+
return STATUS_SUCCESS;
5047+
}
5048+
49435049
NTSTATUS
49445050
NTAPI
49455051
MmFlushSegment(
@@ -4991,8 +5097,8 @@ MmFlushSegment(
49915097
FlushEnd.QuadPart = PageTable->FileOffset.QuadPart + _countof(PageTable->PageEntries) * PAGE_SIZE;
49925098
}
49935099

4994-
FlushStart.QuadPart >>= PAGE_SHIFT;
4995-
FlushStart.QuadPart <<= PAGE_SHIFT;
5100+
/* Find byte offset of the page to start */
5101+
FlushStart.QuadPart = PAGE_ROUND_DOWN(FlushStart.QuadPart);
49965102

49975103
while (FlushStart.QuadPart < FlushEnd.QuadPart)
49985104
{
@@ -5197,10 +5303,13 @@ MmCheckDirtySegment(
51975303
return FALSE;
51985304
}
51995305

5306+
/* This function is not used. It is left for future use, when per-process
5307+
* address space is considered. */
5308+
#if 0
52005309
NTSTATUS
52015310
NTAPI
52025311
MmMakePagesDirty(
5203-
_In_ PEPROCESS Process,
5312+
_In_opt_ PEPROCESS Process,
52045313
_In_ PVOID Address,
52055314
_In_ ULONG Length)
52065315
{
@@ -5267,6 +5376,7 @@ MmMakePagesDirty(
52675376
MmUnlockAddressSpace(AddressSpace);
52685377
return STATUS_SUCCESS;
52695378
}
5379+
#endif
52705380

52715381
NTSTATUS
52725382
NTAPI

0 commit comments

Comments
 (0)