1 /* $Id: kmap.c,v 1.21 2002/10/01 19:27:22 chorns Exp $
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");