Author: sir_richard
Date: Thu Jul 22 18:37:27 2010
New Revision: 48190
URL: http://svn.reactos.org/svn/reactos?rev=48190&view=rev
Log:
[NTOS]: Add support for handling a very specific type of user-fault on ARM3 memory: memory belonging to a VAD allocation made for a PEB/TEB (read-write) that hasn't yet been allocated.
[NTOS]: Define the demand-zero PDE template.
Modified:
trunk/reactos/ntoskrnl/mm/ARM3/i386/init.c
trunk/reactos/ntoskrnl/mm/ARM3/miarm.h
trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c
Modified: trunk/reactos/ntoskrnl/mm/ARM3/i386/init.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/i386/init…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/i386/init.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/i386/init.c [iso-8859-1] Thu Jul 22 18:37:27 2010
@@ -21,6 +21,9 @@
/* Template PTE and PDE for a kernel page */
MMPTE ValidKernelPde = {.u.Hard.Valid = 1, .u.Hard.Write = 1, .u.Hard.Dirty = 1, .u.Hard.Accessed = 1};
MMPTE ValidKernelPte = {.u.Hard.Valid = 1, .u.Hard.Write = 1, .u.Hard.Dirty = 1, .u.Hard.Accessed = 1};
+
+/* Template PDE for a demand-zero page */
+MMPDE DemandZeroPde = {.u.Long = (MM_READWRITE << MM_PTE_SOFTWARE_PROTECTION_BITS)};
/* PRIVATE FUNCTIONS **********************************************************/
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] Thu Jul 22 18:37:27 2010
@@ -377,6 +377,7 @@
extern MMPTE HyperTemplatePte;
extern MMPDE ValidKernelPde;
extern MMPTE ValidKernelPte;
+extern MMPDE DemandZeroPde;
extern BOOLEAN MmLargeSystemCache;
extern BOOLEAN MmZeroPageFile;
extern BOOLEAN MmProtectFreedNonPagedPool;
Modified: trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/pagfault.…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c [iso-8859-1] Thu Jul 22 18:37:27 2010
@@ -20,6 +20,34 @@
/* PRIVATE FUNCTIONS **********************************************************/
+PMMPTE
+NTAPI
+MiCheckVirtualAddress(IN PVOID VirtualAddress,
+ OUT PULONG ProtectCode,
+ OUT PMMVAD *ProtoVad)
+{
+ PMMVAD Vad;
+
+ /* No prototype/section support for now */
+ *ProtoVad = NULL;
+
+ /* Only valid for user VADs for now */
+ ASSERT(VirtualAddress <= MM_HIGHEST_USER_ADDRESS);
+
+ /* Find the VAD, it must exist, since we only handle PEB/TEB */
+ Vad = MiLocateAddress(VirtualAddress);
+ ASSERT(Vad);
+
+ /* This must be a TEB/PEB VAD */
+ ASSERT(Vad->u.VadFlags.PrivateMemory == TRUE);
+ ASSERT(Vad->u.VadFlags.MemCommit == TRUE);
+ ASSERT(Vad->u.VadFlags.VadType == VadNone);
+
+ /* Return the protection on it */
+ *ProtectCode = Vad->u.VadFlags.Protection;
+ return NULL;
+}
+
NTSTATUS
FASTCALL
MiCheckPdeForPagedPool(IN PVOID Address)
@@ -300,6 +328,9 @@
PEPROCESS CurrentProcess;
NTSTATUS Status;
PMMSUPPORT WorkingSet;
+ ULONG ProtectionCode;
+ PMMVAD Vad;
+ PFN_NUMBER PageFrameIndex;
DPRINT("ARM3 FAULT AT: %p\n", Address);
//
@@ -494,12 +525,101 @@
/* Lock the working set */
MiLockProcessWorkingSet(CurrentProcess, CurrentThread);
- /* Do something */
+ /* First things first, is the PDE valid? */
+ ASSERT(PointerPde != MiAddressToPde(PTE_BASE));
+ ASSERT(PointerPde->u.Hard.LargePage == 0);
+ if (PointerPde->u.Hard.Valid == 0)
+ {
+ /* Right now, we only handle scenarios where the PDE is totally empty */
+ ASSERT(PointerPde->u.Long == 0);
+
+ /* Check if this address range belongs to a valid allocation (VAD) */
+ MiCheckVirtualAddress(Address, &ProtectionCode, &Vad);
+
+ /* Right now, we expect a valid protection mask on the VAD */
+ ASSERT(ProtectionCode != MM_NOACCESS);
+
+ /* Make the PDE demand-zero */
+ MI_WRITE_INVALID_PTE(PointerPde, DemandZeroPde);
+
+ /* And go dispatch the fault on the PDE. This should handle the demand-zero */
+ Status = MiDispatchFault(TRUE,
+ PointerPte,
+ PointerPde,
+ NULL,
+ FALSE,
+ PsGetCurrentProcess(),
+ TrapInformation,
+ NULL);
+
+ /* We should come back with APCs enabled, and with a valid PDE */
+ ASSERT(KeAreAllApcsDisabled() == TRUE);
+ ASSERT(PointerPde->u.Hard.Valid == 1);
+ }
+
+ /* Now capture the PTE. We only handle cases where it's totally empty */
+ TempPte = *PointerPte;
+ ASSERT(TempPte.u.Long == 0);
+
+ /* Check if this address range belongs to a valid allocation (VAD) */
+ MiCheckVirtualAddress(Address, &ProtectionCode, &Vad);
+
+ /* Right now, we expect a valid protection mask on the VAD */
+ ASSERT(ProtectionCode != MM_NOACCESS);
+ PointerPte->u.Soft.Protection = ProtectionCode;
+
+ /* Lock the PFN database since we're going to grab a page */
+ OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+
+ /* Grab a page out of there. Later we should grab a colored zero page */
+ PageFrameIndex = MiRemoveAnyPage(0);
+ ASSERT(PageFrameIndex);
+
+ /* Release the lock since we need to do some zeroing */
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+
+ /* Zero out the page, since it's for user-mode */
+ MiZeroPfn(PageFrameIndex);
+
+ /* Grab the lock again so we can initialize the PFN entry */
+ OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+
+ /* Initialize the PFN entry now */
+ MiInitializePfn(PageFrameIndex, PointerPte, 1);
+
+ /* And we're done with the lock */
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+
+ /* One more demand-zero fault */
+ InterlockedIncrement(&KeGetCurrentPrcb()->MmDemandZeroCount);
+
+ /* Was the fault on an actual user page, or a kernel page for the user? */
+ if (PointerPte <= MiHighestUserPte)
+ {
+ /* User fault, build a user PTE */
+ MI_MAKE_HARDWARE_PTE_USER(&TempPte,
+ PointerPte,
+ PointerPte->u.Soft.Protection,
+ PageFrameIndex);
+ }
+ else
+ {
+ /* Session, kernel, or user PTE, figure it out and build it */
+ MI_MAKE_HARDWARE_PTE(&TempPte,
+ PointerPte,
+ PointerPte->u.Soft.Protection,
+ PageFrameIndex);
+ }
+
+ /* Write the dirty bit for writeable pages */
+ if (TempPte.u.Hard.Write) TempPte.u.Hard.Dirty = TRUE;
+
+ /* And now write down the PTE, making the address valid */
+ MI_WRITE_VALID_PTE(PointerPte, TempPte);
/* Release the working set */
MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
- DPRINT1("WARNING: USER MODE FAULT IN ARM3???\n");
- return STATUS_ACCESS_VIOLATION;
+ return STATUS_PAGE_FAULT_DEMAND_ZERO;
}
/* EOF */
Author: cgutman
Date: Thu Jul 22 18:29:35 2010
New Revision: 48188
URL: http://svn.reactos.org/svn/reactos?rev=48188&view=rev
Log:
[NETCFGX]
- Start the TCP/IP driver after we install a network adapter
- This fixes the major bug that blocks Live CD networking but we still have some DHCP issues (DHCP starts and fails before the NIC and TCP/IP has been installed) and some other adapter detection issues that I need to look into but this is a good first step
Modified:
trunk/reactos/dll/win32/netcfgx/netcfgx.c
trunk/reactos/dll/win32/netcfgx/precomp.h
Modified: trunk/reactos/dll/win32/netcfgx/netcfgx.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/netcfgx/netcfgx.…
==============================================================================
--- trunk/reactos/dll/win32/netcfgx/netcfgx.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/netcfgx/netcfgx.c [iso-8859-1] Thu Jul 22 18:29:35 2010
@@ -290,6 +290,7 @@
IN HWND hWnd)
{
BOOL ret;
+ UNICODE_STRING TcpipServicePath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Tcpip");
/* Install TCP/IP protocol */
ret = InstallInfSection(
@@ -302,6 +303,17 @@
DPRINT("InstallInfSection() failed with error 0x%lx\n", GetLastError());
return GetLastError();
}
+ else if (ret)
+ {
+ /* Start the TCP/IP driver */
+ ret = NtLoadDriver(&TcpipServicePath);
+ if (ret)
+ {
+ /* This isn't really fatal but we want to warn anyway */
+ DPRINT1("NtLoadDriver(TCPIP) failed with NTSTATUS 0x%lx\n", (NTSTATUS)ret);
+ }
+ }
+
/* You can add here more clients (SMB...) and services (DHCP server...) */
Modified: trunk/reactos/dll/win32/netcfgx/precomp.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/netcfgx/precomp.…
==============================================================================
--- trunk/reactos/dll/win32/netcfgx/precomp.h [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/netcfgx/precomp.h [iso-8859-1] Thu Jul 22 18:29:35 2010
@@ -5,7 +5,10 @@
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
+#define WIN32_NO_STATUS
#include <windows.h>
+#define NTOS_MODE_USER
+#include <ndk/ntndk.h>
#include <netcfgx.h>
#include <setupapi.h>
#include <stdio.h>
Author: sir_richard
Date: Thu Jul 22 18:26:04 2010
New Revision: 48187
URL: http://svn.reactos.org/svn/reactos?rev=48187&view=rev
Log:
[NTOS]: Fix a very stupid bug which made any machine with less than 52GB of RAM appear as a "Small memory machine" (instead of 13MB).
[NTOS]: Initialize MmTotalCommitLimit, MmTotalCommitLimitMaximum for consistency.
[NTOS]: Initialize and honor MmAllocationFragment value from registry, or from defaults.
[NTOS]: Initialize the system cache working set pushlock.
[NTOS]: Implement Mi(Un)Lock(Process)WorkingSet inlines to handle the various scenarios. Replace broken/hacky code that was in the system loader, fault handler, and VM deletion paths with the correct macros. No locking is done yet as ReactOS' MAREA implementation overloads the Vm field in EPROCESS, but the correct APC blockings and state transitions are done.
[NTOS]: Add another helper from symbols, MI_IS_PAGE_TABLE_OR_HYPER_ADDRESS, and use it instead of the math-by-hand.
[NTOS]: Add MM_IS_ANY_LOCK_HELD and MI_WS_OWNER to help out the new working let locking inlines (names taken from symbols).
[NTOS]: Add _1GB helper for large-memory checks. Also define _1KB as "1024u". The "u" makes GCC not complain when sizes reach >= 2GB, because GCC will interpret the integer literals as "signed", even if the final calculated value is in an unsigned variable.
Modified:
trunk/reactos/ntoskrnl/mm/ARM3/miarm.h
trunk/reactos/ntoskrnl/mm/ARM3/mminit.c
trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c
trunk/reactos/ntoskrnl/mm/ARM3/sysldr.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] Thu Jul 22 18:26:04 2010
@@ -8,35 +8,39 @@
#ifndef _M_AMD64
-#define MI_MIN_PAGES_FOR_NONPAGED_POOL_TUNING ((255*1024*1024) >> PAGE_SHIFT)
-#define MI_MIN_PAGES_FOR_SYSPTE_TUNING ((19*1024*1024) >> PAGE_SHIFT)
-#define MI_MIN_PAGES_FOR_SYSPTE_BOOST ((32*1024*1024) >> PAGE_SHIFT)
-#define MI_MAX_INIT_NONPAGED_POOL_SIZE (128 * 1024 * 1024)
-#define MI_MAX_NONPAGED_POOL_SIZE (128 * 1024 * 1024)
-#define MI_MAX_FREE_PAGE_LISTS 4
-
-#define MI_MIN_INIT_PAGED_POOLSIZE (32 * 1024 * 1024)
-
-#define MI_SESSION_VIEW_SIZE (20 * 1024 * 1024)
-#define MI_SESSION_POOL_SIZE (16 * 1024 * 1024)
-#define MI_SESSION_IMAGE_SIZE (8 * 1024 * 1024)
-#define MI_SESSION_WORKING_SET_SIZE (4 * 1024 * 1024)
-#define MI_SESSION_SIZE (MI_SESSION_VIEW_SIZE + \
- MI_SESSION_POOL_SIZE + \
- MI_SESSION_IMAGE_SIZE + \
- MI_SESSION_WORKING_SET_SIZE)
-
-#define MI_SYSTEM_VIEW_SIZE (16 * 1024 * 1024)
-
-#define MI_SYSTEM_CACHE_WS_START (PVOID)0xC0C00000
-#define MI_PAGED_POOL_START (PVOID)0xE1000000
-#define MI_NONPAGED_POOL_END (PVOID)0xFFBE0000
-#define MI_DEBUG_MAPPING (PVOID)0xFFBFF000
+#define MI_MIN_PAGES_FOR_NONPAGED_POOL_TUNING ((255 * _1MB) >> PAGE_SHIFT)
+#define MI_MIN_PAGES_FOR_SYSPTE_TUNING ((19 * _1MB) >> PAGE_SHIFT)
+#define MI_MIN_PAGES_FOR_SYSPTE_BOOST ((32 * _1MB) >> PAGE_SHIFT)
+#define MI_MAX_INIT_NONPAGED_POOL_SIZE (128 * _1MB)
+#define MI_MAX_NONPAGED_POOL_SIZE (128 * _1MB)
+#define MI_MAX_FREE_PAGE_LISTS 4
+
+#define MI_MIN_INIT_PAGED_POOLSIZE (32 * _1MB)
+
+#define MI_SESSION_VIEW_SIZE (20 * _1MB)
+#define MI_SESSION_POOL_SIZE (16 * _1MB)
+#define MI_SESSION_IMAGE_SIZE (8 * _1MB)
+#define MI_SESSION_WORKING_SET_SIZE (4 * _1MB)
+#define MI_SESSION_SIZE (MI_SESSION_VIEW_SIZE + \
+ MI_SESSION_POOL_SIZE + \
+ MI_SESSION_IMAGE_SIZE + \
+ MI_SESSION_WORKING_SET_SIZE)
+
+#define MI_SYSTEM_VIEW_SIZE (16 * _1MB)
+
+#define MI_SYSTEM_CACHE_WS_START (PVOID)0xC0C00000
+#define MI_PAGED_POOL_START (PVOID)0xE1000000
+#define MI_NONPAGED_POOL_END (PVOID)0xFFBE0000
+#define MI_DEBUG_MAPPING (PVOID)0xFFBFF000
#define MI_MIN_SECONDARY_COLORS 8
#define MI_SECONDARY_COLORS 64
#define MI_MAX_SECONDARY_COLORS 1024
+#define MI_MIN_ALLOCATION_FRAGMENT (4 * _1KB)
+#define MI_ALLOCATION_FRAGMENT (64 * _1KB)
+#define MI_MAX_ALLOCATION_FRAGMENT (2 * _1MB)
+
#define MM_HIGHEST_VAD_ADDRESS \
(PVOID)((ULONG_PTR)MM_HIGHEST_USER_ADDRESS - (16 * PAGE_SIZE))
@@ -46,8 +50,9 @@
#endif /* !_M_AMD64 */
/* Make the code cleaner with some definitions for size multiples */
-#define _1KB (1024)
+#define _1KB (1024u)
#define _1MB (1024 * _1KB)
+#define _1GB (1024 * _1MB)
/* Area mapped by a PDE */
#define PDE_MAPPED_VA (PTE_COUNT * PAGE_SIZE)
@@ -199,6 +204,9 @@
#define MI_IS_SYSTEM_PAGE_TABLE_ADDRESS(Address) \
(((Address) >= (PVOID)MiAddressToPte(MmSystemRangeStart)) && ((Address) <= (PVOID)PTE_TOP))
+#define MI_IS_PAGE_TABLE_OR_HYPER_ADDRESS(Address) \
+ (((PVOID)(Address) >= (PVOID)PTE_BASE) && ((PVOID)(Address) <= (PVOID)MmHyperSpaceEnd))
+
//
// Corresponds to MMPTE_SOFTWARE.Protection
//
@@ -608,6 +616,165 @@
*PointerPte = InvalidPte;
}
+//
+// Checks if the thread already owns a working set
+//
+FORCEINLINE
+BOOLEAN
+MM_ANY_WS_LOCK_HELD(IN PETHREAD Thread)
+{
+ /* If any of these are held, return TRUE */
+ return ((Thread->OwnsProcessWorkingSetExclusive) ||
+ (Thread->OwnsProcessWorkingSetShared) ||
+ (Thread->OwnsSystemWorkingSetExclusive) ||
+ (Thread->OwnsSystemWorkingSetShared) ||
+ (Thread->OwnsSessionWorkingSetExclusive) ||
+ (Thread->OwnsSessionWorkingSetShared));
+}
+
+//
+// Checks if the process owns the working set lock
+//
+FORCEINLINE
+BOOLEAN
+MI_WS_OWNER(IN PEPROCESS Process)
+{
+ /* Check if this process is the owner, and that the thread owns the WS */
+ return ((KeGetCurrentThread()->ApcState.Process == &Process->Pcb) &&
+ ((PsGetCurrentThread()->OwnsProcessWorkingSetExclusive) ||
+ (PsGetCurrentThread()->OwnsProcessWorkingSetShared)));
+}
+
+//
+// Locks the working set for the given process
+//
+FORCEINLINE
+VOID
+MiLockProcessWorkingSet(IN PEPROCESS Process,
+ IN PETHREAD Thread)
+{
+ /* Shouldn't already be owning the process working set */
+ ASSERT(Thread->OwnsProcessWorkingSetShared == FALSE);
+ ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE);
+
+ /* Block APCs, make sure that still nothing is already held */
+ KeEnterGuardedRegion();
+ ASSERT(!MM_ANY_WS_LOCK_HELD(Thread));
+
+ /* FIXME: Actually lock it (we can't because Vm is used by MAREAs) */
+
+ /* FIXME: This also can't be checked because Vm is used by MAREAs) */
+ //ASSERT(Process->Vm.Flags.AcquiredUnsafe == 0);
+
+ /* Okay, now we can own it exclusively */
+ ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE);
+ Thread->OwnsProcessWorkingSetExclusive = TRUE;
+}
+
+//
+// Unlocks the working set for the given process
+//
+FORCEINLINE
+VOID
+MiUnlockProcessWorkingSet(IN PEPROCESS Process,
+ IN PETHREAD Thread)
+{
+ /* Make sure this process really is owner, and it was a safe acquisition */
+ ASSERT(MI_WS_OWNER(Process));
+ /* This can't be checked because Vm is used by MAREAs) */
+ //ASSERT(Process->Vm.Flags.AcquiredUnsafe == 0);
+
+ /* The thread doesn't own it anymore */
+ ASSERT(Thread->OwnsProcessWorkingSetExclusive == TRUE);
+ Thread->OwnsProcessWorkingSetExclusive = FALSE;
+
+ /* FIXME: Actually release it (we can't because Vm is used by MAREAs) */
+
+ /* Unblock APCs */
+ KeLeaveGuardedRegion();
+}
+
+//
+// Locks the working set
+//
+FORCEINLINE
+VOID
+MiLockWorkingSet(IN PETHREAD Thread,
+ IN PMMSUPPORT WorkingSet)
+{
+ /* Block APCs */
+ KeEnterGuardedRegion();
+
+ /* Working set should be in global memory */
+ ASSERT(MI_IS_SESSION_ADDRESS((PVOID)WorkingSet) == FALSE);
+
+ /* Thread shouldn't already be owning something */
+ ASSERT(!MM_ANY_WS_LOCK_HELD(Thread));
+
+ /* FIXME: Actually lock it (we can't because Vm is used by MAREAs) */
+
+ /* Which working set is this? */
+ if (WorkingSet == &MmSystemCacheWs)
+ {
+ /* Own the system working set */
+ ASSERT((Thread->OwnsSystemWorkingSetExclusive == FALSE) &&
+ (Thread->OwnsSystemWorkingSetShared == FALSE));
+ Thread->OwnsSystemWorkingSetExclusive = TRUE;
+ }
+ else if (WorkingSet->Flags.SessionSpace)
+ {
+ /* We don't implement this yet */
+ UNIMPLEMENTED;
+ while (TRUE);
+ }
+ else
+ {
+ /* Own the process working set */
+ ASSERT((Thread->OwnsProcessWorkingSetExclusive == FALSE) &&
+ (Thread->OwnsProcessWorkingSetShared == FALSE));
+ Thread->OwnsProcessWorkingSetExclusive = TRUE;
+ }
+}
+
+//
+// Unlocks the working set
+//
+FORCEINLINE
+VOID
+MiUnlockWorkingSet(IN PETHREAD Thread,
+ IN PMMSUPPORT WorkingSet)
+{
+ /* Working set should be in global memory */
+ ASSERT(MI_IS_SESSION_ADDRESS((PVOID)WorkingSet) == FALSE);
+
+ /* Which working set is this? */
+ if (WorkingSet == &MmSystemCacheWs)
+ {
+ /* Release the system working set */
+ ASSERT((Thread->OwnsSystemWorkingSetExclusive == TRUE) ||
+ (Thread->OwnsSystemWorkingSetShared == TRUE));
+ Thread->OwnsSystemWorkingSetExclusive = FALSE;
+ }
+ else if (WorkingSet->Flags.SessionSpace)
+ {
+ /* We don't implement this yet */
+ UNIMPLEMENTED;
+ while (TRUE);
+ }
+ else
+ {
+ /* Release the process working set */
+ ASSERT((Thread->OwnsProcessWorkingSetExclusive) ||
+ (Thread->OwnsProcessWorkingSetShared));
+ Thread->OwnsProcessWorkingSetExclusive = FALSE;
+ }
+
+ /* FIXME: Actually release it (we can't because Vm is used by MAREAs) */
+
+ /* Unblock APCs */
+ KeLeaveGuardedRegion();
+}
+
NTSTATUS
NTAPI
MmArmInitSystem(
Modified: trunk/reactos/ntoskrnl/mm/ARM3/mminit.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/mminit.c?…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/mminit.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/mminit.c [iso-8859-1] Thu Jul 22 18:26:04 2010
@@ -327,6 +327,26 @@
/* FIXME: Move to cache/working set code later */
BOOLEAN MmLargeSystemCache;
+
+/*
+ * This value determines in how many fragments/chunks the subsection prototype
+ * PTEs should be allocated when mapping a section object. It is configurable in
+ * the registry through the MapAllocationFragment parameter.
+ *
+ * The default is 64KB on systems with more than 1GB of RAM, 32KB on systems with
+ * more than 256MB of RAM, and 16KB on systems with less than 256MB of RAM.
+ *
+ * The maximum it can be set to is 2MB, and the minimum is 4KB.
+ */
+SIZE_T MmAllocationFragment;
+
+/*
+ * These two values track how much virtual memory can be committed, and when
+ * expansion should happen.
+ */
+ // FIXME: They should be moved elsewhere since it's not an "init" setting?
+SIZE_T MmTotalCommitLimit;
+SIZE_T MmTotalCommitLimitMaximum;
/* PRIVATE FUNCTIONS **********************************************************/
@@ -1799,6 +1819,44 @@
DPRINT("System PTE count has been tuned to %d (%d bytes)\n",
MmNumberOfSystemPtes, MmNumberOfSystemPtes * PAGE_SIZE);
+
+ /* Initialize the working set lock */
+ ExInitializePushLock((PULONG_PTR)&MmSystemCacheWs.WorkingSetMutex);
+
+ /* Set commit limit */
+ MmTotalCommitLimit = 2 * _1GB;
+ MmTotalCommitLimitMaximum = MmTotalCommitLimit;
+
+ /* Has the allocation fragment been setup? */
+ if (!MmAllocationFragment)
+ {
+ /* Use the default value */
+ MmAllocationFragment = MI_ALLOCATION_FRAGMENT;
+ if (PageCount < ((256 * _1MB) / PAGE_SIZE))
+ {
+ /* On memory systems with less than 256MB, divide by 4 */
+ MmAllocationFragment = MI_ALLOCATION_FRAGMENT / 4;
+ }
+ else if (PageCount < (_1GB / PAGE_SIZE))
+ {
+ /* On systems with less than 1GB, divide by 2 */
+ MmAllocationFragment = MI_ALLOCATION_FRAGMENT / 2;
+ }
+ }
+ else
+ {
+ /* Convert from 1KB fragments to pages */
+ MmAllocationFragment *= _1KB;
+ MmAllocationFragment = ROUND_TO_PAGES(MmAllocationFragment);
+
+ /* Don't let it past the maximum */
+ MmAllocationFragment = min(MmAllocationFragment,
+ MI_MAX_ALLOCATION_FRAGMENT);
+
+ /* Don't let it too small either */
+ MmAllocationFragment = max(MmAllocationFragment,
+ MI_MIN_ALLOCATION_FRAGMENT);
+ }
/* Initialize the platform-specific parts */
MiInitMachineDependent(LoaderBlock);
@@ -1889,12 +1947,12 @@
/* FIXME: Call out into Driver Verifier for initialization */
/* Check how many pages the system has */
- if (MmNumberOfPhysicalPages <= (13 * _1MB))
+ if (MmNumberOfPhysicalPages <= ((13 * _1MB) / PAGE_SIZE))
{
/* Set small system */
MmSystemSize = MmSmallSystem;
}
- else if (MmNumberOfPhysicalPages <= (19 * _1MB))
+ else if (MmNumberOfPhysicalPages <= ((19 * _1MB) / PAGE_SIZE))
{
/* Set small system and add 100 pages for the cache */
MmSystemSize = MmSmallSystem;
@@ -1986,6 +2044,14 @@
return FALSE;
}
+ /* Initialize the system cache */
+ //MiInitializeSystemCache(MmSystemCacheWsMinimum, MmAvailablePages);
+
+ /* Update the commit limit */
+ MmTotalCommitLimit = MmAvailablePages;
+ if (MmTotalCommitLimit > 1024) MmTotalCommitLimit -= 1024;
+ MmTotalCommitLimitMaximum = MmTotalCommitLimit;
+
/* Size up paged pool and build the shadow system page directory */
MiBuildPagedPool();
Modified: trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/pagfault.…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c [iso-8859-1] Thu Jul 22 18:26:04 2010
@@ -297,7 +297,9 @@
PMMPDE PointerPde;
MMPTE TempPte;
PETHREAD CurrentThread;
+ PEPROCESS CurrentProcess;
NTSTATUS Status;
+ PMMSUPPORT WorkingSet;
DPRINT("ARM3 FAULT AT: %p\n", Address);
//
@@ -392,7 +394,7 @@
//
// Check for a fault on the page table or hyperspace itself
//
- if ((Address >= (PVOID)PTE_BASE) && (Address <= MmHyperSpaceEnd))
+ if (MI_IS_PAGE_TABLE_OR_HYPER_ADDRESS(Address))
{
//
// This might happen...not sure yet
@@ -415,17 +417,13 @@
return STATUS_ACCESS_VIOLATION;
}
- //
- // Now we must raise to APC_LEVEL and mark the thread as owner
- // We don't actually implement a working set pushlock, so this is only
- // for internal consistency (and blocking APCs)
- //
+ /* In this path, we are using the system working set */
+ CurrentThread = PsGetCurrentThread();
+ WorkingSet = &MmSystemCacheWs;
+
+ /* Acquire it */
KeRaiseIrql(APC_LEVEL, &LockIrql);
- CurrentThread = PsGetCurrentThread();
- KeEnterGuardedRegion();
- ASSERT((CurrentThread->OwnsSystemWorkingSetExclusive == 0) &&
- (CurrentThread->OwnsSystemWorkingSetShared == 0));
- CurrentThread->OwnsSystemWorkingSetExclusive = 1;
+ MiLockWorkingSet(CurrentThread, WorkingSet);
//
// Re-read PTE now that the IRQL has been raised
@@ -444,6 +442,10 @@
DPRINT1("Should NEVER happen on ARM3!!!\n");
return STATUS_ACCESS_VIOLATION;
}
+
+ /* Release the working set */
+ MiUnlockWorkingSet(CurrentThread, WorkingSet);
+ KeLowerIrql(LockIrql);
//
// Otherwise, the PDE was probably invalid, and all is good now
@@ -472,13 +474,10 @@
NULL,
TrapInformation,
NULL);
-
- //
- // Re-enable APCs
- //
+
+ /* Release the working set */
ASSERT(KeAreAllApcsDisabled() == TRUE);
- CurrentThread->OwnsSystemWorkingSetExclusive = 0;
- KeLeaveGuardedRegion();
+ MiUnlockWorkingSet(CurrentThread, WorkingSet);
KeLowerIrql(LockIrql);
//
@@ -488,9 +487,17 @@
return Status;
}
- //
- // DIE DIE DIE
- //
+ /* This is a user fault */
+ CurrentThread = PsGetCurrentThread();
+ CurrentProcess = PsGetCurrentProcess();
+
+ /* Lock the working set */
+ MiLockProcessWorkingSet(CurrentProcess, CurrentThread);
+
+ /* Do something */
+
+ /* Release the working set */
+ MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
DPRINT1("WARNING: USER MODE FAULT IN ARM3???\n");
return STATUS_ACCESS_VIOLATION;
}
Modified: trunk/reactos/ntoskrnl/mm/ARM3/sysldr.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/sysldr.c?…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/sysldr.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/sysldr.c [iso-8859-1] Thu Jul 22 18:26:04 2010
@@ -2230,7 +2230,7 @@
IN PMMPTE LastPte)
{
PVOID ImageBase;
- PETHREAD CurrentThread;
+ PETHREAD CurrentThread = PsGetCurrentThread();
PFN_NUMBER PageCount = 0, PageFrameIndex;
PMMPFN Pfn1;
PAGED_CODE();
@@ -2242,12 +2242,8 @@
/* If this is a large page, it's stuck in physical memory */
if (MI_IS_PHYSICAL_ADDRESS(ImageBase)) return;
- /* We should lock the system working set -- we don't have one yet, so just be consistent */
- CurrentThread = PsGetCurrentThread();
- KeEnterGuardedRegion();
- ASSERT((CurrentThread->OwnsSystemWorkingSetExclusive == 0) &&
- (CurrentThread->OwnsSystemWorkingSetShared == 0));
- CurrentThread->OwnsSystemWorkingSetExclusive = 1;
+ /* Lock the working set */
+ MiLockWorkingSet(CurrentThread, &MmSystemCacheWs);
/* Loop the PTEs */
while (PointerPte <= LastPte)
@@ -2267,10 +2263,8 @@
PointerPte++;
}
- /* Release the working set "lock" */
- ASSERT(KeAreAllApcsDisabled() == TRUE);
- CurrentThread->OwnsSystemWorkingSetExclusive = 0;
- KeLeaveGuardedRegion();
+ /* Release the working set */
+ MiUnlockWorkingSet(CurrentThread, &MmSystemCacheWs);
/* Do we have any driver pages? */
if (PageCount)
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] Thu Jul 22 18:26:04 2010
@@ -37,23 +37,14 @@
OUT PPFN_NUMBER ValidPages)
{
PFN_NUMBER ActualPages = 0;
- PETHREAD CurrentThread;
+ PETHREAD CurrentThread = PsGetCurrentThread();
PMMPFN Pfn1, Pfn2;
PFN_NUMBER PageFrameIndex, PageTableIndex;
- KIRQL OldIrql, LockIrql;
+ KIRQL OldIrql;
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
- /*
- * Now we must raise to APC_LEVEL and mark the thread as owner
- * We don't actually implement a working set pushlock, so this is only
- * for internal consistency (and blocking APCs)
- */
- KeRaiseIrql(APC_LEVEL, &LockIrql);
- CurrentThread = PsGetCurrentThread();
- KeEnterGuardedRegion();
- ASSERT((CurrentThread->OwnsSystemWorkingSetExclusive == 0) &&
- (CurrentThread->OwnsSystemWorkingSetShared == 0));
- CurrentThread->OwnsSystemWorkingSetExclusive = 1;
+ /* Lock the system working set */
+ MiLockWorkingSet(CurrentThread, &MmSystemCacheWs);
/* Loop all pages */
while (PageCount)
@@ -124,11 +115,8 @@
PageCount--;
}
- /* Re-enable APCs */
- ASSERT(KeAreAllApcsDisabled() == TRUE);
- CurrentThread->OwnsSystemWorkingSetExclusive = 0;
- KeLeaveGuardedRegion();
- KeLowerIrql(LockIrql);
+ /* Release the working set */
+ MiUnlockWorkingSet(CurrentThread, &MmSystemCacheWs);
/* Flush the entire TLB */
KeFlushEntireTb(TRUE, TRUE);