diff --git a/reactos/ntoskrnl/mm/ARM3/mminit.c b/reactos/ntoskrnl/mm/ARM3/mminit.c index 524f20e822f..4ecb18f5cc7 100644 --- a/reactos/ntoskrnl/mm/ARM3/mminit.c +++ b/reactos/ntoskrnl/mm/ARM3/mminit.c @@ -1605,7 +1605,10 @@ MiBuildPagedPool(VOID) KIRQL OldIrql; SIZE_T Size; ULONG BitMapSize; -#if (_MI_PAGING_LEVELS == 2) +#if (_MI_PAGING_LEVELS >= 3) + MMPPE TempPpe = ValidKernelPpe; + PMMPPE PointerPpe; +#elif (_MI_PAGING_LEVELS == 2) MMPTE TempPte = ValidKernelPte; // @@ -1681,18 +1684,33 @@ MiBuildPagedPool(VOID) MmPagedPoolEnd = (PVOID)(((ULONG_PTR)MmPagedPoolStart + MmSizeOfPagedPoolInBytes) - 1); + // + // Lock the PFN database + // + OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock); + +#if (_MI_PAGING_LEVELS >= 3) + /* On these systems, there's no double-mapping, so instead, the PPEs + * are setup to span the entire paged pool area, so there's no need for the + * system PD */ + for (PointerPpe = MiAddressToPpe(MmPagedPoolStart); + PointerPpe <= MiAddressToPpe(MmPagedPoolEnd); + PointerPpe++) + { + /* Check if the PPE is already valid */ + if (!PointerPpe->u.Hard.Valid) + { + /* It is not, so map a fresh zeroed page */ + TempPpe.u.Hard.PageFrameNumber = MiRemoveZeroPage(0); + MI_WRITE_VALID_PPE(PointerPpe, TempPpe); + } + } +#endif + // // So now get the PDE for paged pool and zero it out // PointerPde = MiAddressToPde(MmPagedPoolStart); - -#if (_MI_PAGING_LEVELS >= 3) - /* On these systems, there's no double-mapping, so instead, the PPE and PXEs - * are setup to span the entire paged pool area, so there's no need for the - * system PD */ - ASSERT(FALSE); -#endif - RtlZeroMemory(PointerPde, (1 + MiAddressToPde(MmPagedPoolEnd) - PointerPde) * sizeof(MMPDE)); @@ -1703,11 +1721,6 @@ MiBuildPagedPool(VOID) MmPagedPoolInfo.FirstPteForPagedPool = PointerPte; MmPagedPoolInfo.LastPteForPagedPool = MiAddressToPte(MmPagedPoolEnd); - // - // Lock the PFN database - // - OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock); - /* Allocate a page and map the first paged pool PDE */ MI_SET_USAGE(MI_USAGE_PAGED_POOL); MI_SET_PROCESS2("Kernel"); @@ -1717,7 +1730,11 @@ MiBuildPagedPool(VOID) #if (_MI_PAGING_LEVELS >= 3) /* Use the PPE of MmPagedPoolStart that was setup above */ // Bla = PFN_FROM_PTE(PpeAddress(MmPagedPool...)); - ASSERT(FALSE); + + /* Initialize the PFN entry for it */ + MiInitializePfnForOtherProcess(PageFrameIndex, + (PMMPTE)PointerPde, + PFN_FROM_PTE(MiAddressToPpe(MmPagedPoolStart))); #else /* Do it this way */ // Bla = MmSystemPageDirectory[(PointerPde - (PMMPTE)PDE_BASE) / PDE_COUNT] diff --git a/reactos/ntoskrnl/mm/ARM3/pagfault.c b/reactos/ntoskrnl/mm/ARM3/pagfault.c index 63372447fcc..a7c1841d63d 100644 --- a/reactos/ntoskrnl/mm/ARM3/pagfault.c +++ b/reactos/ntoskrnl/mm/ARM3/pagfault.c @@ -637,8 +637,15 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction, IN PVOID TrapInformation) { KIRQL OldIrql = KeGetCurrentIrql(), LockIrql; - PMMPTE PointerPte, ProtoPte = NULL; - PMMPDE PointerPde; + PMMPTE ProtoPte = NULL; + PMMPTE PointerPte = MiAddressToPte(Address); + PMMPDE PointerPde = MiAddressToPde(Address); +#if (_MI_PAGING_LEVELS >= 3) + PMMPDE PointerPpe = MiAddressToPpe(Address); +#if (_MI_PAGING_LEVELS == 4) + PMMPDE PointerPxe = MiAddressToPxe(Address); +#endif +#endif MMPTE TempPte; PETHREAD CurrentThread; PEPROCESS CurrentProcess; @@ -648,17 +655,8 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction, PMMVAD Vad; PFN_NUMBER PageFrameIndex; ULONG Color; - DPRINT("ARM3 FAULT AT: %p\n", Address); - // - // Get the PTE and PDE - // - PointerPte = MiAddressToPte(Address); - PointerPde = MiAddressToPde(Address); -#if (_MI_PAGING_LEVELS >= 3) - /* We need the PPE and PXE addresses */ - ASSERT(FALSE); -#endif + DPRINT("ARM3 FAULT AT: %p\n", Address); // // Check for dispatch-level snafu @@ -675,7 +673,7 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction, } // - // Check for kernel fault + // Check for kernel fault address // while (Address >= MmSystemRangeStart) { @@ -685,8 +683,18 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction, if (Mode == UserMode) return STATUS_ACCESS_VIOLATION; #if (_MI_PAGING_LEVELS >= 3) - /* Need to check PXE and PDE validity */ - ASSERT(FALSE); + if ( +#if (_MI_PAGING_LEVELS == 4) + (PointerPxe->u.Hard.Valid == 0) || +#endif + (PointerPpe->u.Hard.Valid == 0)) + { + KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA, + (ULONG_PTR)Address, + StoreInstruction, + (ULONG_PTR)TrapInformation, + 2); + } #endif // @@ -871,18 +879,21 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction, return Status; } - /* This is a user fault */ +#if (_MI_PAGING_LEVELS == 4) + /* On these systems we have PXEs and PPEs ready for everything we need */ + if (PointerPxe->u.Hard.Valid == 0) return STATUS_ACCESS_VIOLATION; +#endif +#if (_MI_PAGING_LEVELS >= 3) + if (PointerPpe->u.Hard.Valid == 0) return STATUS_ACCESS_VIOLATION; +#endif + + /* This is a user fault (<- And this is a lie!) */ CurrentThread = PsGetCurrentThread(); CurrentProcess = PsGetCurrentProcess(); /* Lock the working set */ MiLockProcessWorkingSet(CurrentProcess, CurrentThread); -#if (_MI_PAGING_LEVELS >= 3) - /* Need to check/handle PPE and PXE validity too */ - ASSERT(FALSE); -#endif - /* First things first, is the PDE valid? */ ASSERT(PointerPde->u.Hard.LargePage == 0); if (PointerPde->u.Hard.Valid == 0) @@ -916,10 +927,6 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction, #endif /* We should come back with APCs enabled, and with a valid PDE */ ASSERT(KeAreAllApcsDisabled() == TRUE); -#if (_MI_PAGING_LEVELS >= 3) - /* Need to check/handle PPE and PXE validity too */ - ASSERT(FALSE); -#endif ASSERT(PointerPde->u.Hard.Valid == 1); }