3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/mm/kmap.c
6 * PURPOSE: Implements the kernel memory pool
7 * PROGRAMMER: David Welch (welch@cwcom.net)
10 /* INCLUDES ****************************************************************/
12 #include <ddk/ntddk.h>
13 #include <internal/mm.h>
14 #include <internal/ntoskrnl.h>
15 #include <internal/pool.h>
16 #include <ntos/minmax.h>
19 #include <internal/debug.h>
21 /* GLOBALS *****************************************************************/
23 #define ALLOC_MAP_SIZE (NONPAGED_POOL_SIZE / PAGE_SIZE)
26 * One bit for each page in the kmalloc region
27 * If set then the page is used by a kmalloc block
29 static ULONG AllocMap[ALLOC_MAP_SIZE/32]={0,};
30 static KSPIN_LOCK AllocMapLock;
31 static ULONG AllocMapHint = 1;
33 static PVOID NonPagedPoolBase;
35 /* FUNCTIONS ***************************************************************/
38 ExUnmapPage(PVOID Addr)
41 ULONG i = (Addr - NonPagedPoolBase) / PAGE_SIZE;
43 DPRINT("ExUnmapPage(Addr %x)\n",Addr);
46 MmDeleteVirtualMapping(NULL, (PVOID)Addr, FALSE, NULL, NULL);
47 KeAcquireSpinLock(&AllocMapLock, &oldIrql);
48 AllocMap[i / 32] &= (~(1 << (i % 32)));
49 AllocMapHint = min(AllocMapHint, i);
50 KeReleaseSpinLock(&AllocMapLock, oldIrql);
56 PHYSICAL_ADDRESS PhysPage;
59 Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &PhysPage);
60 if (!NT_SUCCESS(Status))
65 return(ExAllocatePageWithPhysPage(PhysPage));
69 MiZeroPage(PHYSICAL_ADDRESS PhysPage)
73 TempAddress = ExAllocatePageWithPhysPage(PhysPage);
74 if (TempAddress == NULL)
76 return(STATUS_NO_MEMORY);
78 memset(TempAddress, 0, PAGE_SIZE);
79 ExUnmapPage(TempAddress);
80 return(STATUS_SUCCESS);
84 MiCopyFromUserPage(PHYSICAL_ADDRESS DestPhysPage, PVOID SourceAddress)
88 TempAddress = ExAllocatePageWithPhysPage(DestPhysPage);
89 if (TempAddress == NULL)
91 return(STATUS_NO_MEMORY);
93 memcpy(TempAddress, SourceAddress, PAGE_SIZE);
94 ExUnmapPage(TempAddress);
95 return(STATUS_SUCCESS);
99 ExAllocatePageWithPhysPage(PHYSICAL_ADDRESS PhysPage)
106 KeAcquireSpinLock(&AllocMapLock, &oldlvl);
107 for (i = AllocMapHint; i < ALLOC_MAP_SIZE; i++)
109 if (!(AllocMap[i / 32] & (1 << (i % 32))))
112 AllocMap[i / 32] |= (1 << (i % 32));
113 AllocMapHint = i + 1;
114 addr = (ULONG)(NonPagedPoolBase + (i*PAGE_SIZE));
115 Status = MmCreateVirtualMapping(NULL,
117 PAGE_READWRITE | PAGE_SYSTEM,
120 if (!NT_SUCCESS(Status))
122 DbgPrint("Unable to create virtual mapping\n");
125 KeReleaseSpinLock(&AllocMapLock, oldlvl);
129 KeReleaseSpinLock(&AllocMapLock, oldlvl);
134 MmInitKernelMap(PVOID BaseAddress)
136 NonPagedPoolBase = BaseAddress;
137 KeInitializeSpinLock(&AllocMapLock);
141 MiFreeNonPagedPoolRegion(PVOID Addr, ULONG Count, BOOLEAN Free)
144 ULONG Base = (Addr - NonPagedPoolBase) / PAGE_SIZE;
148 KeAcquireSpinLock(&AllocMapLock, &oldlvl);
149 AllocMapHint = min(AllocMapHint, Base);
150 for (i = 0; i < Count; i++)
153 AllocMap[Offset / 32] &= (~(1 << (Offset % 32)));
154 MmDeleteVirtualMapping(NULL,
155 Addr + (i * PAGE_SIZE),
160 KeReleaseSpinLock(&AllocMapLock, oldlvl);
164 MiAllocNonPagedPoolRegion(ULONG nr_pages)
166 * FUNCTION: Allocates a region of pages within the nonpaged pool area
169 unsigned int start = 0;
170 unsigned int length = 0;
174 KeAcquireSpinLock(&AllocMapLock, &oldlvl);
175 for (i=AllocMapHint; i<ALLOC_MAP_SIZE;i++)
177 if (!(AllocMap[i/32] & (1 << (i % 32))))
188 if (length==nr_pages)
190 AllocMapHint = start + length;
191 for (j=start;j<(start+length);j++)
193 AllocMap[j / 32] |= (1 << (j % 32));
195 DPRINT("returning %x\n",((start*PAGE_SIZE)+NonPagedPoolBase));
196 KeReleaseSpinLock(&AllocMapLock, oldlvl);
197 return(((start*PAGE_SIZE)+NonPagedPoolBase));
206 DbgPrint("CRITICAL: Out of non-paged pool space\n");