linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Andi Kleen <ak@muc.de>
To: linux-kernel@vger.kernel.org, torvalds@transmeta.com
Subject: [PATCH] Put modules into linear mapping
Date: Fri, 27 Sep 2002 16:09:30 +0200	[thread overview]
Message-ID: <20020927140930.GA12610@averell> (raw)


Now that kksymoops is in this can be safely merged:

In some cases there is a benchmarkable difference (in the several percent
range) between a compiled in driver and a modular driver. The reason is 
the compiled in driver is mapped in 2/4MB pages in the direct mapping,
while modules are mapped wit 4K pages in the vmalloc area. The resulting
TLB misses can make that much difference.

This patch fixes it by just putting the modules into the linear mapping
if possible. This needs unfragmented memory, but modules tend to be loaded
at bootup when there is still plenty of this. When it fails it just falls
back to vmalloc.

It has one drawback in that it makes the load address of modules much more
random than they were previously: you have a bigger chance that 
the module is loaded somewhere else after reboot and then ksymoops wouldn't
be able to decode an module oops correctly anymore. With kksymoops this
shouldn't be a problem anymore, so it can be safely merged.

To avoid too much memory wastage it adds a new interface alloc_exact/free_exact
that allocates pages from the page allocator but doesn't round the area size
to the next power of two. 

Variants of this patch have run successfully for several years in the -aa
kernels and in the SuSE kernels.

Patch for 2.5.38. Please apply.

-Andi


--- linux-2.5.38-work/include/linux/gfp.h-MODULE	2002-09-25 00:59:27.000000000 +0200
+++ linux-2.5.38-work/include/linux/gfp.h	2002-09-27 15:30:59.000000000 +0200
@@ -85,4 +85,7 @@
 #define __free_page(page) __free_pages((page), 0)
 #define free_page(addr) free_pages((addr),0)
 
+extern void *alloc_exact(unsigned int size);
+extern void free_exact(void * addr, unsigned int size);
+
 #endif /* __LINUX_GFP_H */
--- linux-2.5.38-work/include/asm-i386/module.h-MODULE	2002-09-25 00:59:28.000000000 +0200
+++ linux-2.5.38-work/include/asm-i386/module.h	2002-09-27 15:30:35.000000000 +0200
@@ -3,9 +3,31 @@
 /*
  * This file contains the i386 architecture specific module code.
  */
+#include <linux/vmalloc.h>
+#include <linux/highmem.h>
+#include <asm/page.h>
+
+/* 
+ * Try to allocate in the linear large page mapping first to conserve
+ * TLB entries. 
+ */
+static inline void *module_map(unsigned long size) 
+{ 
+	void *p = alloc_exact(size); 
+	if (!p)
+		p = vmalloc(size); 
+	return p;
+} 
+
+static inline void module_unmap (struct module *mod)
+{
+	unsigned long mptr = (unsigned long)mod;
+	if (mptr >= VMALLOC_START && mptr+mod->size <= VMALLOC_END)
+		vfree(mod); 
+	else
+		free_exact(mod, mod->size);
+}
 
-#define module_map(x)		vmalloc(x)
-#define module_unmap(x)		vfree(x)
 #define module_arch_init(x)	(0)
 #define arch_init_modules(x)	do { } while (0)
 
--- linux-2.5.38-work/mm/page_alloc.c-MODULE	2002-09-25 00:59:29.000000000 +0200
+++ linux-2.5.38-work/mm/page_alloc.c	2002-09-27 15:34:59.000000000 +0200
@@ -464,6 +464,38 @@
 		__free_pages(virt_to_page(addr), order);
 	}
 }
+ 
+void *alloc_exact(unsigned int size)
+{ 
+	struct page *p, *w; 
+	int order = get_order(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 NULL;
+} 
+
+void free_exact(void * addr, unsigned int size)
+{ 
+	struct page * w; 
+	unsigned long mptr = (unsigned long) addr; 
+	int sz;
+
+	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:
--- linux-2.5.38-work/kernel/ksyms.c-MODULE	2002-09-25 00:59:29.000000000 +0200
+++ linux-2.5.38-work/kernel/ksyms.c	2002-09-27 15:51:47.000000000 +0200
@@ -97,6 +97,8 @@
 EXPORT_SYMBOL(get_zeroed_page);
 EXPORT_SYMBOL(__page_cache_release);
 EXPORT_SYMBOL(__free_pages);
+EXPORT_SYMBOL(alloc_exact);
+EXPORT_SYMBOL(free_exact);
 EXPORT_SYMBOL(free_pages);
 EXPORT_SYMBOL(num_physpages);
 EXPORT_SYMBOL(kmem_find_general_cachep);

             reply	other threads:[~2002-09-27 14:04 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-09-27 14:09 Andi Kleen [this message]
2002-09-27 14:43 ` [PATCH] Put modules into linear mapping Roman Zippel
2002-09-27 15:05 ` Christoph Hellwig
2002-09-28 13:47 ` Keith Owens
     [not found] <20020927140930.GA12610@averell.suse.lists.linux.kernel>
     [not found] ` <Pine.LNX.4.44.0209271618360.8911-100000@serv.suse.lists.linux.kernel>
2002-09-27 15:36   ` Andi Kleen
2002-09-27 15:55     ` Roman Zippel
2002-09-27 16:14       ` Andi Kleen
2002-09-27 16:52         ` Roman Zippel
2002-09-27 16:59           ` Andi Kleen
2002-09-27 17:09             ` Roman Zippel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20020927140930.GA12610@averell \
    --to=ak@muc.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=torvalds@transmeta.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).