Skip to content

Commit

Permalink
[NTOS:MM][NTOS:CC] Rewrite some cache memory management functions (re…
Browse files Browse the repository at this point in the history
…actos#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.
  • Loading branch information
TAN-Gaming authored Nov 24, 2024
1 parent 541cb0d commit 69bf140
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 24 deletions.
8 changes: 6 additions & 2 deletions ntoskrnl/cc/copy.c
Original file line number Diff line number Diff line change
Expand Up @@ -653,7 +653,9 @@ CcCopyWrite (
CurrentOffset += VacbLength;

/* Tell Mm */
Status = MmMakePagesDirty(NULL, Add2Ptr(Vacb->BaseAddress, VacbOffset), VacbLength);
Status = MmMakeSegmentDirty(FileObject->SectionObjectPointer,
Vacb->FileOffset.QuadPart + VacbOffset,
VacbLength);
if (!NT_SUCCESS(Status))
ExRaiseStatus(Status);
}
Expand Down Expand Up @@ -913,7 +915,9 @@ CcZeroData (
Length -= VacbLength;

/* Tell Mm */
Status = MmMakePagesDirty(NULL, Add2Ptr(Vacb->BaseAddress, VacbOffset), VacbLength);
Status = MmMakeSegmentDirty(FileObject->SectionObjectPointer,
Vacb->FileOffset.QuadPart + VacbOffset,
VacbLength);
if (!NT_SUCCESS(Status))
ExRaiseStatus(Status);
}
Expand Down
11 changes: 6 additions & 5 deletions ntoskrnl/cc/pin.c
Original file line number Diff line number Diff line change
Expand Up @@ -551,17 +551,18 @@ CcSetDirtyPinnedData (
IN PLARGE_INTEGER Lsn)
{
PINTERNAL_BCB iBcb = CONTAINING_RECORD(Bcb, INTERNAL_BCB, PFCB);
PROS_VACB Vacb = iBcb->Vacb;

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

/* Tell Mm */
MmMakePagesDirty(NULL,
Add2Ptr(iBcb->Vacb->BaseAddress, iBcb->PFCB.MappedFileOffset.QuadPart - iBcb->Vacb->FileOffset.QuadPart),
iBcb->PFCB.MappedLength);
MmMakeSegmentDirty(Vacb->SharedCacheMap->FileObject->SectionObjectPointer,
iBcb->PFCB.MappedFileOffset.QuadPart,
iBcb->PFCB.MappedLength);

if (!iBcb->Vacb->Dirty)
if (!Vacb->Dirty)
{
CcRosMarkDirtyVacb(iBcb->Vacb);
CcRosMarkDirtyVacb(Vacb);
}
}

Expand Down
11 changes: 5 additions & 6 deletions ntoskrnl/cc/view.c
Original file line number Diff line number Diff line change
Expand Up @@ -936,22 +936,22 @@ CcRosEnsureVacbResident(
_In_ ULONG Length
)
{
PVOID BaseAddress;
PROS_SHARED_CACHE_MAP SharedCacheMap = Vacb->SharedCacheMap;

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

#if 0
if ((Vacb->FileOffset.QuadPart + Offset) > Vacb->SharedCacheMap->SectionSize.QuadPart)
if ((Vacb->FileOffset.QuadPart + Offset) > SharedCacheMap->SectionSize.QuadPart)
{
DPRINT1("Vacb read beyond the file size!\n");
return FALSE;
}
#endif

BaseAddress = (PVOID)((ULONG_PTR)Vacb->BaseAddress + Offset);

/* Check if the pages are resident */
if (!MmArePagesResident(NULL, BaseAddress, Length))
if (!MmIsDataSectionResident(SharedCacheMap->FileObject->SectionObjectPointer,
Vacb->FileOffset.QuadPart + Offset,
Length))
{
if (!Wait)
{
Expand All @@ -960,7 +960,6 @@ CcRosEnsureVacbResident(

if (!NoRead)
{
PROS_SHARED_CACHE_MAP SharedCacheMap = Vacb->SharedCacheMap;
NTSTATUS Status = MmMakeDataSectionResident(SharedCacheMap->FileObject->SectionObjectPointer,
Vacb->FileOffset.QuadPart + Offset,
Length,
Expand Down
12 changes: 6 additions & 6 deletions ntoskrnl/include/internal/mm.h
Original file line number Diff line number Diff line change
Expand Up @@ -1502,16 +1502,16 @@ MmMapViewInSystemSpaceEx(

BOOLEAN
NTAPI
MmArePagesResident(
_In_ PEPROCESS Process,
_In_ PVOID BaseAddress,
MmIsDataSectionResident(
_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer,
_In_ LONGLONG Offset,
_In_ ULONG Length);

NTSTATUS
NTAPI
MmMakePagesDirty(
_In_ PEPROCESS Process,
_In_ PVOID Address,
MmMakeSegmentDirty(
_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer,
_In_ LONGLONG Offset,
_In_ ULONG Length);

NTSTATUS
Expand Down
120 changes: 115 additions & 5 deletions ntoskrnl/mm/section.c
Original file line number Diff line number Diff line change
Expand Up @@ -4775,10 +4775,13 @@ MmCreateSection (OUT PVOID * Section,
return Status;
}

/* This function is not used. It is left for future use, when per-process
* address space is considered. */
#if 0
BOOLEAN
NTAPI
MmArePagesResident(
_In_ PEPROCESS Process,
_In_opt_ PEPROCESS Process,
_In_ PVOID Address,
_In_ ULONG Length)
{
Expand Down Expand Up @@ -4826,6 +4829,7 @@ MmArePagesResident(
MmUnlockAddressSpace(AddressSpace);
return Ret;
}
#endif

/* Like CcPurgeCache but for the in-memory segment */
BOOLEAN
Expand Down Expand Up @@ -4859,9 +4863,9 @@ MmPurgeSegment(
/* We must calculate the length for ourselves */
/* FIXME: All of this is suboptimal */
ULONG ElemCount = RtlNumberGenericTableElements(&Segment->PageTable);
/* No page. Nothing to purge */
if (!ElemCount)
{
/* No page. Nothing to purge */
MmUnlockSectionSegment(Segment);
MmDereferenceSegment(Segment);
return TRUE;
Expand All @@ -4871,6 +4875,9 @@ MmPurgeSegment(
PurgeEnd.QuadPart = PageTable->FileOffset.QuadPart + _countof(PageTable->PageEntries) * PAGE_SIZE;
}

/* Find byte offset of the page to start */
PurgeStart.QuadPart = PAGE_ROUND_DOWN(PurgeStart.QuadPart);

while (PurgeStart.QuadPart < PurgeEnd.QuadPart)
{
ULONG_PTR Entry = MmGetPageEntrySectionSegment(Segment, &PurgeStart);
Expand Down Expand Up @@ -4920,6 +4927,48 @@ MmPurgeSegment(
return TRUE;
}

BOOLEAN
NTAPI
MmIsDataSectionResident(
_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer,
_In_ LONGLONG Offset,
_In_ ULONG Length)
{
PMM_SECTION_SEGMENT Segment;
LARGE_INTEGER RangeStart, RangeEnd;
BOOLEAN Ret = TRUE;

RangeStart.QuadPart = Offset;
if (!NT_SUCCESS(RtlLongLongAdd(RangeStart.QuadPart, Length, &RangeEnd.QuadPart)))
return FALSE;

Segment = MiGrabDataSection(SectionObjectPointer);
if (!Segment)
return FALSE;

/* Find byte offset of the page to start */
RangeStart.QuadPart = PAGE_ROUND_DOWN(RangeStart.QuadPart);

MmLockSectionSegment(Segment);

while (RangeStart.QuadPart < RangeEnd.QuadPart)
{
ULONG_PTR Entry = MmGetPageEntrySectionSegment(Segment, &RangeStart);
if ((Entry == 0) || IS_SWAP_FROM_SSE(Entry))
{
Ret = FALSE;
break;
}

RangeStart.QuadPart += PAGE_SIZE;
}

MmUnlockSectionSegment(Segment);
MmDereferenceSegment(Segment);

return Ret;
}

NTSTATUS
NTAPI
MmMakeDataSectionResident(
Expand All @@ -4940,6 +4989,63 @@ MmMakeDataSectionResident(
return Status;
}

NTSTATUS
NTAPI
MmMakeSegmentDirty(
_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer,
_In_ LONGLONG Offset,
_In_ ULONG Length)
{
PMM_SECTION_SEGMENT Segment;
LARGE_INTEGER RangeStart, RangeEnd;
NTSTATUS Status;

RangeStart.QuadPart = Offset;
Status = RtlLongLongAdd(RangeStart.QuadPart, Length, &RangeEnd.QuadPart);
if (!NT_SUCCESS(Status))
return Status;

Segment = MiGrabDataSection(SectionObjectPointer);
if (!Segment)
return STATUS_NOT_MAPPED_VIEW;

/* Find byte offset of the page to start */
RangeStart.QuadPart = PAGE_ROUND_DOWN(RangeStart.QuadPart);

MmLockSectionSegment(Segment);

while (RangeStart.QuadPart < RangeEnd.QuadPart)
{
ULONG_PTR Entry = MmGetPageEntrySectionSegment(Segment, &RangeStart);

/* Let any pending read proceed */
while (MM_IS_WAIT_PTE(Entry))
{
MmUnlockSectionSegment(Segment);
KeDelayExecutionThread(KernelMode, FALSE, &TinyTime);
MmLockSectionSegment(Segment);
Entry = MmGetPageEntrySectionSegment(Segment, &RangeStart);
}

/* We are called from Cc, this can't be backed by the page files */
ASSERT(!IS_SWAP_FROM_SSE(Entry));

/* If there is no page there, there is nothing to make dirty */
if (Entry != 0)
{
/* Dirtify the entry */
MmSetPageEntrySectionSegment(Segment, &RangeStart, DIRTY_SSE(Entry));
}

RangeStart.QuadPart += PAGE_SIZE;
}

MmUnlockSectionSegment(Segment);
MmDereferenceSegment(Segment);

return STATUS_SUCCESS;
}

NTSTATUS
NTAPI
MmFlushSegment(
Expand Down Expand Up @@ -4991,8 +5097,8 @@ MmFlushSegment(
FlushEnd.QuadPart = PageTable->FileOffset.QuadPart + _countof(PageTable->PageEntries) * PAGE_SIZE;
}

FlushStart.QuadPart >>= PAGE_SHIFT;
FlushStart.QuadPart <<= PAGE_SHIFT;
/* Find byte offset of the page to start */
FlushStart.QuadPart = PAGE_ROUND_DOWN(FlushStart.QuadPart);

while (FlushStart.QuadPart < FlushEnd.QuadPart)
{
Expand Down Expand Up @@ -5197,10 +5303,13 @@ MmCheckDirtySegment(
return FALSE;
}

/* This function is not used. It is left for future use, when per-process
* address space is considered. */
#if 0
NTSTATUS
NTAPI
MmMakePagesDirty(
_In_ PEPROCESS Process,
_In_opt_ PEPROCESS Process,
_In_ PVOID Address,
_In_ ULONG Length)
{
Expand Down Expand Up @@ -5267,6 +5376,7 @@ MmMakePagesDirty(
MmUnlockAddressSpace(AddressSpace);
return STATUS_SUCCESS;
}
#endif

NTSTATUS
NTAPI
Expand Down

0 comments on commit 69bf140

Please sign in to comment.