- Implemented a kernel mapping region which is process local. This mapping can be used to map temporary memory pages from other process's like pde's/pte's. It is also used to make a copy of a page or to clean a page. Modified: trunk/reactos/ntoskrnl/Makefile Modified: trunk/reactos/ntoskrnl/include/internal/mm.h Modified: trunk/reactos/ntoskrnl/ke/i386/multiboot.S Modified: trunk/reactos/ntoskrnl/mm/freelist.c Modified: trunk/reactos/ntoskrnl/mm/i386/page.c Modified: trunk/reactos/ntoskrnl/mm/kmap.c Modified: trunk/reactos/ntoskrnl/mm/mminit.c Modified: trunk/reactos/ntoskrnl/mm/section.c _____
Modified: trunk/reactos/ntoskrnl/Makefile --- trunk/reactos/ntoskrnl/Makefile 2005-01-25 22:36:28 UTC (rev 13287) +++ trunk/reactos/ntoskrnl/Makefile 2005-01-25 22:50:47 UTC (rev 13288) @@ -148,7 +148,6 @@
mm/region.o \ mm/rmap.o \ mm/section.o \ - mm/slab.o \ mm/verifier.o \ mm/virtual.o \ mm/wset.o _____
Modified: trunk/reactos/ntoskrnl/include/internal/mm.h --- trunk/reactos/ntoskrnl/include/internal/mm.h 2005-01-25 22:36:28 UTC (rev 13287) +++ trunk/reactos/ntoskrnl/include/internal/mm.h 2005-01-25 22:50:47 UTC (rev 13288) @@ -551,8 +551,6 @@
VOID ExUnmapPage(PVOID Addr);
-VOID MiInitKernelMap(VOID); - PVOID ExAllocatePageWithPhysPage(PFN_TYPE Page);
NTSTATUS MiCopyFromUserPage(PFN_TYPE Page, PVOID SourceAddress); @@ -649,6 +647,12 @@
/* i386/page.c *********************************************************/
+PVOID MmCreateHyperspaceMapping(PFN_TYPE Page); + +PFN_TYPE MmChangeHyperspaceMapping(PVOID Address, PFN_TYPE Page); + +PFN_TYPE MmDeleteHyperspaceMapping(PVOID Address); + NTSTATUS MmCreateVirtualMappingForKernel(PVOID Address, ULONG flProtect, PPFN_TYPE Pages, _____
Modified: trunk/reactos/ntoskrnl/ke/i386/multiboot.S --- trunk/reactos/ntoskrnl/ke/i386/multiboot.S 2005-01-25 22:36:28 UTC (rev 13287) +++ trunk/reactos/ntoskrnl/ke/i386/multiboot.S 2005-01-25 22:50:47 UTC (rev 13288) @@ -114,7 +114,7 @@
movl $(V2P(kernel_pagetable+4096) + 0x3), ((KERNEL_BASE >> 20) + 4)(%esi)
movl $(V2P(startup_pagedirectory) + 0x3), 0xF00(%esi) - movl $(V2P(kernelmap_pagetable) + 0x3), 0xF0C(%esi) + movl $(V2P(hyperspace_pagetable) + 0x3), 0xF08(%esi) #ifdef CONFIG_SMP movl $(V2P(apic_pagetable) + 0x3), 0xFEC(%esi) #endif /* CONFIG_SMP */ @@ -351,8 +351,9 @@ kernel_pagetable: .fill 2*4096, 1, 0
-kernelmap_pagetable: +hyperspace_pagetable: .fill 4096, 1, 0 + _pae_pagedirtable: .fill 4096, 1, 0 #ifdef CONFIG_SMP _____
Modified: trunk/reactos/ntoskrnl/mm/freelist.c --- trunk/reactos/ntoskrnl/mm/freelist.c 2005-01-25 22:36:28 UTC (rev 13287) +++ trunk/reactos/ntoskrnl/mm/freelist.c 2005-01-25 22:50:47 UTC (rev 13288) @@ -56,9 +56,10 @@
static LIST_ENTRY FreeUnzeroedPageListHead; static LIST_ENTRY BiosPageListHead;
-static HANDLE ZeroPageThreadHandle; +static PETHREAD ZeroPageThread; static CLIENT_ID ZeroPageThreadId; static KEVENT ZeroPageThreadEvent; +static BOOLEAN ZeroPageThreadShouldTerminate = FALSE;
static ULONG UnzeroedPageCount = 0;
@@ -381,6 +382,11 @@ KEBUGCHECK(0); } } + else + { + /* Setting the page protection is necessary to set the global bit on IA32 */ + MmSetPageProtect(NULL, Address, PAGE_READWRITE); + } memset(Address, 0, PAGE_SIZE);
start = ((ULONG_PTR)Address - (ULONG_PTR)MmPageArray) / sizeof(PHYSICAL_PAGE); @@ -1046,7 +1052,7 @@ return NumberOfPagesFound; }
-NTSTATUS STDCALL +VOID STDCALL MmZeroPageThreadMain(PVOID Ignored) { NTSTATUS Status; @@ -1054,7 +1060,6 @@ PLIST_ENTRY ListEntry; PPHYSICAL_PAGE PageDescriptor; PFN_TYPE Pfn; - static PVOID Address = NULL; ULONG Count;
while(1) @@ -1068,9 +1073,14 @@ { DbgPrint("ZeroPageThread: Wait failed\n"); KEBUGCHECK(0); - return(STATUS_UNSUCCESSFUL); + return; }
+ if (ZeroPageThreadShouldTerminate) + { + DbgPrint("ZeroPageThread: Terminating\n"); + return; + } Count = 0; KeAcquireSpinLock(&PageListLock, &oldIrql); while (!IsListEmpty(&FreeUnzeroedPageListHead)) @@ -1081,27 +1091,9 @@ /* We set the page to used, because MmCreateVirtualMapping failed with unused pages */ PageDescriptor->Flags.Type = MM_PHYSICAL_PAGE_USED; KeReleaseSpinLock(&PageListLock, oldIrql); - Count++; Pfn = PageDescriptor - MmPageArray; - if (Address == NULL) - { - Address = ExAllocatePageWithPhysPage(Pfn); - } - else - { - Status = MmCreateVirtualMapping(NULL, - Address, - PAGE_READWRITE | PAGE_SYSTEM, - &Pfn, - 1); - if (!NT_SUCCESS(Status)) - { - DbgPrint("Unable to create virtual mapping\n"); - KEBUGCHECK(0); - } - } - memset(Address, 0, PAGE_SIZE); - MmDeleteVirtualMapping(NULL, (PVOID)Address, FALSE, NULL, NULL); + Status = MiZeroPage(Pfn); + KeAcquireSpinLock(&PageListLock, &oldIrql); if (PageDescriptor->MapCount != 0) { @@ -1110,7 +1102,17 @@ } PageDescriptor->Flags.Zero = 1; PageDescriptor->Flags.Type = MM_PHYSICAL_PAGE_FREE; - InsertHeadList(&FreeZeroedPageListHead, ListEntry); + if (NT_SUCCESS(Status)) + { + InsertHeadList(&FreeZeroedPageListHead, ListEntry); + Count++; + } + else + { + InsertHeadList(&FreeUnzeroedPageListHead, ListEntry); + UnzeroedPageCount++; + } + } DPRINT("Zeroed %d pages.\n", Count); KeResetEvent(&ZeroPageThreadEvent); @@ -1121,28 +1123,36 @@ NTSTATUS INIT_FUNCTION MmInitZeroPageThread(VOID) { - KPRIORITY Priority; NTSTATUS Status; - - Status = PsCreateSystemThread(&ZeroPageThreadHandle, + HANDLE ThreadHandle; + + ZeroPageThreadShouldTerminate = FALSE; + Status = PsCreateSystemThread(&ThreadHandle, THREAD_ALL_ACCESS, NULL, NULL, &ZeroPageThreadId, - (PKSTART_ROUTINE) MmZeroPageThreadMain, + MmZeroPageThreadMain, NULL); if (!NT_SUCCESS(Status)) { - return(Status); + KEBUGCHECK(0); }
- Priority = 1; - NtSetInformationThread(ZeroPageThreadHandle, - ThreadPriority, - &Priority, - sizeof(Priority)); + Status = ObReferenceObjectByHandle(ThreadHandle, + THREAD_ALL_ACCESS, + PsThreadType, + KernelMode, + (PVOID*)&ZeroPageThread, + NULL); + if (!NT_SUCCESS(Status)) + { + KEBUGCHECK(0); + }
- return(STATUS_SUCCESS); + KeSetPriorityThread(&ZeroPageThread->Tcb, LOW_PRIORITY); + NtClose(ThreadHandle); + return STATUS_SUCCESS; }
/* EOF */ _____
Modified: trunk/reactos/ntoskrnl/mm/i386/page.c --- trunk/reactos/ntoskrnl/mm/i386/page.c 2005-01-25 22:36:28 UTC (rev 13287) +++ trunk/reactos/ntoskrnl/mm/i386/page.c 2005-01-25 22:50:47 UTC (rev 13288) @@ -52,11 +52,14 @@
#define PA_ACCESSED (1 << PA_BIT_ACCESSED) #define PA_GLOBAL (1 << PA_BIT_GLOBAL)
-#define PAGETABLE_MAP (0xf0000000) -#define PAGEDIRECTORY_MAP (0xf0000000 + (PAGETABLE_MAP / (1024))) +#define PAGETABLE_MAP (0xf0000000) +#define PAGEDIRECTORY_MAP (0xf0000000 + (PAGETABLE_MAP / (1024)))
#define PAE_PAGEDIRECTORY_MAP (0xf0000000 + (PAGETABLE_MAP / (512)))
+#define HYPERSPACE (0xf0800000) +#define IS_HYPERSPACE(v) (((ULONG)(v) >= 0xF0800000 && (ULONG)(v) < 0xF0C00000)) + ULONG MmGlobalKernelPageDirectory[1024]; ULONGLONG MmGlobalKernelPageDirectoryForPAE[2048];
@@ -237,12 +240,12 @@ PULONGLONG Pde; ULONG k;
- PageDirTable = (PULONGLONG)ExAllocatePageWithPhysPage(Process->Pcb.DirectoryTableBase.Q uadPart >> PAGE_SHIFT); + PageDirTable = (PULONGLONG)MmCreateHyperspaceMapping(PAE_PTE_TO_PFN(Process->Pcb.Direct oryTableBase.QuadPart)); for (i = 0; i < 4; i++) { + PageDir = (PULONGLONG)MmCreateHyperspaceMapping(PAE_PTE_TO_PFN(PageDirTable[i])); if (i < PAE_ADDR_TO_PDTE_OFFSET(KERNEL_BASE)) { - PageDir = (PULONGLONG)ExAllocatePageWithPhysPage(PageDirTable[i] >> PAGE_SHIFT); for (j = 0; j < 512; j++) { if (PageDir[j] != 0LL) @@ -251,7 +254,7 @@ Process->UniqueProcessId, (i * 512 + j) * 512 * PAGE_SIZE, (i * 512 + j + 1) * 512 * PAGE_SIZE - 1,
Process->AddressSpace.PageTableRefCountTable[i*512 + j]); - Pde = ExAllocatePageWithPhysPage(PageDir[j] >> PAGE_SHIFT); + Pde = MmCreateHyperspaceMapping(PAE_PTE_TO_PFN(PageDir[j])); for (k = 0; k < 512; k++) { if(Pde[k] != 0) @@ -268,21 +271,27 @@ } } } - ExUnmapPage(Pde); + MmDeleteHyperspaceMapping(Pde); MmReleasePageMemoryConsumer(MC_NPPOOL, PAE_PTE_TO_PFN(PageDir[j])); } } - ExUnmapPage(PageDir); } - MmReleasePageMemoryConsumer(MC_NPPOOL, PageDirTable[i] >> PAGE_SHIFT); + else + { + MmReleasePageMemoryConsumer(MC_NPPOOL, PAE_PTE_TO_PFN(PageDir[PAE_ADDR_TO_PDE_PAGE_OFFSET(HYPERSPACE)])); + MmReleasePageMemoryConsumer(MC_NPPOOL, PAE_PTE_TO_PFN(PageDir[PAE_ADDR_TO_PDE_PAGE_OFFSET(HYPERSPACE)+1])); + } + MmDeleteHyperspaceMapping(PageDir); + MmReleasePageMemoryConsumer(MC_NPPOOL, PAE_PTE_TO_PFN(PageDirTable[i])); } - ExUnmapPage((PVOID)PageDirTable); + MmDeleteHyperspaceMapping((PVOID)PageDirTable); + MmReleasePageMemoryConsumer(MC_NPPOOL, PAE_PTE_TO_PFN(Process->Pcb.DirectoryTableBase.QuadPart)); } else { PULONG Pde; PULONG PageDir; - PageDir = ExAllocatePageWithPhysPage(Process->Pcb.DirectoryTableBase.QuadPart >> PAGE_SHIFT); + PageDir = MmCreateHyperspaceMapping(PTE_TO_PFN(Process->Pcb.DirectoryTableBase.u.L owPart)); for (i = 0; i < ADDR_TO_PDE_OFFSET(KERNEL_BASE); i++) { if (PageDir[i] != 0) @@ -290,7 +299,7 @@ DPRINT1("Pde for %08x - %08x is not freed, RefCount %d\n", i * 4 * 1024 * 1024, (i + 1) * 4 * 1024 * 1024 - 1, Process->AddressSpace.PageTableRefCountTable[i]); - Pde = ExAllocatePageWithPhysPage(PageDir[i] >> PAGE_SHIFT); + Pde = MmCreateHyperspaceMapping(PTE_TO_PFN(PageDir[i])); for (j = 0; j < 1024; j++) { if(Pde[j] != 0) @@ -307,14 +316,15 @@ } } } - ExUnmapPage(Pde); + MmDeleteHyperspaceMapping(Pde); MmReleasePageMemoryConsumer(MC_NPPOOL, PTE_TO_PFN(PageDir[i])); } } - ExUnmapPage(PageDir); + MmReleasePageMemoryConsumer(MC_NPPOOL, PTE_TO_PFN(PageDir[ADDR_TO_PDE_OFFSET(HYPERSPACE)])); + MmDeleteHyperspaceMapping(PageDir); + MmReleasePageMemoryConsumer(MC_NPPOOL, PTE_TO_PFN(Process->Pcb.DirectoryTableBase.u.LowPart)); }
- MmReleasePageMemoryConsumer(MC_NPPOOL, Process->Pcb.DirectoryTableBase.QuadPart >> PAGE_SHIFT); #if defined(__GNUC__)
Process->Pcb.DirectoryTableBase.QuadPart = 0LL; @@ -329,87 +339,75 @@
NTSTATUS MmCopyMmInfo(PEPROCESS Src, PEPROCESS Dest) { - PHYSICAL_ADDRESS PhysPageDirectory; PKPROCESS KProcess = &Dest->Pcb; - + NTSTATUS Status; + ULONG i, j; + PFN_TYPE Pfn[7]; + ULONG Count; + DPRINT("MmCopyMmInfo(Src %x, Dest %x)\n", Src, Dest);
+ Count = Ke386Pae ? 7 : 2; + + for (i = 0; i < Count; i++) + { + Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn[i]); + if (!NT_SUCCESS(Status)) + { + for (j = 0; j < i; j++) + { + MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn[j]); + } + return Status; + } + } + if (Ke386Pae) { PULONGLONG PageDirTable; PULONGLONG PageDir; - PFN_TYPE Pfn[4]; - ULONG i, j; - NTSTATUS Status;
- PageDirTable = ExAllocatePage(); - if (PageDirTable == NULL) - { - return STATUS_UNSUCCESSFUL; - } - PhysPageDirectory = MmGetPhysicalAddress(PageDirTable); - + PageDirTable = MmCreateHyperspaceMapping(Pfn[0]); for (i = 0; i < 4; i++) { - Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn[i]); - if (!NT_SUCCESS(Status)) - { - for (j = 0; j < i; j++) - { - MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn[j]); - } - ExUnmapPage(PageDirTable); - MmReleasePageMemoryConsumer(MC_NPPOOL, PhysPageDirectory.QuadPart >> PAGE_SHIFT); - return Status; - } - PageDirTable[i] = (Pfn[i] << PAGE_SHIFT) | PA_PRESENT; + PageDirTable[i] = PAE_PFN_TO_PTE(Pfn[1+i]) | PA_PRESENT; } - ExUnmapPage(PageDirTable); + MmDeleteHyperspaceMapping(PageDirTable); for (i = PAE_ADDR_TO_PDTE_OFFSET(KERNEL_BASE); i < 4; i++) { - PageDir = (PULONGLONG)ExAllocatePageWithPhysPage(Pfn[i]); - if (PageDir == NULL) - { - for (j = 0; j < 4; j++) - { - MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn[j]); - } - ExUnmapPage(PageDirTable); - MmReleasePageMemoryConsumer(MC_NPPOOL, PhysPageDirectory.QuadPart >> PAGE_SHIFT); - return STATUS_UNSUCCESSFUL; - } + PageDir = (PULONGLONG)MmCreateHyperspaceMapping(Pfn[i+1]); memcpy(PageDir, &MmGlobalKernelPageDirectoryForPAE[i * 512], 512 * sizeof(ULONGLONG)); if (PAE_ADDR_TO_PDTE_OFFSET(PAGETABLE_MAP) == i) { for (j = 0; j < 4; j++) { - PageDir[PAE_ADDR_TO_PDE_PAGE_OFFSET(PAGETABLE_MAP) + j] = (Pfn[j] << PAGE_SHIFT) | PA_PRESENT | PA_READWRITE; + PageDir[PAE_ADDR_TO_PDE_PAGE_OFFSET(PAGETABLE_MAP) + j] = PAE_PFN_TO_PTE(Pfn[1+j]) | PA_PRESENT | PA_READWRITE; } } - ExUnmapPage(PageDir); + if (PAE_ADDR_TO_PDTE_OFFSET(HYPERSPACE) == i) + { + PageDir[PAE_ADDR_TO_PDE_PAGE_OFFSET(HYPERSPACE)] = PAE_PFN_TO_PTE(Pfn[5]) | PA_PRESENT | PA_READWRITE; + PageDir[PAE_ADDR_TO_PDE_PAGE_OFFSET(HYPERSPACE)+1] = PAE_PFN_TO_PTE(Pfn[6]) | PA_PRESENT | PA_READWRITE; + } + MmDeleteHyperspaceMapping(PageDir); } } else { PULONG PageDirectory; - PageDirectory = ExAllocatePage(); - if (PageDirectory == NULL) - { - return(STATUS_UNSUCCESSFUL); - } - PhysPageDirectory = MmGetPhysicalAddress(PageDirectory); + PageDirectory = MmCreateHyperspaceMapping(Pfn[0]);
memcpy(PageDirectory + ADDR_TO_PDE_OFFSET(KERNEL_BASE), MmGlobalKernelPageDirectory + ADDR_TO_PDE_OFFSET(KERNEL_BASE), (1024 - ADDR_TO_PDE_OFFSET(KERNEL_BASE)) * sizeof(ULONG));
- DPRINT("Addr %x\n",PAGETABLE_MAP / (4*1024*1024)); - PageDirectory[PAGETABLE_MAP / (4*1024*1024)] = - PhysPageDirectory.u.LowPart | PA_PRESENT | PA_READWRITE; + DPRINT("Addr %x\n",ADDR_TO_PDE_OFFSET(PAGETABLE_MAP)); + PageDirectory[ADDR_TO_PDE_OFFSET(PAGETABLE_MAP)] = PFN_TO_PTE(Pfn[0]) | PA_PRESENT | PA_READWRITE; + PageDirectory[ADDR_TO_PDE_OFFSET(HYPERSPACE)] = PFN_TO_PTE(Pfn[1]) | PA_PRESENT | PA_READWRITE;
- ExUnmapPage(PageDirectory); + MmDeleteHyperspaceMapping(PageDirectory); } - KProcess->DirectoryTableBase = PhysPageDirectory; + KProcess->DirectoryTableBase.QuadPart = PFN_TO_PTE(Pfn[0]); DPRINT("Finished MmCopyMmInfo()\n"); return(STATUS_SUCCESS); } @@ -524,13 +522,13 @@ } if (Address < (PVOID)KERNEL_BASE && Process && Process != PsGetCurrentProcess()) { - PageDirTable = ExAllocatePageWithPhysPage(Process->Pcb.DirectoryTableBase.QuadPart >> PAGE_SHIFT); + PageDirTable = MmCreateHyperspaceMapping(PAE_PTE_TO_PFN(Process->Pcb.DirectoryTableBase .QuadPart)); if (PageDirTable == NULL) { KEBUGCHECK(0); } - PageDir = ExAllocatePageWithPhysPage(PageDirTable[PAE_ADDR_TO_PDTE_OFFSET(Address) ] >> PAGE_SHIFT); - ExUnmapPage(PageDirTable); + PageDir = MmCreateHyperspaceMapping(PAE_PTE_TO_PFN(PageDirTable[PAE_ADDR_TO_PDTE_O FFSET(Address)])); + MmDeleteHyperspaceMapping(PageDirTable); if (PageDir == NULL) { KEBUGCHECK(0); @@ -541,7 +539,7 @@ { if (Create == FALSE) { - ExUnmapPage(PageDir); + MmDeleteHyperspaceMapping(PageDir); return NULL; } Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn); @@ -561,8 +559,8 @@ { Pfn = PAE_PTE_TO_PFN(Entry); } - ExUnmapPage(PageDir); - Pt = ExAllocatePageWithPhysPage(Pfn); + MmDeleteHyperspaceMapping(PageDir); + Pt = MmCreateHyperspaceMapping(Pfn); if (Pt == NULL) { KEBUGCHECK(0); @@ -630,7 +628,7 @@
if (Address < (PVOID)KERNEL_BASE && Process && Process != PsGetCurrentProcess()) { - PageDir = ExAllocatePageWithPhysPage(Process->Pcb.DirectoryTableBase.QuadPart >> PAGE_SHIFT); + PageDir = MmCreateHyperspaceMapping(PTE_TO_PFN(Process->Pcb.DirectoryTableBase.Qua dPart)); if (PageDir == NULL) { KEBUGCHECK(0); @@ -639,7 +637,7 @@ { if (Create == FALSE) { - ExUnmapPage(PageDir); + MmDeleteHyperspaceMapping(PageDir); return NULL; } Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn); @@ -658,8 +656,8 @@ { Pfn = PTE_TO_PFN(PageDir[PdeOffset]); } - ExUnmapPage(PageDir); - Pt = ExAllocatePageWithPhysPage(Pfn); + MmDeleteHyperspaceMapping(PageDir); + Pt = MmCreateHyperspaceMapping(Pfn); if (Pt == NULL) { KEBUGCHECK(0); @@ -733,7 +731,7 @@ } if (Pt) { - ExUnmapPage((PVOID)PAGE_ROUND_DOWN(Pt)); + MmDeleteHyperspaceMapping((PVOID)PAGE_ROUND_DOWN(Pt)); } return FALSE; } @@ -1907,7 +1905,7 @@ { if (!MmIsUsablePage(Pages[i])) { - DPRINT1("Page at address %x not usable\n", Pages[i] << PAGE_SHIFT); + DPRINT1("Page at address %x not usable\n", PFN_TO_PTE(Pages[i])); KEBUGCHECK(0); } } @@ -2075,6 +2073,176 @@ return p; }
+PVOID +MmCreateHyperspaceMapping(PFN_TYPE Page) +{ + PVOID Address; + LONG i; + + if (Ke386Pae) + { + ULONGLONG Entry; + ULONGLONG ZeroEntry = 0LL; + PULONGLONG Pte; + + Entry = PFN_TO_PTE(Page) | PA_PRESENT | PA_READWRITE; + Pte = PAE_ADDR_TO_PTE(HYPERSPACE) + Page % 1024; + + if (Page & 1024) + { + for (i = Page %1024; i < 1024; i++, Pte++) + { + if (0LL == ExfInterlockedCompareExchange64UL(Pte, &Entry, &ZeroEntry)) + { + break; + } + } + if (i >= 1024) + { + Pte = PAE_ADDR_TO_PTE(HYPERSPACE); + for (i = 0; i < Page % 1024; i++, Pte++) + { + if (0LL == ExfInterlockedCompareExchange64UL(Pte, &Entry, &ZeroEntry)) + { + break; + } + } + if (i >= Page % 1024) + { + KEBUGCHECK(0); + } + } + } + else + { + for (i = Page %1024; i >= 0; i--, Pte--) + { + if (0LL == ExfInterlockedCompareExchange64UL(Pte, &Entry, &ZeroEntry)) + { + break; + } + } + if (i < 0) + { + Pte = PAE_ADDR_TO_PTE(HYPERSPACE) + 1023; + for (i = 1023; i > Page % 1024; i--, Pte--) + { + if (0LL == ExfInterlockedCompareExchange64UL(Pte, &Entry, &ZeroEntry)) + { + break; + } + } + if (i <= Page % 1024) + { + KEBUGCHECK(0); + } + } + } + } + else + { + ULONG Entry; + PULONG Pte; + Entry = PFN_TO_PTE(Page) | PA_PRESENT | PA_READWRITE; + Pte = ADDR_TO_PTE(HYPERSPACE) + Page % 1024; + if (Page & 1024) + { + for (i = Page % 1024; i < 1024; i++, Pte++) + { + if (0 == InterlockedCompareExchange((PLONG)Pte, (LONG)Entry, 0)) + { + break; + } + } + if (i >= 1024) + { + Pte = ADDR_TO_PTE(HYPERSPACE); + for (i = 0; i < Page % 1024; i++, Pte++) + { + if (0 == InterlockedCompareExchange((PLONG)Pte, (LONG)Entry, 0)) + { + break; + } + } + if (i >= Page % 1024) + { + KEBUGCHECK(0); + } + } + } + else + { + for (i = Page % 1024; i >= 0; i--, Pte--) + { + if (0 == InterlockedCompareExchange((PLONG)Pte, (LONG)Entry, 0)) + { + break; + } + } + if (i < 0) + { + Pte = ADDR_TO_PTE(HYPERSPACE) + 1023; + for (i = 1023; i > Page % 1024; i--, Pte--) + { + if (0 == InterlockedCompareExchange((PLONG)Pte, (LONG)Entry, 0)) + { + break; + } + } + if (i <= Page % 1024) + { + KEBUGCHECK(0); + } + } + } + } + Address = (PVOID)HYPERSPACE + i * PAGE_SIZE; + FLUSH_TLB_ONE(Address); + return Address; +} + +PFN_TYPE +MmChangeHyperspaceMapping(PVOID Address, PFN_TYPE NewPage) +{ + PFN_TYPE Pfn; + ASSERT (IS_HYPERSPACE(Address)); + if (Ke386Pae) + { + ULONGLONG Entry = PAE_PFN_TO_PTE(NewPage) | PA_PRESENT | PA_READWRITE; + Entry = (ULONG)ExfpInterlockedExchange64UL(PAE_ADDR_TO_PTE(Address), &Entry); + Pfn = PAE_PTE_TO_PFN(Entry); + } + else + { + ULONG Entry; + Entry = InterlockedExchange(ADDR_TO_PTE(Address), PFN_TO_PTE(NewPage) | PA_PRESENT | PA_READWRITE); + Pfn = PTE_TO_PFN(Entry); + } + FLUSH_TLB_ONE(Address); + return Pfn; +} + +PFN_TYPE +MmDeleteHyperspaceMapping(PVOID Address) +{ + PFN_TYPE Pfn; + ASSERT (IS_HYPERSPACE(Address)); + if (Ke386Pae) + { + ULONGLONG Entry = 0LL; + Entry = (ULONG)ExfpInterlockedExchange64UL(PAE_ADDR_TO_PTE(Address), &Entry); + Pfn = PAE_PTE_TO_PFN(Entry); + } + else + { + ULONG Entry; + Entry = InterlockedExchange(ADDR_TO_PTE(Address), 0); + Pfn = PTE_TO_PFN(Entry); + } + FLUSH_TLB_ONE(Address); + return Pfn; +} + VOID MmUpdatePageDir(PEPROCESS Process, PVOID Address, ULONG Size) { ULONG StartOffset, EndOffset, Offset; @@ -2111,9 +2279,9 @@
if (Process != NULL && Process != PsGetCurrentProcess()) { - PageDirTable = ExAllocatePageWithPhysPage(Process->Pcb.DirectoryTableBase.u.LowPart >> PAGE_SHIFT); - Pde = (PULONGLONG)ExAllocatePageWithPhysPage(PageDirTable[i] >> PAGE_SHIFT); - ExUnmapPage(PageDirTable); + PageDirTable = MmCreateHyperspaceMapping(PAE_PTE_TO_PFN(Process->Pcb.DirectoryTableBase .QuadPart)); + Pde = (PULONGLONG)MmCreateHyperspaceMapping(PTE_TO_PFN(PageDirTable[i])); + MmDeleteHyperspaceMapping(PageDirTable); } else { @@ -2138,7 +2306,7 @@
if (Process != NULL && Process != PsGetCurrentProcess()) { - Pde = ExAllocatePageWithPhysPage(Process->Pcb.DirectoryTableBase.u.LowPart >> PAGE_SHIFT); + Pde = MmCreateHyperspaceMapping(PTE_TO_PFN(Process->Pcb.DirectoryTableBase.u.L owPart)); } else { @@ -2153,22 +2321,26 @@ } if (Pde != (PULONG)PAGEDIRECTORY_MAP) { - ExUnmapPage(Pde); + MmDeleteHyperspaceMapping(Pde); } } } - + VOID INIT_FUNCTION MmInitGlobalKernelPageDirectory(VOID) { ULONG i; + + DPRINT("MmInitGlobalKernelPageDirectory()\n"); + if (Ke386Pae) { PULONGLONG CurrentPageDirectory = (PULONGLONG)PAE_PAGEDIRECTORY_MAP; for (i = PAE_ADDR_TO_PDE_OFFSET(KERNEL_BASE); i < 4 * 512; i++) { - if ((i < PAE_ADDR_TO_PDE_OFFSET(PAGETABLE_MAP) || i >= PAE_ADDR_TO_PDE_OFFSET(PAGETABLE_MAP) + 4) && - 0LL == MmGlobalKernelPageDirectoryForPAE[i] && 0LL != CurrentPageDirectory[i]) + if (!(i >= PAE_ADDR_TO_PDE_OFFSET(PAGETABLE_MAP) && i < PAE_ADDR_TO_PDE_OFFSET(PAGETABLE_MAP) + 4) && + !(i >= PAE_ADDR_TO_PDE_OFFSET(HYPERSPACE) && i < PAE_ADDR_TO_PDE_OFFSET(HYPERSPACE) + 2) && + 0LL == MmGlobalKernelPageDirectoryForPAE[i] && 0LL != CurrentPageDirectory[i]) {
ExfpInterlockedExchange64UL(&MmGlobalKernelPageDirectoryForPAE[i], &CurrentPageDirectory[i]); if (Ke386GlobalPagesEnabled) @@ -2185,6 +2357,7 @@ for (i = ADDR_TO_PDE_OFFSET(KERNEL_BASE); i < 1024; i++) { if (i != ADDR_TO_PDE_OFFSET(PAGETABLE_MAP) && + i != ADDR_TO_PDE_OFFSET(HYPERSPACE) && 0 == MmGlobalKernelPageDirectory[i] && 0 != CurrentPageDirectory[i]) { MmGlobalKernelPageDirectory[i] = CurrentPageDirectory[i]; @@ -2218,22 +2391,26 @@ memcpy(PageDirTable, (PVOID)PAGEDIRECTORY_MAP, PAGE_SIZE);
PageDir = (PULONGLONG)*LastKernelAddress; - (*LastKernelAddress) += 4 * PAGE_SIZE; + (*LastKernelAddress) += 6 * PAGE_SIZE; PageDirTable[0] = MmGetPhysicalAddress((PVOID)PageDir).QuadPart | PA_PRESENT; PageDirTable[1] = PageDirTable[0] + PAGE_SIZE; PageDirTable[2] = PageDirTable[1] + PAGE_SIZE; PageDirTable[3] = PageDirTable[2] + PAGE_SIZE;
- memset(PageDir, 0, 4 * PAGE_SIZE); + memset(PageDir, 0, 6 * PAGE_SIZE);
for (i = 0; i < 4; i++) { - PageDir[3*512+PAE_ADDR_TO_PDE_PAGE_OFFSET(PAGETABLE_MAP) + i] = PageDirTable[i] | PA_READWRITE; + PageDir[PAE_ADDR_TO_PDE_OFFSET(PAGETABLE_MAP) + i] = PageDirTable[i] | PA_READWRITE; } + PageDir[PAE_ADDR_TO_PDE_OFFSET(HYPERSPACE)] = (PageDirTable[0] + 4 * PAGE_SIZE) | PA_READWRITE; + PageDir[PAE_ADDR_TO_PDE_OFFSET(HYPERSPACE)+1] = (PageDirTable[0] + 5 * PAGE_SIZE) | PA_READWRITE;
for (i = 0; i < 2048; i++) { - if (i < PAE_ADDR_TO_PDE_OFFSET(PAGETABLE_MAP) || i >= PAE_ADDR_TO_PDE_OFFSET(PAGETABLE_MAP) + 4) + if (!(i >= PAE_ADDR_TO_PDE_OFFSET(PAGETABLE_MAP) && i < PAE_ADDR_TO_PDE_OFFSET(PAGETABLE_MAP) + 4) && + !(i >= PAE_ADDR_TO_PDE_OFFSET(HYPERSPACE) && i < PAE_ADDR_TO_PDE_OFFSET(HYPERSPACE)+2)) + { PVOID Address = (PVOID)(i * 512 * PAGE_SIZE); PULONG Pde = ADDR_TO_PDE(Address); @@ -2293,9 +2470,12 @@ MiInitPageDirectoryMap(VOID) { MEMORY_AREA* kernel_map_desc = NULL; + MEMORY_AREA* hyperspace_desc = NULL; PHYSICAL_ADDRESS BoundaryAddressMultiple; PVOID BaseAddress;
+ DPRINT("MiInitPageDirectoryMap()\n"); + BoundaryAddressMultiple.QuadPart = 0; BaseAddress = (PVOID)PAGETABLE_MAP; MmCreateMemoryArea(NULL, @@ -2308,6 +2488,17 @@ TRUE, FALSE, BoundaryAddressMultiple); + BaseAddress = (PVOID)HYPERSPACE; + MmCreateMemoryArea(NULL, + MmGetKernelAddressSpace(), + MEMORY_AREA_SYSTEM, + &BaseAddress, + 0x400000, + 0, + &hyperspace_desc, + TRUE, + FALSE, + BoundaryAddressMultiple); }
/* EOF */ _____
Modified: trunk/reactos/ntoskrnl/mm/kmap.c --- trunk/reactos/ntoskrnl/mm/kmap.c 2005-01-25 22:36:28 UTC (rev 13287) +++ trunk/reactos/ntoskrnl/mm/kmap.c 2005-01-25 22:50:47 UTC (rev 13288) @@ -15,61 +15,19 @@
/* GLOBALS *****************************************************************/
-#define ALLOC_MAP_SIZE (MM_KERNEL_MAP_SIZE / PAGE_SIZE) - -/* - * One bit for each page in the kmalloc region - * If set then the page is used by a kmalloc block - */ -static UCHAR AllocMapBuffer[ROUND_UP(ALLOC_MAP_SIZE, 32) / 8]; -static RTL_BITMAP AllocMap; -static KSPIN_LOCK AllocMapLock; -static ULONG AllocMapHint = 0; - /* FUNCTIONS ***************************************************************/ - -VOID -ExUnmapPage(PVOID Addr) -{ - KIRQL oldIrql; - ULONG_PTR Base = ((ULONG_PTR)Addr - (ULONG_PTR)MM_KERNEL_MAP_BASE) / PAGE_SIZE; - - DPRINT("ExUnmapPage(Addr %x)\n",Addr); - - MmDeleteVirtualMapping(NULL, (PVOID)Addr, FALSE, NULL, NULL); - KeAcquireSpinLock(&AllocMapLock, &oldIrql); - RtlClearBits(&AllocMap, Base, 1); - AllocMapHint = min(AllocMapHint, Base); - KeReleaseSpinLock(&AllocMapLock, oldIrql); -} - -PVOID -ExAllocatePage(VOID) -{ - PFN_TYPE Page; - NTSTATUS Status; - - Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Page); - if (!NT_SUCCESS(Status)) - { - return(NULL); - } - - return(ExAllocatePageWithPhysPage(Page)); -} - NTSTATUS MiZeroPage(PFN_TYPE Page) { PVOID TempAddress;
- TempAddress = ExAllocatePageWithPhysPage(Page); + TempAddress = MmCreateHyperspaceMapping(Page); if (TempAddress == NULL) { return(STATUS_NO_MEMORY); } memset(TempAddress, 0, PAGE_SIZE); - ExUnmapPage(TempAddress); + MmDeleteHyperspaceMapping(TempAddress); return(STATUS_SUCCESS); }
@@ -78,99 +36,13 @@ { PVOID TempAddress;
- TempAddress = ExAllocatePageWithPhysPage(DestPage); + TempAddress = MmCreateHyperspaceMapping(DestPage); if (TempAddress == NULL) { return(STATUS_NO_MEMORY); } memcpy(TempAddress, SourceAddress, PAGE_SIZE); - ExUnmapPage(TempAddress); + MmDeleteHyperspaceMapping(TempAddress); return(STATUS_SUCCESS); }
-PVOID -ExAllocatePageWithPhysPage(PFN_TYPE Page) -{ - KIRQL oldlvl; - PVOID Addr; - ULONG_PTR Base; - NTSTATUS Status; - - KeAcquireSpinLock(&AllocMapLock, &oldlvl); - Base = RtlFindClearBitsAndSet(&AllocMap, 1, AllocMapHint); - if (Base != (ULONG_PTR)-1) - { - AllocMapHint = Base + 1; - KeReleaseSpinLock(&AllocMapLock, oldlvl); - Addr = (char*)MM_KERNEL_MAP_BASE + Base * PAGE_SIZE; - Status = MmCreateVirtualMapping(NULL, - Addr, - PAGE_READWRITE | PAGE_SYSTEM, - &Page, - 1); - if (!NT_SUCCESS(Status)) - { - DbgPrint("Unable to create virtual mapping\n"); - KEBUGCHECK(0); - } - return Addr; - } - KeReleaseSpinLock(&AllocMapLock, oldlvl); - return NULL; -} - -VOID INIT_FUNCTION -MiInitKernelMap(VOID) -{ - KeInitializeSpinLock(&AllocMapLock); - RtlInitializeBitMap(&AllocMap, (PULONG)AllocMapBuffer, ALLOC_MAP_SIZE); - RtlClearAllBits(&AllocMap); -} - -VOID -MiFreeNonPagedPoolRegion(PVOID Addr, ULONG Count, BOOLEAN Free) -{ - ULONG i; - ULONG_PTR Base = ((char*)Addr - (char*)MM_KERNEL_MAP_BASE) / PAGE_SIZE; - KIRQL oldlvl; - - for (i = 0; i < Count; i++) - { - MmDeleteVirtualMapping(NULL, - (char*)Addr + (i * PAGE_SIZE), - Free, - NULL, - NULL); - } - KeAcquireSpinLock(&AllocMapLock, &oldlvl); - RtlClearBits(&AllocMap, Base, Count); - AllocMapHint = min(AllocMapHint, Base); - KeReleaseSpinLock(&AllocMapLock, oldlvl); -} - -PVOID -MiAllocNonPagedPoolRegion(ULONG nr_pages) -/* - * FUNCTION: Allocates a region of pages within the nonpaged pool area - */ -{ - ULONG_PTR Base; - KIRQL oldlvl; - - KeAcquireSpinLock(&AllocMapLock, &oldlvl); - Base = RtlFindClearBitsAndSet(&AllocMap, nr_pages, AllocMapHint); - if (Base == (ULONG_PTR)-1) - { - DbgPrint("CRITICAL: Out of non-paged pool space\n"); - KEBUGCHECK(0); - } - if (AllocMapHint == Base) - { - AllocMapHint += nr_pages; - } - KeReleaseSpinLock(&AllocMapLock, oldlvl); [truncated at 1000 lines; 81 more skipped]