diff --git a/reactos/ntoskrnl/include/internal/mm.h b/reactos/ntoskrnl/include/internal/mm.h index 09918a62af6..278b667f40e 100644 --- a/reactos/ntoskrnl/include/internal/mm.h +++ b/reactos/ntoskrnl/include/internal/mm.h @@ -6,6 +6,20 @@ struct _EPROCESS; +/* ReactOS Mm Hacks */ +VOID +FASTCALL +MiSyncForProcessAttach( + IN PKTHREAD NextThread, + IN PEPROCESS Process +); + +VOID +FASTCALL +MiSyncForContextSwitch( + IN PKTHREAD Thread +); + extern PMMSUPPORT MmKernelAddressSpace; extern PFN_COUNT MiFreeSwapPages; extern PFN_COUNT MiUsedSwapPages; diff --git a/reactos/ntoskrnl/ke/i386/thrdini.c b/reactos/ntoskrnl/ke/i386/thrdini.c index 8ee631428d1..cb120d39cb3 100644 --- a/reactos/ntoskrnl/ke/i386/thrdini.c +++ b/reactos/ntoskrnl/ke/i386/thrdini.c @@ -433,6 +433,9 @@ KiSwapContextEntry(IN PKSWITCHFRAME SwitchFrame, /* Get thread pointers */ OldThread = (PKTHREAD)(OldThreadAndApcFlag & ~3); NewThread = Pcr->PrcbData.CurrentThread; + + /* ReactOS Mm Hack */ + MiSyncForContextSwitch(NewThread); /* Get the old thread and set its kernel stack */ OldThread->KernelStack = SwitchFrame; diff --git a/reactos/ntoskrnl/ke/procobj.c b/reactos/ntoskrnl/ke/procobj.c index 7051c8241e1..c8de4f05f43 100644 --- a/reactos/ntoskrnl/ke/procobj.c +++ b/reactos/ntoskrnl/ke/procobj.c @@ -97,6 +97,9 @@ KiAttachProcess(IN PKTHREAD Thread, /* Release lock */ KiReleaseApcLockFromDpcLevel(ApcLock); + /* Make sure that we are in the right page directory (ReactOS Mm Hack) */ + MiSyncForProcessAttach(Thread, (PEPROCESS)Process); + /* Swap Processes */ KiSwapProcess(Process, SavedApcState->Process); @@ -615,6 +618,9 @@ KeDetachProcess(VOID) /* Release lock */ KiReleaseApcLockFromDpcLevel(&ApcLock); + /* Make sure that we are in the right page directory (ReactOS Mm Hack) */ + MiSyncForProcessAttach(Thread, (PEPROCESS)Process); + /* Swap Processes */ KiSwapProcess(Thread->ApcState.Process, Process); @@ -782,6 +788,9 @@ KeUnstackDetachProcess(IN PRKAPC_STATE ApcState) /* Release lock */ KiReleaseApcLockFromDpcLevel(&ApcLock); + /* Make sure that we are in the right page directory (ReactOS Mm Hack) */ + MiSyncForProcessAttach(Thread, (PEPROCESS)Process); + /* Swap Processes */ KiSwapProcess(Thread->ApcState.Process, Process); diff --git a/reactos/ntoskrnl/ke/thrdobj.c b/reactos/ntoskrnl/ke/thrdobj.c index cfccf0de1b2..686fbbbe4ad 100644 --- a/reactos/ntoskrnl/ke/thrdobj.c +++ b/reactos/ntoskrnl/ke/thrdobj.c @@ -856,6 +856,9 @@ KeInitThread(IN OUT PKTHREAD Thread, Thread->StackBase = KernelStack; Thread->StackLimit = (ULONG_PTR)KernelStack - KERNEL_STACK_SIZE; Thread->KernelStackResident = TRUE; + + /* Make sure that we are in the right page directory (ReactOS Mm Hack) */ + MiSyncForProcessAttach(Thread, (PEPROCESS)Process); /* Enter SEH to avoid crashes due to user mode */ Status = STATUS_SUCCESS; diff --git a/reactos/ntoskrnl/ke/thrdschd.c b/reactos/ntoskrnl/ke/thrdschd.c index ee418c7e7ef..b9a063846d3 100644 --- a/reactos/ntoskrnl/ke/thrdschd.c +++ b/reactos/ntoskrnl/ke/thrdschd.c @@ -394,6 +394,9 @@ KiSwapThread(IN PKTHREAD CurrentThread, /* Save the wait IRQL */ WaitIrql = CurrentThread->WaitIrql; + /* REACTOS Mm Hack of Doom */ + MiSyncForContextSwitch(NextThread); + /* Swap contexts */ ApcState = KiSwapContext(WaitIrql, CurrentThread); @@ -790,6 +793,9 @@ NtYieldExecution(VOID) /* Sanity check */ ASSERT(OldIrql <= DISPATCH_LEVEL); + /* REACTOS Mm Hack of Doom */ + MiSyncForContextSwitch(NextThread); + /* Swap to new thread */ KiSwapContext(APC_LEVEL, Thread); Status = STATUS_SUCCESS; diff --git a/reactos/ntoskrnl/mm/i386/page.c b/reactos/ntoskrnl/mm/i386/page.c index 9ebf1bd2b93..2b80afd0c4f 100644 --- a/reactos/ntoskrnl/mm/i386/page.c +++ b/reactos/ntoskrnl/mm/i386/page.c @@ -1028,6 +1028,54 @@ MmGetPhysicalAddress(PVOID vaddr) return p; } +VOID +NTAPI +MmUpdatePageDir(PEPROCESS Process, PVOID Address, ULONG Size) +{ + ULONG StartOffset, EndOffset, Offset; + PULONG Pde; + + // + // Check if the process isn't there anymore + // This is probably a bad sign, since it means the caller is setting cr3 to + // 0 or something... + // + if ((PTE_TO_PFN(Process->Pcb.DirectoryTableBase[0]) == 0) && (Process != PsGetCurrentProcess())) + { + DPRINT1("Process: %16s is dead: %p\n", Process->ImageFileName, Process->Pcb.DirectoryTableBase[0]); + ASSERT(FALSE); + return; + } + + if (Address < MmSystemRangeStart) + { + KeBugCheck(MEMORY_MANAGEMENT); + } + + StartOffset = ADDR_TO_PDE_OFFSET(Address); + EndOffset = ADDR_TO_PDE_OFFSET((PVOID)((ULONG_PTR)Address + Size)); + + if (Process != NULL && Process != PsGetCurrentProcess()) + { + Pde = MmCreateHyperspaceMapping(PTE_TO_PFN(Process->Pcb.DirectoryTableBase[0])); + } + else + { + Pde = (PULONG)PAGEDIRECTORY_MAP; + } + for (Offset = StartOffset; Offset <= EndOffset; Offset++) + { + if (Offset != ADDR_TO_PDE_OFFSET(PAGETABLE_MAP)) + { + InterlockedCompareExchangePte(&Pde[Offset], MmGlobalKernelPageDirectory[Offset], 0); + } + } + if (Pde != (PULONG)PAGEDIRECTORY_MAP) + { + MmDeleteHyperspaceMapping(Pde); + } +} + VOID INIT_FUNCTION NTAPI diff --git a/reactos/ntoskrnl/mm/mmfault.c b/reactos/ntoskrnl/mm/mmfault.c index b8628a8db25..c749f187232 100644 --- a/reactos/ntoskrnl/mm/mmfault.c +++ b/reactos/ntoskrnl/mm/mmfault.c @@ -20,6 +20,41 @@ /* PRIVATE FUNCTIONS **********************************************************/ +VOID +FASTCALL +MiSyncForProcessAttach(IN PKTHREAD Thread, + IN PEPROCESS Process) +{ + PETHREAD Ethread = CONTAINING_RECORD(Thread, ETHREAD, Tcb); + //DPRINT1("Hack sync for process: %p and thread: %p\n", Process, Thread); + //DPRINT1("Thread stack hack: %p %d\n", Thread->StackLimit, Thread->LargeStack); + + /* Hack Sync because Mm is broken */ + MmUpdatePageDir(Process, Ethread, sizeof(ETHREAD)); + MmUpdatePageDir(Process, Ethread->ThreadsProcess, sizeof(EPROCESS)); + MmUpdatePageDir(Process, + (PVOID)Thread->StackLimit, + Thread->LargeStack ? + KERNEL_LARGE_STACK_SIZE : KERNEL_STACK_SIZE); +} + +VOID +FASTCALL +MiSyncForContextSwitch(IN PKTHREAD Thread) +{ + PVOID Process = PsGetCurrentProcess(); + PETHREAD Ethread = CONTAINING_RECORD(Thread, ETHREAD, Tcb); + //DPRINT1("Hack sync for thread: %p and process: %p\n", Thread, Process); + //DPRINT1("Thread stack hack: %p %d\n", Thread->StackLimit, Thread->LargeStack); + + /* Hack Sync because Mm is broken */ + MmUpdatePageDir(Process, Ethread->ThreadsProcess, sizeof(EPROCESS)); + MmUpdatePageDir(Process, + (PVOID)Thread->StackLimit, + Thread->LargeStack ? + KERNEL_LARGE_STACK_SIZE : KERNEL_STACK_SIZE); +} + NTSTATUS NTAPI MmpAccessFault(KPROCESSOR_MODE Mode,