Author: sir_richard
Date: Sun Oct 17 20:11:04 2010
New Revision: 49188
URL: http://svn.reactos.org/svn/reactos?rev=49188&view=rev
Log:
[NTOS]: Fix brainfart (an interesting bug we would've never hit, but a bug nevertheless).
Modified:
trunk/reactos/ntoskrnl/mm/ARM3/virtual.c
Modified: trunk/reactos/ntoskrnl/mm/ARM3/virtual.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/virtual.c…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/virtual.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/virtual.c [iso-8859-1] Sun Oct 17 20:11:04 2010
@@ -323,7 +323,7 @@
/* Otherwise, we exited because we hit a new PDE boundary, so start over */
PointerPde = MiAddressToPde(Va);
- } while (TRUE);
+ }
}
LONG
Author: sir_richard
Date: Sun Oct 17 20:02:17 2010
New Revision: 49187
URL: http://svn.reactos.org/svn/reactos?rev=49187&view=rev
Log:
[NTOS]: Use MI_SET_PFN_DELETED where we missed it.
[NTOS]: Implement support for deleting user-mode pageable VM addresses. Now when cleaning up the process address space, MiDeleteVirtualAddresses is called for the VADs, so this will now actually free the PEB/TEB pages that were previously getting leaked for each thread/process (a known regression I introduced when moving to VADs for PEB/TEB).
Modified:
trunk/reactos/ntoskrnl/mm/ARM3/miarm.h
trunk/reactos/ntoskrnl/mm/ARM3/procsup.c
trunk/reactos/ntoskrnl/mm/ARM3/virtual.c
Modified: trunk/reactos/ntoskrnl/mm/ARM3/miarm.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/miarm.h?r…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/miarm.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/miarm.h [iso-8859-1] Sun Oct 17 20:02:17 2010
@@ -1205,6 +1205,21 @@
IN ULONG Protect
);
+VOID
+NTAPI
+MiDeleteVirtualAddresses(
+ IN ULONG_PTR Va,
+ IN ULONG_PTR EndingAddress,
+ IN PMMVAD Vad
+);
+
+ULONG
+NTAPI
+MiMakeSystemAddressValid(
+ IN PVOID PageTableVirtualAddress,
+ IN PEPROCESS CurrentProcess
+);
+
//
// MiRemoveZeroPage will use inline code to zero out the page manually if only
// free pages are available. In some scenarios, we don't/can't run that piece of
Modified: trunk/reactos/ntoskrnl/mm/ARM3/procsup.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/procsup.c…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/procsup.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/procsup.c [iso-8859-1] Sun Oct 17 20:02:17 2010
@@ -139,6 +139,8 @@
/* Insert the VAD */
ASSERT(Vad->EndingVpn >= Vad->StartingVpn);
Process->VadRoot.NodeHint = Vad;
+ Vad->ControlArea = NULL; // For Memory-Area hack
+ Vad->FirstPrototypePte = NULL;
MiInsertNode(&Process->VadRoot, (PVOID)Vad, Parent, Result);
/* Release the working set */
@@ -258,7 +260,7 @@
MiDecrementShareCount(Pfn2, PageTableFrameNumber);
#endif
/* Set the special pending delete marker */
- Pfn1->PteAddress = (PMMPTE)((ULONG_PTR)Pfn1->PteAddress | 1);
+ MI_SET_PFN_DELETED(Pfn1);
/* And now delete the actual stack page */
MiDecrementShareCount(Pfn1, PageFrameNumber);
@@ -1174,7 +1176,6 @@
/* Enumerate the VADs */
VadTree = &Process->VadRoot;
- DPRINT("Cleaning up VADs: %d\n", VadTree->NumberGenericTableElements);
while (VadTree->NumberGenericTableElements)
{
/* Grab the current VAD */
@@ -1186,11 +1187,15 @@
/* Remove this VAD from the tree */
ASSERT(VadTree->NumberGenericTableElements >= 1);
MiRemoveNode((PMMADDRESS_NODE)Vad, VadTree);
- DPRINT("Moving on: %d\n", VadTree->NumberGenericTableElements);
/* Only PEB/TEB VADs supported for now */
ASSERT(Vad->u.VadFlags.PrivateMemory == 1);
ASSERT(Vad->u.VadFlags.VadType == VadNone);
+
+ /* Delete the addresses */
+ MiDeleteVirtualAddresses(Vad->StartingVpn << PAGE_SHIFT,
+ (Vad->EndingVpn << PAGE_SHIFT) | (PAGE_SIZE - 1),
+ Vad);
/* Release the working set */
MiUnlockProcessWorkingSet(Process, Thread);
Modified: trunk/reactos/ntoskrnl/mm/ARM3/virtual.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/virtual.c…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/virtual.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/virtual.c [iso-8859-1] Sun Oct 17 20:02:17 2010
@@ -28,6 +28,45 @@
OUT PULONG OldAccessProtection OPTIONAL);
/* PRIVATE FUNCTIONS **********************************************************/
+
+ULONG
+NTAPI
+MiMakeSystemAddressValid(IN PVOID PageTableVirtualAddress,
+ IN PEPROCESS CurrentProcess)
+{
+ NTSTATUS Status;
+ BOOLEAN LockChange = FALSE;
+
+ /* Must be a non-pool page table, since those are double-mapped already */
+ ASSERT(PageTableVirtualAddress > MM_HIGHEST_USER_ADDRESS);
+ ASSERT((PageTableVirtualAddress < MmPagedPoolStart) ||
+ (PageTableVirtualAddress > MmPagedPoolEnd));
+
+ /* Working set lock or PFN lock should be held */
+ ASSERT(KeAreAllApcsDisabled() == TRUE);
+
+ /* Check if the page table is valid */
+ while (!MmIsAddressValid(PageTableVirtualAddress))
+ {
+ /* Fault it in */
+ Status = MmAccessFault(FALSE, PageTableVirtualAddress, KernelMode, NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ /* This should not fail */
+ KeBugCheckEx(KERNEL_DATA_INPAGE_ERROR,
+ 1,
+ Status,
+ (ULONG_PTR)CurrentProcess,
+ (ULONG_PTR)PageTableVirtualAddress);
+ }
+
+ /* This flag will be useful later when we do better locking */
+ LockChange = TRUE;
+ }
+
+ /* Let caller know what the lock state is */
+ return LockChange;
+}
PFN_NUMBER
NTAPI
@@ -126,6 +165,167 @@
return ActualPages;
}
+VOID
+NTAPI
+MiDeletePte(IN PMMPTE PointerPte,
+ IN PVOID VirtualAddress,
+ IN PEPROCESS CurrentProcess)
+{
+ PMMPFN Pfn1;
+ MMPTE PteContents;
+ PFN_NUMBER PageFrameIndex;
+
+ /* PFN lock must be held */
+ ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+
+ /* Capture the PTE */
+ PteContents = *PointerPte;
+
+ /* We only support valid PTEs for now */
+ ASSERT(PteContents.u.Hard.Valid == 1);
+ ASSERT(PteContents.u.Soft.Prototype == 0);
+ ASSERT(PteContents.u.Soft.Transition == 0);
+
+ /* Get the PFN entry */
+ PageFrameIndex = PFN_FROM_PTE(&PteContents);
+ Pfn1 = MiGetPfnEntry(PageFrameIndex);
+
+ /* We don't support deleting prototype PTEs for now */
+ ASSERT(Pfn1->u3.e1.PrototypePte == 0);
+
+ /* Make sure the saved PTE address is valid */
+ if ((PMMPTE)((ULONG_PTR)Pfn1->PteAddress & ~0x1) != PointerPte)
+ {
+ /* The PFN entry is illegal, or invalid */
+ KeBugCheckEx(MEMORY_MANAGEMENT,
+ 0x401,
+ (ULONG_PTR)PointerPte,
+ PointerPte->u.Long,
+ (ULONG_PTR)Pfn1->PteAddress);
+ }
+
+ /* There should only be 1 shared reference count */
+ ASSERT(Pfn1->u2.ShareCount == 1);
+
+ /* FIXME: Drop the reference on the page table. For now, leak it until RosMM is gone */
+ //MiDecrementShareCount(MiGetPfnEntry(Pfn1->u4.PteFrame), Pfn1->u4.PteFrame);
+
+ /* Mark the PFN for deletion and dereference what should be the last ref */
+ MI_SET_PFN_DELETED(Pfn1);
+ MiDecrementShareCount(Pfn1, PageFrameIndex);
+
+ /* We should eventually do this */
+ //CurrentProcess->NumberOfPrivatePages--;
+
+ /* Destroy the PTE and flush the TLB */
+ PointerPte->u.Long = 0;
+ KeFlushCurrentTb();
+}
+
+VOID
+NTAPI
+MiDeleteVirtualAddresses(IN ULONG_PTR Va,
+ IN ULONG_PTR EndingAddress,
+ IN PMMVAD Vad)
+{
+ PMMPTE PointerPte, PointerPde;
+ MMPTE TempPte;
+ PEPROCESS CurrentProcess;
+ KIRQL OldIrql;
+
+ /* Grab the process and PTE/PDE for the address being deleted */
+ CurrentProcess = PsGetCurrentProcess();
+ PointerPde = MiAddressToPde(Va);
+ PointerPte = MiAddressToPte(Va);
+
+ /* We usually only get a VAD when it's not a VM address */
+ if (Vad)
+ {
+ /* At process deletion, we may get a VAD, but it should be a VM VAD */
+ ASSERT(Vad->u.VadFlags.PrivateMemory);
+ ASSERT(Vad->FirstPrototypePte == NULL);
+
+ /* Get out if this is a fake VAD, RosMm will free the marea pages */
+ if (Vad->u.VadFlags.Spare == 1) return;
+ }
+
+ /* In all cases, we don't support fork() yet */
+ ASSERT(CurrentProcess->CloneRoot == NULL);
+
+ /* Loop the PTE for each VA */
+ while (TRUE)
+ {
+ /* First keep going until we find a valid PDE */
+ while (PointerPde->u.Long == 0)
+ {
+ /* Still no valid PDE, try the next 4MB (or whatever) */
+ PointerPde++;
+
+ /* Update the PTE on this new boundary */
+ PointerPte = MiPteToAddress(PointerPde);
+
+ /* Check if all the PDEs are invalid, so there's nothing to free */
+ Va = (ULONG_PTR)MiPteToAddress(PointerPte);
+ if (Va > EndingAddress) return;
+ }
+
+ /* Now check if the PDE is mapped in */
+ if (PointerPde->u.Hard.Valid == 0)
+ {
+ /* It isn't, so map it in */
+ PointerPte = MiPteToAddress(PointerPde);
+ MiMakeSystemAddressValid(PointerPte, CurrentProcess);
+ }
+
+ /* Now we should have a valid PDE, mapped in, and still have some VA */
+ ASSERT(PointerPde->u.Hard.Valid == 1);
+ ASSERT(Va <= EndingAddress);
+
+ /* Lock the PFN Database while we delete the PTEs */
+ OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+ do
+ {
+ /* Capture the PDE and make sure it exists */
+ TempPte = *PointerPte;
+ if (TempPte.u.Long)
+ {
+ /* Check if the PTE is actually mapped in */
+ if (TempPte.u.Long & 0xFFFFFC01)
+ {
+ /* It is, we don't support prototype PTEs for now though */
+ ASSERT(TempPte.u.Soft.Prototype == 0);
+
+ /* Delete the PTE proper */
+ MiDeletePte(PointerPte, (PVOID)Va, CurrentProcess);
+ }
+ else
+ {
+ /* The PTE was never mapped, just nuke it here */
+ PointerPte->u.Long = 0;
+ }
+ }
+
+ /* Update the address and PTE for it */
+ Va += PAGE_SIZE;
+ PointerPte++;
+
+ /* Making sure the PDE is still valid */
+ ASSERT(PointerPde->u.Hard.Valid == 1);
+ }
+ while ((Va & (PDE_MAPPED_VA - 1)) && (Va <= EndingAddress));
+
+ /* The PDE should still be valid at this point */
+ ASSERT(PointerPde->u.Hard.Valid == 1);
+
+ /* Release the lock and get out if we're done */
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+ if (Va > EndingAddress) return;
+
+ /* Otherwise, we exited because we hit a new PDE boundary, so start over */
+ PointerPde = MiAddressToPde(Va);
+ } while (TRUE);
+}
+
LONG
MiGetExceptionInfo(IN PEXCEPTION_POINTERS ExceptionInfo,
OUT PBOOLEAN HaveBadAddress,
Author: spetreolle
Date: Sun Oct 17 11:12:54 2010
New Revision: 49180
URL: http://svn.reactos.org/svn/reactos?rev=49180&view=rev
Log:
Patch by Roel Messiant :
Initialise PPB to zero.
The change from NtAllocateVirtualMemory to RtlAllocateHeap causes the memory to
be not automatically initialised to zero anymore.
Not every field of the PPB (for which the memory is allocated) gets explicitly
initialised, meaning this results in them having bogus values.
One of the now uninitialised fields is DebugFlags, which results in
DbgBreakPoint being called in NtProcessStartup. Simply ensuring the memory is
zeroed makes it all better again.
Modified:
trunk/reactos/lib/rtl/ppb.c
Modified: trunk/reactos/lib/rtl/ppb.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/ppb.c?rev=49180&r1…
==============================================================================
--- trunk/reactos/lib/rtl/ppb.c [iso-8859-1] (original)
+++ trunk/reactos/lib/rtl/ppb.c [iso-8859-1] Sun Oct 17 11:12:54 2010
@@ -119,7 +119,7 @@
Length += ALIGN(RuntimeData->MaximumLength, sizeof(ULONG));
/* Calculate the required block size */
- Param = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length);
+ Param = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, Length);
if (!Param)
{
RtlReleasePebLock();