diff -urN 2.4.19pre5/include/asm-alpha/module.h module-gfp/include/asm-alpha/module.h
--- 2.4.19pre5/include/asm-alpha/module.h	Tue Jan 22 18:53:53 2002
+++ module-gfp/include/asm-alpha/module.h	Sat Mar 30 20:59:39 2002
@@ -4,8 +4,8 @@
  * This file contains the alpha architecture specific module code.
  */
 
-#define module_map(x)		vmalloc(x)
-#define module_unmap(x)		vfree(x)
+#define module_map(x)	alloc_exact(x)
+#define module_unmap(x)	free_exact((x), (x)->size)
 #define module_arch_init(x)	alpha_module_init(x)
 #define arch_init_modules(x)	alpha_init_modules(x)
 
diff -urN 2.4.19pre5/include/asm-i386/module.h module-gfp/include/asm-i386/module.h
--- 2.4.19pre5/include/asm-i386/module.h	Tue Jan 22 18:53:54 2002
+++ module-gfp/include/asm-i386/module.h	Sat Mar 30 20:59:39 2002
@@ -4,8 +4,8 @@
  * This file contains the i386 architecture specific module code.
  */
 
-#define module_map(x)		vmalloc(x)
-#define module_unmap(x)		vfree(x)
+#define module_map(x)	alloc_exact(x)
+#define module_unmap(x)	free_exact((x), (x)->size)
 #define module_arch_init(x)	(0)
 #define arch_init_modules(x)	do { } while (0)
 
diff -urN 2.4.19pre5/include/linux/mm.h module-gfp/include/linux/mm.h
--- 2.4.19pre5/include/linux/mm.h	Sat Mar 30 00:12:05 2002
+++ module-gfp/include/linux/mm.h	Sat Mar 30 20:59:39 2002
@@ -456,6 +456,9 @@
 extern void FASTCALL(__free_pages(struct page *page, unsigned int order));
 extern void FASTCALL(free_pages(unsigned long addr, unsigned int order));
 
+extern void * FASTCALL(alloc_exact(unsigned int size));
+extern void FASTCALL(free_exact(void * addr, unsigned int size));
+
 #define __free_page(page) __free_pages((page), 0)
 #define free_page(addr) free_pages((addr),0)
 
diff -urN 2.4.19pre5/kernel/ksyms.c module-gfp/kernel/ksyms.c
--- 2.4.19pre5/kernel/ksyms.c	Sat Mar 30 00:12:05 2002
+++ module-gfp/kernel/ksyms.c	Sat Mar 30 20:59:39 2002
@@ -97,6 +97,8 @@
 EXPORT_SYMBOL(get_zeroed_page);
 EXPORT_SYMBOL(__free_pages);
 EXPORT_SYMBOL(free_pages);
+EXPORT_SYMBOL(free_exact);
+EXPORT_SYMBOL(alloc_exact);
 EXPORT_SYMBOL(num_physpages);
 EXPORT_SYMBOL(kmem_find_general_cachep);
 EXPORT_SYMBOL(kmem_cache_create);
diff -urN 2.4.19pre5/mm/page_alloc.c module-gfp/mm/page_alloc.c
--- 2.4.19pre5/mm/page_alloc.c	Sat Mar 30 00:12:05 2002
+++ module-gfp/mm/page_alloc.c	Sat Mar 30 20:59:51 2002
@@ -21,6 +21,7 @@
 #include <linux/bootmem.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/vmalloc.h>
 
 int nr_swap_pages;
 int nr_active_pages;
@@ -471,6 +472,54 @@
 	if (addr != 0)
 		__free_pages(virt_to_page(addr), order);
 }
+
+static inline int nextorder(unsigned int x)
+{
+	int c = -PAGE_SHIFT;
+	while (x) {
+		x >>= 1; 
+		c++; 
+	}
+	if (c < 0) 
+		c = 0;
+	return c; 
+}  
+
+void * alloc_exact(unsigned int size)
+{ 
+	struct page *p, *w; 
+	int order = nextorder(size); 
+
+	p = alloc_pages(GFP_KERNEL, order);
+	if (p) {
+		struct page *end = p + (1UL << order); 
+		for (w = p+1; w < end; ++w) 
+			set_page_count(w, 1); 
+		for (w = p + (size>>PAGE_SHIFT)+1; w < end; ++w) 	      
+			__free_pages(w, 0); 
+		return (void *) page_address(p); 
+	} 
+
+	return vmalloc(size);
+} 
+
+void free_exact(void * addr, unsigned int size)
+{ 
+	struct page * w; 
+	unsigned long mptr = (unsigned long) addr; 
+	int sz;
+
+	if (mptr >= VMALLOC_START && mptr + size <= VMALLOC_END) { 
+		vfree(addr); 
+		return;
+	} 
+	w = virt_to_page(addr); 
+	for (sz = size; sz > 0; sz -= PAGE_SIZE, ++w) { 
+		if (atomic_read(&w->count) != 1) 
+			BUG(); 
+		__free_pages(w, 0); 
+	} 	
+} 
 
 /*
  * Total amount of free (allocatable) RAM: