1 /* 2 * COPYRIGHT: GPL, See COPYING in the top level directory 3 * PROJECT: ReactOS kernel 4 * FILE: ntoskrnl/mm/amd64/procsup.c 5 * PURPOSE: Low level memory managment manipulation 6 * 7 * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org) 8 * ReactOS Portable Systems Group 9 */ 10 11 /* INCLUDES *******************************************************************/ 12 13 #include <ntoskrnl.h> 14 #define NDEBUG 15 #include <debug.h> 16 17 #define MODULE_INVOLVED_IN_ARM3 18 #include <mm/ARM3/miarm.h> 19 20 BOOLEAN 21 MiArchCreateProcessAddressSpace( 22 _In_ PEPROCESS Process, 23 _In_ PULONG_PTR DirectoryTableBase) 24 { 25 KIRQL OldIrql; 26 PFN_NUMBER TableBasePfn, HyperPfn, HyperPdPfn, HyperPtPfn; 27 PMMPTE SystemPte; 28 MMPTE TempPte, PdePte; 29 ULONG TableIndex; 30 PMMPTE PageTablePointer; 31 ULONG PageColor; 32 33 /* Non-arch specific code-path allocated those for us */ 34 TableBasePfn = DirectoryTableBase[0] >> PAGE_SHIFT; 35 HyperPfn = DirectoryTableBase[1] >> PAGE_SHIFT; 36 37 /* 38 * Lock PFN database. Try getting zero pages. 39 * If that doesn't work, we take the slow path 40 * outside of the PFN lock. 41 */ 42 OldIrql = MiAcquirePfnLock(); 43 PageColor = MI_GET_NEXT_PROCESS_COLOR(Process); 44 HyperPdPfn = MiRemoveZeroPageSafe(PageColor); 45 if(!HyperPdPfn) 46 { 47 HyperPdPfn = MiRemoveAnyPage(PageColor); 48 MiReleasePfnLock(OldIrql); 49 MiZeroPhysicalPage(HyperPdPfn); 50 OldIrql = MiAcquirePfnLock(); 51 } 52 PageColor = MI_GET_NEXT_PROCESS_COLOR(Process); 53 HyperPtPfn = MiRemoveZeroPageSafe(PageColor); 54 if(!HyperPtPfn) 55 { 56 HyperPtPfn = MiRemoveAnyPage(PageColor); 57 MiReleasePfnLock(OldIrql); 58 MiZeroPhysicalPage(HyperPtPfn); 59 } 60 else 61 { 62 MiReleasePfnLock(OldIrql); 63 } 64 65 /* Get a PTE to map the page directory */ 66 SystemPte = MiReserveSystemPtes(1, SystemPteSpace); 67 if (!SystemPte) 68 return FALSE; 69 70 /* Get its address */ 71 PageTablePointer = MiPteToAddress(SystemPte); 72 73 /* Build the PTE for the page directory and map it */ 74 MI_MAKE_HARDWARE_PTE_KERNEL(&PdePte, SystemPte, MM_READWRITE, TableBasePfn); 75 MI_WRITE_VALID_PTE(SystemPte, PdePte); 76 77 /* Copy the kernel mappings and zero out the rest */ 78 TableIndex = PXE_PER_PAGE / 2; 79 RtlZeroMemory(PageTablePointer, TableIndex * sizeof(MMPTE)); 80 RtlCopyMemory(PageTablePointer + TableIndex, 81 MiAddressToPxe(0) + TableIndex, 82 PAGE_SIZE - TableIndex * sizeof(MMPTE)); 83 84 /* Sanity check */ 85 ASSERT(MiAddressToPxi(MmHyperSpaceEnd) >= TableIndex); 86 87 /* Setup a PTE for the page directory mappings */ 88 TempPte = ValidKernelPte; 89 90 /* Update the self mapping of the PML4 */ 91 TableIndex = MiAddressToPxi((PVOID)PXE_SELFMAP); 92 TempPte.u.Hard.PageFrameNumber = TableBasePfn; 93 PageTablePointer[TableIndex] = TempPte; 94 95 /* Write the PML4 entry for hyperspace */ 96 TableIndex = MiAddressToPxi((PVOID)HYPER_SPACE); 97 TempPte.u.Hard.PageFrameNumber = HyperPfn; 98 PageTablePointer[TableIndex] = TempPte; 99 100 /* Map the hyperspace PDPT to the system PTE */ 101 PdePte.u.Hard.PageFrameNumber = HyperPfn; 102 *SystemPte = PdePte; 103 __invlpg(PageTablePointer); 104 105 /* Write the hyperspace entry for the first PD */ 106 TempPte.u.Hard.PageFrameNumber = HyperPdPfn; 107 PageTablePointer[0] = TempPte; 108 109 /* Map the hyperspace PD to the system PTE */ 110 PdePte.u.Hard.PageFrameNumber = HyperPdPfn; 111 *SystemPte = PdePte; 112 __invlpg(PageTablePointer); 113 114 /* Write the hyperspace entry for the first PT */ 115 TempPte.u.Hard.PageFrameNumber = HyperPtPfn; 116 PageTablePointer[0] = TempPte; 117 118 /* Map the hyperspace PT to the system PTE */ 119 PdePte.u.Hard.PageFrameNumber = HyperPtPfn; 120 *SystemPte = PdePte; 121 __invlpg(PageTablePointer); 122 123 /* Write the hyperspace PTE for the working set list index */ 124 TempPte.u.Hard.PageFrameNumber = Process->WorkingSetPage; 125 TableIndex = MiAddressToPti(MmWorkingSetList); 126 PageTablePointer[TableIndex] = TempPte; 127 128 /* Release the system PTE */ 129 MiReleaseSystemPtes(SystemPte, 1, SystemPteSpace); 130 131 return TRUE; 132 } 133