*/
/* INCLUDES *******************************************************************/
-/* So long, and Thanks for All the Fish */
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
#define MODULE_INVOLVED_IN_ARM3
-#include "../ARM3/miarm.h"
+#include <mm/ARM3/miarm.h>
#define MI_MAPPED_COPY_PAGES 14
#define MI_POOL_COPY_BYTES 512
IN PMMVAD Vad,
IN PEPROCESS Process)
{
- PMMPTE PointerPte, LastPte, PointerPde;
+ PMMPTE PointerPte, LastPte;
+ PMMPDE PointerPde;
ULONG CommittedPages;
/* Compute starting and ending PTE and PDE addresses */
CommittedPages = (ULONG)BYTES_TO_PAGES(EndingAddress - StartingAddress);
/* Is the PDE demand-zero? */
- PointerPde = MiAddressToPte(PointerPte);
+ PointerPde = MiPteToPde(PointerPte);
if (PointerPde->u.Long != 0)
{
/* It is not. Is it valid? */
if (MiIsPteOnPdeBoundary(PointerPte))
{
/* Is this PDE demand zero? */
- PointerPde = MiAddressToPte(PointerPte);
+ PointerPde = MiPteToPde(PointerPte);
if (PointerPde->u.Long != 0)
{
/* It isn't -- is it valid? */
CommittedPages = 0;
/* Is the PDE demand-zero? */
- PointerPde = MiAddressToPte(PointerPte);
+ PointerPde = MiPteToPde(PointerPte);
if (PointerPde->u.Long != 0)
{
/* It isn't -- is it invalid? */
if (MiIsPteOnPdeBoundary(PointerPte))
{
/* Is this new PDE demand-zero? */
- PointerPde = MiAddressToPte(PointerPte);
+ PointerPde = MiPteToPde(PointerPte);
if (PointerPde->u.Long != 0)
{
/* It isn't. Is it valid? */
while (!MmIsAddressValid(VirtualAddress))
{
/* Release the PFN database */
- KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+ MiReleasePfnLock(OldIrql);
/* Fault it in */
Status = MmAccessFault(FALSE, VirtualAddress, KernelMode, NULL);
LockChange = TRUE;
/* Lock the PFN database */
- OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+ OldIrql = MiAcquirePfnLock();
}
/* Let caller know what the lock state is */
Pfn2 = MiGetPfnEntry(PageTableIndex);
/* Lock the PFN database */
- OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+ OldIrql = MiAcquirePfnLock();
/* Delete it the page */
MI_SET_PFN_DELETED(Pfn1);
MiDecrementShareCount(Pfn2, PageTableIndex);
/* Release the PFN database */
- KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+ MiReleasePfnLock(OldIrql);
/* Destroy the PTE */
MI_ERASE_PTE(PointerPte);
PMMPDE PointerPde;
/* PFN lock must be held */
- ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+ MI_ASSERT_PFN_LOCK_HELD();
/* Capture the PTE */
TempPte = *PointerPte;
DPRINT("Pte %p is transitional!\n", PointerPte);
+ /* Make sure the saved PTE address is valid */
+ ASSERT((PMMPTE)((ULONG_PTR)Pfn1->PteAddress & ~0x1) == PointerPte);
+
/* Destroy the PTE */
MI_ERASE_PTE(PointerPte);
ASSERT(Pfn1->u3.e1.PrototypePte == 0);
/* Make the page free. For prototypes, it will be made free when deleting the section object */
- if (Pfn1->u2.ShareCount == 0)
+ if (Pfn1->u3.e2.ReferenceCount == 0)
{
- NT_ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
-
/* And it should be in standby or modified list */
ASSERT((Pfn1->u3.e1.PageLocation == ModifiedPageList) || (Pfn1->u3.e1.PageLocation == StandbyPageList));
- /* Unlink it and temporarily mark it as active */
+ /* Unlink it and set its reference count to one */
MiUnlinkPageFromList(Pfn1);
Pfn1->u3.e2.ReferenceCount++;
- Pfn1->u3.e1.PageLocation = ActiveAndValid;
/* This will put it back in free list and clean properly up */
MI_SET_PFN_DELETED(Pfn1);
}
/* Lock the PFN Database while we delete the PTEs */
- OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+ OldIrql = MiAcquirePfnLock();
do
{
/* Capture the PDE and make sure it exists */
}
/* Release the lock and get out if we're done */
- KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+ MiReleasePfnLock(OldIrql);
if (Va > EndingAddress) return;
/* Otherwise, we exited because we hit a new PDE boundary, so start over */
{
/* The PTE is valid, so we might need to get the protection from
the PFN. Lock the PFN database */
- OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+ OldIrql = MiAcquirePfnLock();
/* Check if the PDE is still valid */
if (MiAddressToPte(PointerPte)->u.Hard.Valid == 0)
}
/* Release the PFN database */
- KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+ MiReleasePfnLock(OldIrql);
}
/* Lock the working set again */
if (!NT_SUCCESS(Status))
{
DPRINT1("MmQuerySectionView failed. MemoryArea=%p (%p-%p), BaseAddress=%p\n",
- MemoryArea, MemoryArea->StartingAddress, MemoryArea->EndingAddress, BaseAddress);
- NT_ASSERT(NT_SUCCESS(Status));
+ MemoryArea, MA_GetStartingAddress(MemoryArea), MA_GetEndingAddress(MemoryArea), BaseAddress);
+ ASSERT(NT_SUCCESS(Status));
}
}
else
IN PMMVAD Vad,
IN PEPROCESS Process)
{
- PMMPTE PointerPte, LastPte, PointerPde;
+ PMMPTE PointerPte, LastPte;
+ PMMPDE PointerPde;
BOOLEAN OnBoundary = TRUE;
PAGED_CODE();
if (OnBoundary)
{
/* Is this PDE demand zero? */
- PointerPde = MiAddressToPte(PointerPte);
+ PointerPde = MiPteToPde(PointerPte);
if (PointerPde->u.Long != 0)
{
/* It isn't -- is it valid? */
if (PointerPde->u.Hard.Valid == 0)
{
/* Nope, fault it in */
- PointerPte = MiPteToAddress(PointerPde);
MiMakeSystemAddressValid(PointerPte, Process);
}
}
{
/* The PTE was already valid, so move to the next one */
PointerPde++;
- PointerPte = MiPteToAddress(PointerPde);
+ PointerPte = MiPdeToPte(PointerPde);
/* Is the entire VAD committed? If not, fail */
if (!Vad->u.VadFlags.MemCommit) return FALSE;
- /* Everything is committed so far past the range, return true */
- if (PointerPte > LastPte) return TRUE;
+ /* New loop iteration with our new, on-boundary PTE. */
+ continue;
}
}
PMMVAD Vad;
PMMSUPPORT AddressSpace;
ULONG_PTR StartingAddress, EndingAddress;
- PMMPTE PointerPde, PointerPte, LastPte;
+ PMMPTE PointerPte, LastPte;
+ PMMPDE PointerPde;
MMPTE PteContents;
PMMPFN Pfn1;
ULONG ProtectionMask, OldProtect;
/* Check if we've crossed a PDE boundary and make the new PDE valid too */
if (MiIsPteOnPdeBoundary(PointerPte))
{
- PointerPde = MiAddressToPte(PointerPte);
+ PointerPde = MiPteToPde(PointerPte);
MiMakePdeExistAndMakeValid(PointerPde, Process, MM_NOIRQL);
}
if ((NewAccessProtection & PAGE_NOACCESS) ||
(NewAccessProtection & PAGE_GUARD))
{
- KIRQL OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+ KIRQL OldIrql = MiAcquirePfnLock();
/* Mark the PTE as transition and change its protection */
PteContents.u.Hard.Valid = 0;
KeInvalidateTlbEntry(MiPteToAddress(PointerPte));
/* We are done for this PTE */
- KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+ MiReleasePfnLock(OldIrql);
}
else
{
VOID
NTAPI
-MiMakePdeExistAndMakeValid(IN PMMPTE PointerPde,
+MiMakePdeExistAndMakeValid(IN PMMPDE PointerPde,
IN PEPROCESS TargetProcess,
IN KIRQL OldIrql)
{
//
// Acquire the PFN lock and loop all the PTEs in the list
//
- OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+ OldIrql = MiAcquirePfnLock();
for (i = 0; i != Count; i++)
{
//
// and then release the PFN lock
//
KeFlushCurrentTb();
- KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+ MiReleasePfnLock(OldIrql);
}
ULONG
IN PEPROCESS Process,
IN PMMVAD Vad)
{
- PMMPTE PointerPde, PointerPte, CommitPte = NULL;
+ PMMPTE PointerPte, CommitPte = NULL;
+ PMMPDE PointerPde;
ULONG CommitReduction = 0;
PMMPTE ValidPteList[256];
ULONG PteCount = 0;
IN SIZE_T Length,
IN ULONG Mode)
{
- static BOOLEAN Warn; if (!Warn++) UNIMPLEMENTED;
+ static ULONG Warn; if (!Warn++) UNIMPLEMENTED;
return Address;
}
NTAPI
MmUnsecureVirtualMemory(IN PVOID SecureMem)
{
- static BOOLEAN Warn; if (!Warn++) UNIMPLEMENTED;
+ static ULONG Warn; if (!Warn++) UNIMPLEMENTED;
}
/* SYSTEM CALLS ***************************************************************/
return Status;
}
+NTSTATUS
+NTAPI
+NtFlushInstructionCache(_In_ HANDLE ProcessHandle,
+ _In_opt_ PVOID BaseAddress,
+ _In_ SIZE_T FlushSize)
+{
+ KAPC_STATE ApcState;
+ PKPROCESS Process;
+ NTSTATUS Status;
+ PAGED_CODE();
+
+ /* Is a base address given? */
+ if (BaseAddress != NULL)
+ {
+ /* If the requested size is 0, there is nothing to do */
+ if (FlushSize == 0)
+ {
+ return STATUS_SUCCESS;
+ }
+
+ /* Is this a user mode call? */
+ if (ExGetPreviousMode() != KernelMode)
+ {
+ /* Make sure the base address is in user space */
+ if (BaseAddress > MmHighestUserAddress)
+ {
+ DPRINT1("Invalid BaseAddress 0x%p\n", BaseAddress);
+ return STATUS_ACCESS_VIOLATION;
+ }
+ }
+ }
+
+ /* Is another process requested? */
+ if (ProcessHandle != NtCurrentProcess())
+ {
+ /* Reference the process */
+ Status = ObReferenceObjectByHandle(ProcessHandle,
+ PROCESS_VM_WRITE,
+ PsProcessType,
+ ExGetPreviousMode(),
+ (PVOID*)&Process,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to reference the process %p\n", ProcessHandle);
+ return Status;
+ }
+
+ /* Attach to the process */
+ KeStackAttachProcess(Process, &ApcState);
+ }
+
+ /* Forward to Ke */
+ KeSweepICache(BaseAddress, FlushSize);
+
+ /* Check if we attached */
+ if (ProcessHandle != NtCurrentProcess())
+ {
+ /* Detach from the process and dereference it */
+ KeUnstackDetachProcess(&ApcState);
+ ObDereferenceObject(Process);
+ }
+
+ /* All done, return to caller */
+ return STATUS_SUCCESS;
+}
+
NTSTATUS
NTAPI
NtProtectVirtualMemory(IN HANDLE ProcessHandle,
ULONG ProtectionMask, QuotaCharge = 0, QuotaFree = 0;
BOOLEAN Attached = FALSE, ChangeProtection = FALSE;
MMPTE TempPte;
- PMMPTE PointerPte, PointerPde, LastPte;
+ PMMPTE PointerPte, LastPte;
+ PMMPDE PointerPde;
TABLE_SEARCH_RESULT Result;
PAGED_CODE();
//
TempPte.u.Long = 0;
TempPte.u.Soft.Protection = ProtectionMask;
- NT_ASSERT(TempPte.u.Long != 0);
+ ASSERT(TempPte.u.Long != 0);
//
// Get the PTE, PDE and the last PTE for this address range
//
// Get the PDE and now make it valid too
//
- PointerPde = MiAddressToPte(PointerPte);
+ PointerPde = MiPteToPde(PointerPte);
MiMakePdeExistAndMakeValid(PointerPde, Process, MM_NOIRQL);
}
PAGED_CODE();
//
- // Only two flags are supported
- //
- if (!(FreeType & (MEM_RELEASE | MEM_DECOMMIT)))
- {
- DPRINT1("Invalid FreeType\n");
- return STATUS_INVALID_PARAMETER_4;
- }
-
- //
- // Check if no flag was used, or if both flags were used
+ // Only two flags are supported, exclusively.
//
- if (!((FreeType & (MEM_DECOMMIT | MEM_RELEASE))) ||
- ((FreeType & (MEM_DECOMMIT | MEM_RELEASE)) == (MEM_DECOMMIT | MEM_RELEASE)))
+ if (FreeType != MEM_RELEASE && FreeType != MEM_DECOMMIT)
{
- DPRINT1("Invalid FreeType combination\n");
+ DPRINT1("Invalid FreeType (0x%08lx)\n", FreeType);
return STATUS_INVALID_PARAMETER_4;
}
}
}
- DPRINT("NtFreeVirtualMemory: Process 0x%p, Adress 0x%p, size 0x%x, FreeType %x.\n",
- Process, PBaseAddress, PRegionSize, FreeType);
+ DPRINT("NtFreeVirtualMemory: Process 0x%p, Address 0x%p, Size 0x%Ix, FreeType 0x%08lx\n",
+ Process, PBaseAddress, PRegionSize, FreeType);
//
// Lock the address space
Vad->u.VadFlags.CommitCharge -= CommitReduction;
// For ReactOS: shrink the corresponding memory area
MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, (PVOID)StartingAddress);
- ASSERT(Vad->StartingVpn << PAGE_SHIFT == (ULONG_PTR)MemoryArea->StartingAddress);
- ASSERT((Vad->EndingVpn + 1) << PAGE_SHIFT == (ULONG_PTR)MemoryArea->EndingAddress);
- Vad->EndingVpn = ((ULONG_PTR)StartingAddress - 1) >> PAGE_SHIFT;
- MemoryArea->EndingAddress = (PVOID)(StartingAddress);
+ ASSERT(Vad->StartingVpn == MemoryArea->VadNode.StartingVpn);
+ ASSERT(Vad->EndingVpn == MemoryArea->VadNode.EndingVpn);
+ Vad->EndingVpn = (StartingAddress - 1) >> PAGE_SHIFT;
+ MemoryArea->VadNode.EndingVpn = Vad->EndingVpn;
}
else
{