* [PATCH][RFC] __init and friends support for loadable modules
@ 2002-05-08 10:29 Andrey Panin
2002-05-08 14:02 ` Keith Owens
0 siblings, 1 reply; 3+ messages in thread
From: Andrey Panin @ 2002-05-08 10:29 UTC (permalink / raw)
To: linux-kernel
[-- Attachment #1.1: Type: text/plain, Size: 637 bytes --]
Hi all,
attached patch adds support for freeing .init sections of loadable modules
after init_module() function exits. Modutils have support for this since 1998,
but kernel support didn't exist.
All architectures that use vmalloc/vfree for module_map/unmap should work.
Patch contains three major part:
- shrink_vm_area() function for reducing size of vmalloc'ed area;
- init.h changes to allow .init sections in modules;
- change in kernel/module.c.
Comments, suggestions ?
Best regards.
--
Andrey Panin | Embedded systems software engineer
pazke@orbita1.ru | PGP key: wwwkeys.eu.pgp.net
[-- Attachment #1.2: patch-module-init --]
[-- Type: text/plain, Size: 12461 bytes --]
diff -urN -X /usr/share/dontdiff linux.vanilla/include/asm-alpha/module.h linux/include/asm-alpha/module.h
--- linux.vanilla/include/asm-alpha/module.h Wed May 8 10:01:53 2002
+++ linux/include/asm-alpha/module.h Wed May 8 10:06:36 2002
@@ -6,6 +6,7 @@
#define module_map(x) vmalloc(x)
#define module_unmap(x) vfree(x)
+#define module_remap(ptr, size) shrink_vm_area(ptr, size)
#define module_arch_init(x) alpha_module_init(x)
#define arch_init_modules(x) alpha_init_modules(x)
diff -urN -X /usr/share/dontdiff linux.vanilla/include/asm-arm/module.h linux/include/asm-arm/module.h
--- linux.vanilla/include/asm-arm/module.h Wed May 8 10:01:57 2002
+++ linux/include/asm-arm/module.h Wed May 8 10:06:36 2002
@@ -6,6 +6,7 @@
#define module_map(x) vmalloc(x)
#define module_unmap(x) vfree(x)
+#define module_remap(ptr, size) shrink_vm_area(ptr, size)
#define module_arch_init(x) (0)
#define arch_init_modules(x) do { } while (0)
diff -urN -X /usr/share/dontdiff linux.vanilla/include/asm-cris/module.h linux/include/asm-cris/module.h
--- linux.vanilla/include/asm-cris/module.h Wed May 8 10:02:01 2002
+++ linux/include/asm-cris/module.h Wed May 8 10:06:36 2002
@@ -6,6 +6,7 @@
#define module_map(x) vmalloc(x)
#define module_unmap(x) vfree(x)
+#define module_remap(ptr, size) shrink_vm_area(ptr, size)
#define module_arch_init(x) (0)
#define arch_init_modules(x) do { } while (0)
diff -urN -X /usr/share/dontdiff linux.vanilla/include/asm-i386/module.h linux/include/asm-i386/module.h
--- linux.vanilla/include/asm-i386/module.h Wed May 8 10:01:52 2002
+++ linux/include/asm-i386/module.h Wed May 8 10:06:36 2002
@@ -6,6 +6,7 @@
#define module_map(x) vmalloc(x)
#define module_unmap(x) vfree(x)
+#define module_remap(ptr, size) shrink_vm_area(ptr, size)
#define module_arch_init(x) (0)
#define arch_init_modules(x) do { } while (0)
diff -urN -X /usr/share/dontdiff linux.vanilla/include/asm-ia64/module.h linux/include/asm-ia64/module.h
--- linux.vanilla/include/asm-ia64/module.h Wed May 8 10:01:58 2002
+++ linux/include/asm-ia64/module.h Wed May 8 10:06:36 2002
@@ -13,6 +13,7 @@
#define module_map(x) vmalloc(x)
#define module_unmap(x) ia64_module_unmap(x)
+#define module_remap(ptr, size) (-ENOSYS)
#define module_arch_init(x) ia64_module_init(x)
/*
diff -urN -X /usr/share/dontdiff linux.vanilla/include/asm-m68k/module.h linux/include/asm-m68k/module.h
--- linux.vanilla/include/asm-m68k/module.h Wed May 8 10:01:53 2002
+++ linux/include/asm-m68k/module.h Wed May 8 10:06:36 2002
@@ -6,6 +6,7 @@
#define module_map(x) vmalloc(x)
#define module_unmap(x) vfree(x)
+#define module_remap(ptr, size) shrink_vm_area(ptr, size)
#define module_arch_init(x) (0)
#define arch_init_modules(x) do { } while (0)
diff -urN -X /usr/share/dontdiff linux.vanilla/include/asm-mips/module.h linux/include/asm-mips/module.h
--- linux.vanilla/include/asm-mips/module.h Wed May 8 10:01:52 2002
+++ linux/include/asm-mips/module.h Wed May 8 10:06:36 2002
@@ -9,6 +9,7 @@
#define module_map(x) vmalloc(x)
#define module_unmap(x) vfree(x)
+#define module_remap(ptr, size) shrink_vm_area(ptr, size)
#define module_arch_init(x) mips_module_init(x)
#define arch_init_modules(x) mips_init_modules(x)
diff -urN -X /usr/share/dontdiff linux.vanilla/include/asm-mips64/module.h linux/include/asm-mips64/module.h
--- linux.vanilla/include/asm-mips64/module.h Wed May 8 10:02:01 2002
+++ linux/include/asm-mips64/module.h Wed May 8 10:06:36 2002
@@ -9,6 +9,7 @@
#define module_map(x) vmalloc(x)
#define module_unmap(x) vfree(x)
+#define module_remap(ptr, size) shrink_vm_area(ptr, size)
#define module_arch_init(x) mips64_module_init(x)
#define arch_init_modules(x) mips64_init_modules(x)
diff -urN -X /usr/share/dontdiff linux.vanilla/include/asm-ppc/module.h linux/include/asm-ppc/module.h
--- linux.vanilla/include/asm-ppc/module.h Wed May 8 10:01:55 2002
+++ linux/include/asm-ppc/module.h Wed May 8 10:06:36 2002
@@ -9,6 +9,7 @@
#define module_map(x) vmalloc(x)
#define module_unmap(x) vfree(x)
+#define module_remap(ptr, size) shrink_vm_area(ptr, size)
#define module_arch_init(x) (0)
#define arch_init_modules(x) do { } while (0)
diff -urN -X /usr/share/dontdiff linux.vanilla/include/asm-ppc64/module.h linux/include/asm-ppc64/module.h
--- linux.vanilla/include/asm-ppc64/module.h Wed May 8 10:02:04 2002
+++ linux/include/asm-ppc64/module.h Wed May 8 10:06:36 2002
@@ -13,6 +13,7 @@
#define module_map(x) vmalloc(x)
#define module_unmap(x) vfree(x)
+#define module_remap(ptr, size) shrink_vm_area(ptr, size)
#define arch_init_modules(x) do { } while (0)
#define module_arch_init(x) (0)
#endif /* _ASM_PPC64_MODULE_H */
diff -urN -X /usr/share/dontdiff linux.vanilla/include/asm-s390/module.h linux/include/asm-s390/module.h
--- linux.vanilla/include/asm-s390/module.h Wed May 8 10:02:01 2002
+++ linux/include/asm-s390/module.h Wed May 8 10:06:36 2002
@@ -6,6 +6,7 @@
#define module_map(x) vmalloc(x)
#define module_unmap(x) vfree(x)
+#define module_remap(ptr, size) shrink_vm_area(ptr, size)
#define module_arch_init(x) (0)
#define arch_init_modules(x) do { } while (0)
diff -urN -X /usr/share/dontdiff linux.vanilla/include/asm-s390x/module.h linux/include/asm-s390x/module.h
--- linux.vanilla/include/asm-s390x/module.h Wed May 8 10:02:03 2002
+++ linux/include/asm-s390x/module.h Wed May 8 10:06:36 2002
@@ -6,6 +6,7 @@
#define module_map(x) vmalloc(x)
#define module_unmap(x) vfree(x)
+#define module_remap(ptr, size) shrink_vm_area(ptr, size)
#define module_arch_init(x) (0)
#define arch_init_modules(x) do { } while (0)
diff -urN -X /usr/share/dontdiff linux.vanilla/include/asm-sh/module.h linux/include/asm-sh/module.h
--- linux.vanilla/include/asm-sh/module.h Wed May 8 10:01:58 2002
+++ linux/include/asm-sh/module.h Wed May 8 10:06:36 2002
@@ -6,6 +6,7 @@
#define module_map(x) vmalloc(x)
#define module_unmap(x) vfree(x)
+#define module_remap(ptr, size) shrink_vm_area(ptr, size)
#define module_arch_init(x) (0)
#define arch_init_modules(x) do { } while (0)
diff -urN -X /usr/share/dontdiff linux.vanilla/include/asm-sparc/module.h linux/include/asm-sparc/module.h
--- linux.vanilla/include/asm-sparc/module.h Wed May 8 10:01:54 2002
+++ linux/include/asm-sparc/module.h Wed May 8 10:06:36 2002
@@ -6,6 +6,7 @@
#define module_map(x) vmalloc(x)
#define module_unmap(x) vfree(x)
+#define module_remap(ptr, size) shrink_vm_area(ptr, size)
#define module_arch_init(x) (0)
#define arch_init_modules(x) do { } while (0)
diff -urN -X /usr/share/dontdiff linux.vanilla/include/asm-sparc64/module.h linux/include/asm-sparc64/module.h
--- linux.vanilla/include/asm-sparc64/module.h Wed May 8 10:01:56 2002
+++ linux/include/asm-sparc64/module.h Wed May 8 10:06:36 2002
@@ -6,6 +6,7 @@
extern void * module_map (unsigned long size);
extern void module_unmap (void *addr);
+#define module_remap(ptr, size) (-ENOSYS)
#define module_arch_init(x) (0)
#define arch_init_modules(x) do { } while (0)
diff -urN -X /usr/share/dontdiff linux.vanilla/include/asm-x86_64/module.h linux/include/asm-x86_64/module.h
--- linux.vanilla/include/asm-x86_64/module.h Wed May 8 10:02:05 2002
+++ linux/include/asm-x86_64/module.h Wed May 8 10:06:36 2002
@@ -9,6 +9,8 @@
extern void *module_map(unsigned long);
extern void module_unmap(void *);
+#define module_remap(ptr, size) (-ENOSYS)
+
#define module_arch_init(x) (0)
#define arch_init_modules(x) do { } while (0)
diff -urN -X /usr/share/dontdiff linux.vanilla/include/linux/init.h linux/include/linux/init.h
--- linux.vanilla/include/linux/init.h Wed May 8 10:01:47 2002
+++ linux/include/linux/init.h Wed May 8 10:06:36 2002
@@ -38,6 +38,18 @@
* Also note, that this data cannot be "const".
*/
+/*
+ * Mark functions and data as being only used at initialization
+ * or exit time.
+ */
+#define __init __attribute__ ((__section__ (".text.init")))
+#define __initdata __attribute__ ((__section__ (".data.init")))
+
+/* For assembly routines */
+#define __INIT .section ".text.init","ax"
+#define __FINIT .previous
+#define __INITDATA .section ".data.init","aw"
+
#ifndef MODULE
#ifndef __ASSEMBLY__
@@ -89,23 +101,12 @@
#endif /* __ASSEMBLY__ */
-/*
- * Mark functions and data as being only used at initialization
- * or exit time.
- */
-#define __init __attribute__ ((__section__ (".text.init")))
-#define __exit __attribute__ ((unused, __section__(".text.exit")))
-#define __initdata __attribute__ ((__section__ (".data.init")))
-#define __exitdata __attribute__ ((unused, __section__ (".data.exit")))
#define __initsetup __attribute__ ((unused,__section__ (".setup.init")))
#define __init_call(level) __attribute__ ((unused,__section__ (".initcall" level ".init")))
+#define __exit __attribute__ ((unused, __section__(".text.exit")))
+#define __exitdata __attribute__ ((unused, __section__ (".data.exit")))
#define __exit_call __attribute__ ((unused,__section__ (".exitcall.exit")))
-/* For assembly routines */
-#define __INIT .section ".text.init","ax"
-#define __FINIT .previous
-#define __INITDATA .section ".data.init","aw"
-
/**
* module_init() - driver initialization entry point
* @x: function to be run at kernel boot time or module insertion
@@ -131,15 +132,9 @@
#else
-#define __init
#define __exit
-#define __initdata
#define __exitdata
#define __initcall(fn)
-/* For assembly routines */
-#define __INIT
-#define __FINIT
-#define __INITDATA
/* These macros create a dummy inline: gcc 2.9x does not count alias
as usage, hence the `unused function' warning when __init functions
diff -urN -X /usr/share/dontdiff linux.vanilla/include/linux/vmalloc.h linux/include/linux/vmalloc.h
--- linux.vanilla/include/linux/vmalloc.h Wed May 8 10:01:48 2002
+++ linux/include/linux/vmalloc.h Wed May 8 10:34:16 2002
@@ -24,6 +24,7 @@
extern void vmfree_area_pages(unsigned long address, unsigned long size);
extern int vmalloc_area_pages(unsigned long address, unsigned long size,
int gfp_mask, pgprot_t prot);
+extern int shrink_vm_area(void * addr, unsigned long size);
/*
* Allocate any pages
diff -urN -X /usr/share/dontdiff linux.vanilla/kernel/ksyms.c linux/kernel/ksyms.c
--- linux.vanilla/kernel/ksyms.c Wed May 8 10:01:45 2002
+++ linux/kernel/ksyms.c Wed May 8 10:06:36 2002
@@ -108,6 +108,7 @@
EXPORT_SYMBOL(vfree);
EXPORT_SYMBOL(__vmalloc);
EXPORT_SYMBOL(vmalloc_to_page);
+EXPORT_SYMBOL(shrink_vm_area);
EXPORT_SYMBOL(mem_map);
EXPORT_SYMBOL(remap_page_range);
EXPORT_SYMBOL(max_mapnr);
diff -urN -X /usr/share/dontdiff linux.vanilla/kernel/module.c linux/kernel/module.c
--- linux.vanilla/kernel/module.c Wed May 8 10:01:45 2002
+++ linux/kernel/module.c Wed May 8 10:06:36 2002
@@ -558,6 +558,13 @@
error = -EBUSY;
goto err0;
}
+
+ /* It's time to throw away .init sections */
+ if (mod->runsize) {
+ if (!module_remap(mod, mod->runsize))
+ mod->size = mod->runsize;
+ }
+
atomic_dec(&mod->uc.usecount);
/* And set it running. */
diff -urN -X /usr/share/dontdiff linux.vanilla/mm/vmalloc.c linux/mm/vmalloc.c
--- linux.vanilla/mm/vmalloc.c Wed May 8 10:01:46 2002
+++ linux/mm/vmalloc.c Wed May 8 10:06:36 2002
@@ -174,6 +174,44 @@
return ret;
}
+int shrink_vm_area(void * addr, unsigned long size)
+{
+ int ret;
+ struct vm_struct **p, *tmp;
+
+ if (!addr || !(unsigned long)addr & (PAGE_SIZE - 1) || !size)
+ return -EINVAL;
+
+ size = PAGE_ALIGN(size) + PAGE_SIZE;
+
+ ret = 0;
+ write_lock(&vmlist_lock);
+ for (p = &vmlist; (tmp = *p) ; p = &tmp->next) {
+ if (tmp->addr == addr) {
+ int delta;
+ unsigned long end;
+
+ if (size > tmp->size) {
+ ret = -EINVAL;
+ break;
+ }
+ if (size == tmp->size)
+ break;
+
+ delta = tmp->size - size;
+ end = (unsigned long) tmp->addr + size - PAGE_SIZE;
+
+ tmp->size = size + PAGE_SIZE;
+ vmfree_area_pages(VMALLOC_VMADDR(end), delta);
+
+ break;
+ }
+ }
+
+ write_unlock(&vmlist_lock);
+ return ret;
+}
+
struct vm_struct * get_vm_area(unsigned long size, unsigned long flags)
{
unsigned long addr;
[-- Attachment #2: Type: application/pgp-signature, Size: 232 bytes --]
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [PATCH][RFC] __init and friends support for loadable modules
2002-05-08 10:29 [PATCH][RFC] __init and friends support for loadable modules Andrey Panin
@ 2002-05-08 14:02 ` Keith Owens
2002-05-09 7:45 ` Rusty Russell
0 siblings, 1 reply; 3+ messages in thread
From: Keith Owens @ 2002-05-08 14:02 UTC (permalink / raw)
To: Andrey Panin; +Cc: linux-kernel
On Wed, 8 May 2002 14:29:33 +0400,
Andrey Panin <pazke@orbita1.ru> wrote:
>attached patch adds support for freeing .init sections of loadable modules
>after init_module() function exits. Modutils have support for this since 19=
>98,
>but kernel support didn't exist.
The main reason I have not done this myself is the interaction between
freeing code areas and the exception and unwind tables. When you free
code, you should remove or nullify the related unwind and exception
entries. Another module could be loaded into the area that used to
contain init code and it would then be mapped by the first module's
tables, oops.
Fixing exception tables is relatively easy, search_exception_table()
can check if the address fits within the module (taking runsize into
account) before running the exception table. Unwind data is harder, it
is all architecture specific. Your patch will not be complete without
fixing all tables that point at module code. Don't forget the MIPS DBE
table.
Rusty and I plan to completely redo module loading and unloading and
the corresponding modutils support in 2.5. That will (hopefully)
include additional features such as per-node replication of pure module
areas for NUMA boxes. For me, the ability to free .init text and data
from modules falls into the category of "would be nice but the gain is
not worth the bother just for 2.4".
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH][RFC] __init and friends support for loadable modules
2002-05-08 14:02 ` Keith Owens
@ 2002-05-09 7:45 ` Rusty Russell
0 siblings, 0 replies; 3+ messages in thread
From: Rusty Russell @ 2002-05-09 7:45 UTC (permalink / raw)
To: Keith Owens; +Cc: pazke, linux-kernel
On Thu, 09 May 2002 00:02:07 +1000
Keith Owens <kaos@ocs.com.au> wrote:
> On Wed, 8 May 2002 14:29:33 +0400,
> Andrey Panin <pazke@orbita1.ru> wrote:
> >attached patch adds support for freeing .init sections of loadable modules
> >after init_module() function exits. Modutils have support for this since 19=
> >98,
> >but kernel support didn't exist.
>
> The main reason I have not done this myself is the interaction between
> freeing code areas and the exception and unwind tables. When you free
> code, you should remove or nullify the related unwind and exception
> entries. Another module could be loaded into the area that used to
> contain init code and it would then be mapped by the first module's
> tables, oops.
Excellent catch, Keith. I missed this in my current implementation, and
will have to patch the exception tables in the init release callback. I
also get around this because I allow archs to refuse to have separate
init and core sections if they want.
BTW, I just got ppc64 in-kernel relocations working. I am starting on
ia64, in the theory that if you can do ia64, you can do anything.
Cheers,
Rusty.
--
there are those who do and those who hang on and you don't see too
many doers quoting their contemporaries. -- Larry McVoy
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2002-05-09 7:43 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-05-08 10:29 [PATCH][RFC] __init and friends support for loadable modules Andrey Panin
2002-05-08 14:02 ` Keith Owens
2002-05-09 7:45 ` Rusty Russell
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox