2002-11-05 00:15:43

by Rusty Russell

[permalink] [raw]
Subject: [PATCH] Module loader against 2.5.46: 1/9

Stands on its own: adds KBUILD_MODNAME to objects.

Linus, please apply.
--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.

Name: KBUILD_MODNAME define for build system
Author: Kai Germaschewski
Status: Tested on 2.5.45

D: This patch adds a -DKBUILD_MODNAME to the kernel compile, which
D: contains the base of the module name which is being built.
D:
D: - Some sreorganization of the c_flags since they're needed for
D: generating modversions (.ver) and compiling
D: - Use the right KBUILD_MODNAME also when the user just wants a .i/.s/.lst
D: file for debugging and also when generating modversions
D: - It looks like with your current approach you can't have a ',' or '-' in
D: KBUILD_MODNAME - however, that means that KBUILD_MODNAME is not quite
D: right for passing module parameters for built-in modules on the command
D: line, it would be confusing to pass parameters for ide-cd as
D: ide_cd.foo=whatever. So that part could use a little more thought.
D: - If you think your module_names trick makes a noticable difference, feel
D: free to re-add it.
D: - It's possible that objects are linked into more than one module - I
D: suppose this shouldn't be a problem, since these objects hopefully
D: don't have a module_init() nor do they export symbols. Not sure if your
D: patch did handle this.
D:
D: --Kai

diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .31872-linux-2.5.45/net/unix/af_unix.c .31872-linux-2.5.45.updated/net/unix/af_unix.c
--- .31872-linux-2.5.45/net/unix/af_unix.c 2002-10-16 15:01:28.000000000 +1000
+++ .31872-linux-2.5.45.updated/net/unix/af_unix.c 2002-10-30 13:51:12.000000000 +1100
@@ -79,6 +79,8 @@
* with BSD names.
*/

+#undef unix /* KBUILD_MODNAME */
+
#include <linux/module.h>
#include <linux/config.h>
#include <linux/kernel.h>
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .31872-linux-2.5.45/scripts/Makefile.build .31872-linux-2.5.45.updated/scripts/Makefile.build
--- .31872-linux-2.5.45/scripts/Makefile.build 2002-10-30 12:53:10.000000000 +1100
+++ .31872-linux-2.5.45.updated/scripts/Makefile.build 2002-10-30 13:54:32.000000000 +1100
@@ -54,6 +54,7 @@ modkern_cflags := $(CFLAGS_KERNEL)

$(real-objs-m) : modkern_cflags := $(CFLAGS_MODULE)
$(real-objs-m:.o=.i) : modkern_cflags := $(CFLAGS_MODULE)
+$(real-objs-m:.o=.s) : modkern_cflags := $(CFLAGS_MODULE)
$(real-objs-m:.o=.lst): modkern_cflags := $(CFLAGS_MODULE)

$(export-objs) : export_flags := $(EXPORT_FLAGS)
@@ -61,10 +62,17 @@ $(export-objs:.o=.i) : export_flags :
$(export-objs:.o=.s) : export_flags := $(EXPORT_FLAGS)
$(export-objs:.o=.lst): export_flags := $(EXPORT_FLAGS)

-c_flags = -Wp,-MD,$(depfile) $(CFLAGS) $(NOSTDINC_FLAGS) \
- $(modkern_cflags) $(EXTRA_CFLAGS) $(CFLAGS_$(*F).o) \
- -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) \
- $(export_flags)
+# Default for not multi-part modules
+modname = $(*F)
+
+$(multi-objs-m) : modname = $(modname-multi)
+$(multi-objs-m:.o=.i) : modname = $(modname-multi)
+$(multi-objs-m:.o=.s) : modname = $(modname-multi)
+$(multi-objs-m:.o=.lst) : modname = $(modname-multi)
+$(multi-objs-y) : modname = $(modname-multi)
+$(multi-objs-y:.o=.i) : modname = $(modname-multi)
+$(multi-objs-y:.o=.s) : modname = $(modname-multi)
+$(multi-objs-y:.o=.lst) : modname = $(modname-multi)

quiet_cmd_cc_s_c = CC $@
cmd_cc_s_c = $(CC) $(c_flags) -S -o $@ $<
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .31872-linux-2.5.45/scripts/Makefile.lib .31872-linux-2.5.45.updated/scripts/Makefile.lib
--- .31872-linux-2.5.45/scripts/Makefile.lib 2002-10-30 12:53:10.000000000 +1100
+++ .31872-linux-2.5.45.updated/scripts/Makefile.lib 2002-10-30 13:52:07.000000000 +1100
@@ -5,6 +5,8 @@
# Standard vars

comma := ,
+empty :=
+space := $(empty) $(empty)

# Figure out what we need to build from the various variables
# ===========================================================================
@@ -40,11 +40,13 @@ __obj-m = $(filter-out export.o,$(obj-m)
# if $(foo-objs) exists, foo.o is a composite object
multi-used-y := $(sort $(foreach m,$(__obj-y), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))), $(m))))
multi-used-m := $(sort $(foreach m,$(__obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))), $(m))))
+multi-used := $(multi-used-y) $(multi-used-m)

# Build list of the parts of our composite objects, our composite
# objects depend on those (obviously)
multi-objs-y := $(foreach m, $(multi-used-y), $($(m:.o=-objs)) $($(m:.o=-y)))
multi-objs-m := $(foreach m, $(multi-used-m), $($(m:.o=-objs)) $($(m:.o=-y)))
+multi-objs := $(multi-objs-y) $(multi-objs-m)

# $(subdir-obj-y) is the list of objects in $(obj-y) which do not live
# in the local directory
@@ -84,6 +86,23 @@ host-progs-multi-objs := $(addprefix $(o
# contain a comma
depfile = $(subst $(comma),_,$(@D)/.$(@F).d)

+# These flags are needed for modversions and compiling, so we define them here
+# already
+# $(modname_flags) #defines KBUILD_MODNAME as the name of the module it will
+# end up in (or would, if it gets compiled in)
+# Note: It's possible that one object gets potentially linked into more
+# than one module. In that case KBUILD_MODNAME will be set to foo_bar,
+# where foo and bar are the name of the modules.
+basename_flags = -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F)))
+modname_flags = -DKBUILD_MODNAME=$(subst $(comma),_,$(subst -,_,$(modname)))
+c_flags = -Wp,-MD,$(depfile) $(CFLAGS) $(NOSTDINC_FLAGS) \
+ $(modkern_cflags) $(EXTRA_CFLAGS) $(CFLAGS_$(*F).o) \
+ $(basename_flags) $(modname_flags) $(export_flags)
+
+# Finds the multi-part object the current object will be linked into
+modname-multi = $(subst $(space),_,$(strip $(foreach m,$(multi-used),\
+ $(if $(filter $(*F).o,$($(m:.o=-objs))),$(m:.o=)))))
+
# Shipped files
# ===========================================================================

diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .31872-linux-2.5.45/scripts/Makefile.modver .31872-linux-2.5.45.updated/scripts/Makefile.modver
--- .31872-linux-2.5.45/scripts/Makefile.modver 2002-10-30 12:53:10.000000000 +1100
+++ .31872-linux-2.5.45.updated/scripts/Makefile.modver 2002-10-30 13:53:37.000000000 +1100
@@ -48,11 +48,10 @@ CFLAGS_MODULE := $(filter-out -include i
$(addprefix $(MODVERDIR)/,$(real-objs-y:.o=.ver)): modkern_cflags := $(CFLAGS_KERNEL)
$(addprefix $(MODVERDIR)/,$(real-objs-m:.o=.ver)): modkern_cflags := $(CFLAGS_MODULE)
$(addprefix $(MODVERDIR)/,$(export-objs:.o=.ver)): export_flags := -D__GENKSYMS__
+# Default for not multi-part modules
+modname = $(*F)

-c_flags = -Wp,-MD,$(depfile) $(CFLAGS) $(NOSTDINC_FLAGS) \
- $(modkern_cflags) $(EXTRA_CFLAGS) $(CFLAGS_$(*F).o) \
- -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) \
- $(export_flags)
+$(addprefix $(MODVERDIR)/,$(multi-objs:.o=.ver)) : modname = $(modname-multi)

# Our objects only depend on modversions.h, not on the individual .ver
# files (fix-dep filters them), so touch modversions.h if any of the .ver


2002-11-05 00:45:49

by Rusty Russell

[permalink] [raw]
Subject: [PATCH] Module loader against 2.5.46: 8/9

Wedge to support old-style "MODULE_PARM" decls, by turning them into
the equivalent PARAM table at load time.

With this, module parameters work again on all modules.
Rusty.

Name: MODULE_PARM support for older modules
Author: Rusty Russell
Status: Experimental
Depends: Module/param-modules.patch.gz
Depends: Module/forceunload.patch.gz

D: This is the backwards compatibility code for MODULE_PARM.

diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .17025-linux-2.5.45/include/linux/module.h .17025-linux-2.5.45.updated/include/linux/module.h
--- .17025-linux-2.5.45/include/linux/module.h 2002-11-01 12:03:21.000000000 +1100
+++ .17025-linux-2.5.45.updated/include/linux/module.h 2002-11-01 12:03:57.000000000 +1100
@@ -15,6 +15,7 @@
#include <linux/compiler.h>
#include <linux/cache.h>
#include <linux/kmod.h>
+#include <linux/stringify.h>
#include <asm/module.h>
#include <asm/uaccess.h> /* For struct exception_table_entry */

@@ -274,6 +275,17 @@ extern spinlock_t modlist_lock;
#define __MOD_DEC_USE_COUNT(mod) module_put(mod)
#define SET_MODULE_OWNER(dev) ((dev)->owner = THIS_MODULE)

+struct obsolete_modparm { char name[64]; char type[64]; void *addr; };
+#ifdef MODULE
+/* DEPRECATED: Do not use. */
+#define MODULE_PARM(var,type) \
+struct obsolete_modparm __parm_##var __attribute__((section(".obsparm"))) = \
+{ __stringify(var), type };
+
+#else
+#define MODULE_PARM(var,type)
+#endif
+
/* People do this inside their init routines, when the module isn't
"live" yet. They should no longer be doing that, but
meanwhile... */
@@ -286,11 +298,11 @@ extern spinlock_t modlist_lock;
#endif
#define MOD_DEC_USE_COUNT module_put(THIS_MODULE)
#define try_inc_mod_count(mod) try_module_get(mod)
-#define MODULE_PARM(parm,string)
#define EXPORT_NO_SYMBOLS
extern int module_dummy_usage;
#define GET_USE_COUNT(module) (module_dummy_usage)
#define MOD_IN_USE 0
+#define __MODULE_STRING(x) __stringify(x)
#define __mod_between(a_start, a_len, b_start, b_len) \
(((a_start) >= (b_start) && (a_start) <= (b_start)+(b_len)) \
|| ((a_start)+(a_len) >= (b_start) \
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .17025-linux-2.5.45/init/Kconfig .17025-linux-2.5.45.updated/init/Kconfig
--- .17025-linux-2.5.45/init/Kconfig 2002-11-01 12:03:24.000000000 +1100
+++ .17025-linux-2.5.45.updated/init/Kconfig 2002-11-01 12:06:00.000000000 +1100
@@ -135,6 +135,14 @@ config MODULE_FORCE_UNLOAD
rmmod). This is mainly for kernel developers and desparate users.
If unsure, say N.

+config OBSOLETE_MODPARM
+ bool
+ default y
+ help
+ Without this option you will not be able to use module parameters on
+ modules which have not been converted to the new module parameter
+ system yet. If unsure, say Y.
+
config KMOD
bool "Kernel module loader"
depends on MODULES
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .17025-linux-2.5.45/kernel/module.c .17025-linux-2.5.45.updated/kernel/module.c
--- .17025-linux-2.5.45/kernel/module.c 2002-11-01 12:03:24.000000000 +1100
+++ .17025-linux-2.5.45.updated/kernel/module.c 2002-11-01 12:03:57.000000000 +1100
@@ -500,6 +500,129 @@ sys_delete_module(const char *name_user,

#endif /* CONFIG_MODULE_UNLOAD */

+#ifdef CONFIG_OBSOLETE_MODPARM
+static int param_set_byte(const char *val, struct kernel_param *kp)
+{
+ char *endp;
+ long l;
+
+ if (!val) return -EINVAL;
+ l = simple_strtol(val, &endp, 0);
+ if (endp == val || *endp || ((char)l != l))
+ return -EINVAL;
+ *((char *)kp->arg) = l;
+ return 0;
+}
+
+static int param_string(const char *name, const char *val,
+ unsigned int min, unsigned int max,
+ char *dest)
+{
+ if (strlen(val) < min || strlen(val) > max) {
+ printk(KERN_ERR
+ "Parameter %s length must be %u-%u characters\n",
+ name, min, max);
+ return -EINVAL;
+ }
+ strcpy(dest, val);
+ return 0;
+}
+
+extern int set_obsolete(const char *val, struct kernel_param *kp)
+{
+ unsigned int min, max;
+ char *p, *endp;
+ struct obsolete_modparm *obsparm = kp->arg;
+
+ if (!val) {
+ printk(KERN_ERR "Parameter %s needs an argument\n", kp->name);
+ return -EINVAL;
+ }
+
+ /* type is: [min[-max]]{b,h,i,l,s} */
+ p = obsparm->type;
+ min = simple_strtol(p, &endp, 10);
+ if (endp == obsparm->type)
+ min = max = 1;
+ else if (*endp == '-') {
+ p = endp+1;
+ max = simple_strtol(p, &endp, 10);
+ } else
+ max = min;
+ switch (*endp) {
+ case 'b':
+ return param_array(kp->name, val, min, max, obsparm->addr,
+ 1, param_set_byte);
+ case 'h':
+ return param_array(kp->name, val, min, max, obsparm->addr,
+ sizeof(short), param_set_short);
+ case 'i':
+ return param_array(kp->name, val, min, max, obsparm->addr,
+ sizeof(int), param_set_int);
+ case 'l':
+ return param_array(kp->name, val, min, max, obsparm->addr,
+ sizeof(long), param_set_long);
+ case 's':
+ return param_string(kp->name, val, min, max, obsparm->addr);
+ }
+ printk(KERN_ERR "Unknown obsolete parameter type %s\n", obsparm->type);
+ return -EINVAL;
+}
+
+static int obsolete_params(const char *name,
+ char *args,
+ struct obsolete_modparm obsparm[],
+ unsigned int num,
+ Elf_Shdr *sechdrs,
+ unsigned int symindex,
+ const char *strtab)
+{
+ struct kernel_param *kp;
+ unsigned int i;
+ int ret;
+
+ kp = kmalloc(sizeof(kp[0]) * num, GFP_KERNEL);
+ if (!kp)
+ return -ENOMEM;
+
+ for (i = 0; i < num; i++) {
+ kp[i].name = obsparm[i].name;
+ kp[i].perm = 000;
+ kp[i].set = set_obsolete;
+ kp[i].get = NULL;
+ obsparm[i].addr
+ = (void *)find_local_symbol(sechdrs, symindex, strtab,
+ obsparm[i].name);
+ if (!obsparm[i].addr) {
+ printk("%s: falsely claims to have parameter %s\n",
+ name, obsparm[i].name);
+ ret = -EINVAL;
+ goto out;
+ }
+ kp[i].arg = &obsparm[i];
+ }
+
+ ret = parse_args(name, args, kp, num, NULL);
+ out:
+ kfree(kp);
+ return ret;
+}
+#else
+static int obsolete_params(const char *name,
+ char *args,
+ struct obsolete_modparm obsparm[],
+ unsigned int num,
+ Elf_Shdr *sechdrs,
+ unsigned int symindex,
+ const char *strtab)
+{
+ if (num != 0)
+ printk(KERN_WARNING "%s: Ignoring obsolete parameters\n",
+ name);
+ return 0;
+}
+#endif /* CONFIG_OBSOLETE_MODPARM */
+
/* Find an symbol for this module (ie. resolve internals first).
It we find one, record usage. Must be holding module_mutex. */
unsigned long find_symbol_internal(Elf_Shdr *sechdrs,
@@ -811,7 +934,7 @@ static struct module *load_module(void *
Elf_Shdr *sechdrs;
char *secstrings;
unsigned int i, symindex, exportindex, strindex, setupindex, exindex,
- modnameindex;
+ modnameindex, obsparmindex;
long arglen;
unsigned long common_length;
struct sizes sizes, used;
@@ -849,7 +972,7 @@ static struct module *load_module(void *

/* May not export symbols, or have setup params, so these may
not exist */
- exportindex = setupindex = 0;
+ exportindex = setupindex = obsparmindex = 0;

/* And these should exist, but gcc whinges if we don't init them */
symindex = strindex = exindex = modnameindex = 0;
@@ -885,6 +1008,11 @@ static struct module *load_module(void *
/* Exception table */
DEBUGP("Exception table found in section %u\n", i);
exindex = i;
+ } else if (strcmp(secstrings+sechdrs[i].sh_name, ".obsparm")
+ == 0) {
+ /* Obsolete MODULE_PARM() table */
+ DEBUGP("Obsolete param found in section %u\n", i);
+ obsparmindex = i;
}
#ifndef CONFIG_MODULE_UNLOAD
/* Don't load .exit sections */
@@ -1002,13 +1130,23 @@ static struct module *load_module(void *
if (err < 0)
goto cleanup;

- /* Size of section 0 is 0, so this works well if no params */
- err = parse_args(mod->args,
- (struct kernel_param *)
- sechdrs[setupindex].sh_offset,
- sechdrs[setupindex].sh_size
- / sizeof(struct kernel_param),
- NULL);
+ if (obsparmindex) {
+ err = obsolete_params(mod->name, mod->args,
+ (struct obsolete_modparm *)
+ sechdrs[obsparmindex].sh_offset,
+ sechdrs[obsparmindex].sh_size
+ / sizeof(struct obsolete_modparm),
+ sechdrs, symindex,
+ (char *)sechdrs[strindex].sh_offset);
+ } else {
+ /* Size of section 0 is 0, so this works well if no params */
+ err = parse_args(mod->name, mod->args,
+ (struct kernel_param *)
+ sechdrs[setupindex].sh_offset,
+ sechdrs[setupindex].sh_size
+ / sizeof(struct kernel_param),
+ NULL);
+ }
if (err < 0)
goto cleanup;


--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.

2002-11-05 00:45:41

by Rusty Russell

[permalink] [raw]
Subject: [PATCH] Module loader against 2.5.46: 7/9

Forced unload for modules "rmmod -f". Taints the kernel, but
sometimes when you're developing or desperate, it's the best option.

Note that normal module unloading is still supported: this allows you
to unload modules with non-zero refcounts, no unload routine, or which
have been marked "unsafe" by detecting racy usages.

Linus, please apply,
Rusty.
--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.

Name: Forced Module Unload
Author: Rusty Russell
Status: Experimental
Depends: Module/module.patch.gz

D: Allows the (very dangerous!) "rmmod -f" for kernel developers and
D: desperate people.

diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .9002-linux-2.5.45/include/linux/kernel.h .9002-linux-2.5.45.updated/include/linux/kernel.h
--- .9002-linux-2.5.45/include/linux/kernel.h 2002-10-19 17:48:10.000000000 +1000
+++ .9002-linux-2.5.45.updated/include/linux/kernel.h 2002-11-01 11:52:04.000000000 +1100
@@ -102,6 +102,7 @@ extern const char *print_tainted(void);
#define TAINT_PROPRIETORY_MODULE (1<<0)
#define TAINT_FORCED_MODULE (1<<1)
#define TAINT_UNSAFE_SMP (1<<2)
+#define TAINT_FORCED_RMMOD (1<<3)

extern void dump_stack(void);

diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .9002-linux-2.5.45/init/Kconfig .9002-linux-2.5.45.updated/init/Kconfig
--- .9002-linux-2.5.45/init/Kconfig 2002-11-01 11:51:08.000000000 +1100
+++ .9002-linux-2.5.45.updated/init/Kconfig 2002-11-01 11:55:00.000000000 +1100
@@ -125,6 +125,16 @@ config MODULE_UNLOAD
anyway), which makes your kernel slightly smaller and
simpler. If unsure, say Y.

+config MODULE_FORCE_UNLOAD
+ bool "Forced module unloading"
+ depends on MODULES && EXPERIMENTAL
+ help
+ This option allows you to force a module to unload, even if the
+ kernel believes it is unsafe: the kernel will remove the module
+ without waiting for anyone to stop using it (using the -f option to
+ rmmod). This is mainly for kernel developers and desparate users.
+ If unsure, say N.
+
config KMOD
bool "Kernel module loader"
depends on MODULES
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .9002-linux-2.5.45/kernel/module.c .9002-linux-2.5.45.updated/kernel/module.c
--- .9002-linux-2.5.45/kernel/module.c 2002-11-01 11:51:08.000000000 +1100
+++ .9002-linux-2.5.45.updated/kernel/module.c 2002-11-01 11:52:04.000000000 +1100
@@ -335,12 +335,24 @@ static unsigned int module_refcount(stru
/* This exists whether we can unload or not */
static void free_module(struct module *mod);

+#ifdef CONFIG_MODULE_FORCE_UNLOAD
+static inline int try_force(unsigned int flags)
+{
+ return (flags & O_TRUNC);
+}
+#else
+static inline int try_force(unsigned int flags)
+{
+ return 0;
+}
+#endif /* CONFIG_MODULE_FORCE_UNLOAD */
+
asmlinkage long
sys_delete_module(const char *name_user, unsigned int flags)
{
struct module *mod;
char name[MODULE_NAME_LEN];
- int ret;
+ int ret, forced = 0;

if (!capable(CAP_SYS_MODULE))
return -EPERM;
@@ -358,24 +370,29 @@ sys_delete_module(const char *name_user,
goto out;
}

+ if (!list_empty(&mod->modules_which_use_me)) {
+ /* Other modules depend on us: get rid of them first. */
+ ret = -EWOULDBLOCK;
+ goto out;
+ }
+
/* Already dying? */
if (!mod->live) {
+ /* FIXME: if (force), slam module count and wake up
+ waiter --RR */
DEBUGP("%s already dying\n", mod->name);
ret = -EBUSY;
goto out;
}

if (!mod->exit || mod->unsafe) {
- /* This module can't be removed */
- ret = -EBUSY;
- goto out;
- }
- if (!list_empty(&mod->modules_which_use_me)) {
- /* Other modules depend on us: get rid of them first. */
- ret = -EWOULDBLOCK;
- goto out;
+ forced = try_force(flags);
+ if (!forced) {
+ /* This module can't be removed */
+ ret = -EBUSY;
+ goto out;
+ }
}
-
/* Stop the machine so refcounts can't move: irqs disabled. */
DEBUGP("Stopping refcounts...\n");
ret = stop_refcounts();
@@ -383,9 +400,11 @@ sys_delete_module(const char *name_user,
goto out;

/* If it's not unused, quit unless we are told to block. */
- if ((flags & O_NONBLOCK) && module_refcount(mod) != 0)
- ret = -EWOULDBLOCK;
- else {
+ if ((flags & O_NONBLOCK) && module_refcount(mod) != 0) {
+ forced = try_force(flags);
+ if (!forced)
+ ret = -EWOULDBLOCK;
+ } else {
mod->waiter = current;
mod->live = 0;
}
@@ -394,6 +413,9 @@ sys_delete_module(const char *name_user,
if (ret != 0)
goto out;

+ if (forced)
+ goto destroy;
+
/* Since we might sleep for some time, drop the semaphore first */
up(&module_mutex);
for (;;) {
@@ -408,10 +430,11 @@ sys_delete_module(const char *name_user,
DEBUGP("Regrabbing mutex...\n");
down(&module_mutex);

+ destroy:
/* Final destruction now noone is using it. */
- mod->exit();
+ if (mod->exit)
+ mod->exit();
free_module(mod);
- ret = 0;

out:
up(&module_mutex);

2002-11-05 00:48:13

by Rusty Russell

[permalink] [raw]
Subject: [PATCH] Module loader against 2.5.46: 4/9

Now we reintroduce features: first a trivial patch to implement
"strcspn" for module parameter parsing.

Linus, please apply,
Rusty.
--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.

Name: strcspn patch
Author: Rusty Russell
Status: Experimental

D: This patch implements a generic strcspn.

diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .17889-2.5.36-param.pre/include/linux/string.h .17889-2.5.36-param/include/linux/string.h
--- .17889-2.5.36-param.pre/include/linux/string.h 2002-06-06 21:38:40.000000000 +1000
+++ .17889-2.5.36-param/include/linux/string.h 2002-09-19 16:15:20.000000000 +1000
@@ -15,7 +15,7 @@ extern "C" {
extern char * strpbrk(const char *,const char *);
extern char * strsep(char **,const char *);
extern __kernel_size_t strspn(const char *,const char *);
-
+extern __kernel_size_t strcspn(const char *,const char *);

/*
* Include machine specific inline routines
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .17889-2.5.36-param.pre/lib/string.c .17889-2.5.36-param/lib/string.c
--- .17889-2.5.36-param.pre/lib/string.c 2002-05-24 15:20:35.000000000 +1000
+++ .17889-2.5.36-param/lib/string.c 2002-09-19 16:15:20.000000000 +1000
@@ -272,6 +272,29 @@ size_t strspn(const char *s, const char
}
#endif

+/**
+ * strcspn - Calculate the length of the initial substring of @s which does
+ * not contain letters in @reject
+ * @s: The string to be searched
+ * @reject: The string to avoid
+ */
+size_t strcspn(const char *s, const char *reject)
+{
+ const char *p;
+ const char *r;
+ size_t count = 0;
+
+ for (p = s; *p != '\0'; ++p) {
+ for (r = reject; *r != '\0'; ++r) {
+ if (*p == *r)
+ return count;
+ }
+ ++count;
+ }
+
+ return count;
+}
+
#ifndef __HAVE_ARCH_STRPBRK
/**
* strpbrk - Find the first occurrence of a set of characters

2002-11-05 00:47:41

by Rusty Russell

[permalink] [raw]
Subject: [PATCH] Module loader against 2.5.46: 3/9

Linus, please apply. Make x86 compile, and their modules work.

Rusty.

Name: New Module Loader Base: x86 support
Author: Rusty Russell
Status: Tested on 2.5.45
Depends: Module/module.patch.gz

D: This patch provides basic x86 support for modules.

diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .9540-2.5.45-module-i386.pre/arch/i386/kernel/Makefile .9540-2.5.45-module-i386/arch/i386/kernel/Makefile
--- .9540-2.5.45-module-i386.pre/arch/i386/kernel/Makefile 2002-10-19 17:47:49.000000000 +1000
+++ .9540-2.5.45-module-i386/arch/i386/kernel/Makefile 2002-11-01 11:15:05.000000000 +1100
@@ -29,6 +29,7 @@ obj-$(CONFIG_SOFTWARE_SUSPEND) += suspen
obj-$(CONFIG_X86_NUMAQ) += numaq.o
obj-$(CONFIG_PROFILING) += profile.o
obj-$(CONFIG_EDD) += edd.o
+obj-$(CONFIG_MODULES) += module.o

EXTRA_AFLAGS := -traditional

diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .9540-2.5.45-module-i386.pre/arch/i386/kernel/entry.S .9540-2.5.45-module-i386/arch/i386/kernel/entry.S
--- .9540-2.5.45-module-i386.pre/arch/i386/kernel/entry.S 2002-10-31 12:36:19.000000000 +1100
+++ .9540-2.5.45-module-i386/arch/i386/kernel/entry.S 2002-11-01 11:15:05.000000000 +1100
@@ -610,10 +610,10 @@ ENTRY(sys_call_table)
.long sys_adjtimex
.long sys_mprotect /* 125 */
.long sys_sigprocmask
- .long sys_create_module
+ .long sys_ni_syscall /* old "create_module" */
.long sys_init_module
.long sys_delete_module
- .long sys_get_kernel_syms /* 130 */
+ .long sys_ni_syscall /* 130: old "get_kernel_syms" */
.long sys_quotactl
.long sys_getpgid
.long sys_fchdir
@@ -650,7 +650,7 @@ ENTRY(sys_call_table)
.long sys_setresuid16
.long sys_getresuid16 /* 165 */
.long sys_vm86
- .long sys_query_module
+ .long sys_ni_syscall /* Old sys_query_module */
.long sys_poll
.long sys_nfsservctl
.long sys_setresgid16 /* 170 */
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .9540-2.5.45-module-i386.pre/arch/i386/kernel/module.c .9540-2.5.45-module-i386/arch/i386/kernel/module.c
--- .9540-2.5.45-module-i386.pre/arch/i386/kernel/module.c 1970-01-01 10:00:00.000000000 +1000
+++ .9540-2.5.45-module-i386/arch/i386/kernel/module.c 2002-11-01 11:15:05.000000000 +1100
@@ -0,0 +1,130 @@
+/* Kernel module help for i386.
+ Copyright (C) 2001 Rusty Russell.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+#include <linux/module.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(fmt , ...)
+#endif
+
+static void *alloc_and_zero(unsigned long size)
+{
+ void *ret;
+
+ /* We handle the zero case fine, unlike vmalloc */
+ if (size == 0)
+ return NULL;
+
+ ret = vmalloc(size);
+ if (!ret) ret = ERR_PTR(-ENOMEM);
+ else memset(ret, 0, size);
+
+ return ret;
+}
+
+/* Free memory returned from module_core_alloc/module_init_alloc */
+void module_free(struct module *mod, void *module_region)
+{
+ vfree(module_region);
+ /* FIXME: If module_region == mod->init_region, trim exception
+ table entries. */
+}
+
+void *module_core_alloc(const Elf32_Ehdr *hdr,
+ const Elf32_Shdr *sechdrs,
+ const char *secstrings,
+ struct module *module)
+{
+ return alloc_and_zero(module->core_size);
+}
+
+void *module_init_alloc(const Elf32_Ehdr *hdr,
+ const Elf32_Shdr *sechdrs,
+ const char *secstrings,
+ struct module *module)
+{
+ return alloc_and_zero(module->init_size);
+}
+
+int apply_relocate(Elf32_Shdr *sechdrs,
+ const char *strtab,
+ unsigned int symindex,
+ unsigned int relsec,
+ struct module *me)
+{
+ unsigned int i;
+ Elf32_Rel *rel = (void *)sechdrs[relsec].sh_offset;
+ Elf32_Sym *sym;
+ uint32_t *location;
+
+ DEBUGP("Applying relocate section %u to %u\n", relsec,
+ sechdrs[relsec].sh_info);
+ for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+ /* This is where to make the change */
+ location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_offset
+ + rel[i].r_offset;
+ /* This is the symbol it is referring to */
+ sym = (Elf32_Sym *)sechdrs[symindex].sh_offset
+ + ELF32_R_SYM(rel[i].r_info);
+ if (!sym->st_value) {
+ printk(KERN_WARNING "%s: Unknown symbol %s\n",
+ me->name, strtab + sym->st_name);
+ return -ENOENT;
+ }
+
+ switch (ELF32_R_TYPE(rel[i].r_info)) {
+ case R_386_32:
+ /* We add the value into the location given */
+ *location += sym->st_value;
+ break;
+ case R_386_PC32:
+ /* Add the value, subtract its postition */
+ *location += sym->st_value - (uint32_t)location;
+ break;
+ default:
+ printk(KERN_ERR "module %s: Unknown relocation: %u\n",
+ me->name, ELF32_R_TYPE(rel[i].r_info));
+ return -ENOEXEC;
+ }
+ }
+ return 0;
+}
+
+int apply_relocate_add(Elf32_Shdr *sechdrs,
+ const char *strtab,
+ unsigned int symindex,
+ unsigned int relsec,
+ struct module *me)
+{
+ printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n",
+ me->name);
+ return -ENOEXEC;
+}
+
+int module_finalize(const Elf_Ehdr *hdr,
+ const Elf_Shdr *sechdrs,
+ struct module *me)
+{
+ return 0;
+}
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .9540-2.5.45-module-i386.pre/arch/i386/kernel/traps.c .9540-2.5.45-module-i386/arch/i386/kernel/traps.c
--- .9540-2.5.45-module-i386.pre/arch/i386/kernel/traps.c 2002-10-16 15:01:12.000000000 +1000
+++ .9540-2.5.45-module-i386/arch/i386/kernel/traps.c 2002-11-01 11:15:05.000000000 +1100
@@ -95,7 +95,8 @@ static int kstack_depth_to_print = 24;

#ifdef CONFIG_MODULES

-extern struct module kernel_module;
+/* FIXME: Accessed without a lock --RR */
+extern struct list_head modules;

static inline int kernel_text_address(unsigned long addr)
{
@@ -106,11 +107,11 @@ static inline int kernel_text_address(un
addr <= (unsigned long) &_etext)
return 1;

- for (mod = module_list; mod != &kernel_module; mod = mod->next) {
+ list_for_each_entry(mod, &modules, list) {
/* mod_bound tests for addr being inside the vmalloc'ed
* module area. Of course it'd be better to test only
* for the .text subset... */
- if (mod_bound(addr, 0, mod)) {
+ if (mod_bound((void *)addr, 0, mod)) {
retval = 1;
break;
}
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .9540-2.5.45-module-i386.pre/arch/i386/mm/extable.c .9540-2.5.45-module-i386/arch/i386/mm/extable.c
--- .9540-2.5.45-module-i386.pre/arch/i386/mm/extable.c 2001-09-18 06:16:30.000000000 +1000
+++ .9540-2.5.45-module-i386/arch/i386/mm/extable.c 2002-11-01 11:15:05.000000000 +1100
@@ -44,15 +44,17 @@ search_exception_table(unsigned long add
return ret;
#else
unsigned long flags;
- /* The kernel is the last "module" -- no need to treat it special. */
- struct module *mp;
+ struct list_head *i;

+ /* The kernel is the last "module" -- no need to treat it special. */
spin_lock_irqsave(&modlist_lock, flags);
- for (mp = module_list; mp != NULL; mp = mp->next) {
- if (mp->ex_table_start == NULL || !(mp->flags&(MOD_RUNNING|MOD_INITIALIZING)))
+ list_for_each(i, &extables) {
+ struct exception_table *ex
+ = list_entry(i, struct exception_table, list);
+ if (ex->num_entries == 0)
continue;
- ret = search_one_table(mp->ex_table_start,
- mp->ex_table_end - 1, addr);
+ ret = search_one_table(ex->entry,
+ ex->entry + ex->num_entries - 1, addr);
if (ret)
break;
}
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .9540-2.5.45-module-i386.pre/arch/i386/vmlinux.lds.S .9540-2.5.45-module-i386/arch/i386/vmlinux.lds.S
--- .9540-2.5.45-module-i386.pre/arch/i386/vmlinux.lds.S 2002-10-19 17:47:49.000000000 +1000
+++ .9540-2.5.45-module-i386/arch/i386/vmlinux.lds.S 2002-11-01 11:15:05.000000000 +1100
@@ -26,6 +26,7 @@ SECTIONS
__ex_table : { *(__ex_table) }
__stop___ex_table = .;

+ . = ALIGN(64);
__start___ksymtab = .; /* Kernel symbol table */
__ksymtab : { *(__ksymtab) }
__stop___ksymtab = .;
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .9540-2.5.45-module-i386.pre/include/asm-i386/module.h .9540-2.5.45-module-i386/include/asm-i386/module.h
--- .9540-2.5.45-module-i386.pre/include/asm-i386/module.h 2001-09-14 09:33:03.000000000 +1000
+++ .9540-2.5.45-module-i386/include/asm-i386/module.h 2002-11-01 11:15:05.000000000 +1100
@@ -1,12 +1,11 @@
#ifndef _ASM_I386_MODULE_H
#define _ASM_I386_MODULE_H
-/*
- * This file contains the i386 architecture specific module code.
- */
-
-#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)
+/* x86 is simple */
+struct mod_arch_specific
+{
+};

+#define Elf_Shdr Elf32_Shdr
+#define Elf_Sym Elf32_Sym
+#define Elf_Ehdr Elf32_Ehdr
#endif /* _ASM_I386_MODULE_H */

--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.

2002-11-05 00:54:10

by Rusty Russell

[permalink] [raw]
Subject: [PATCH] Module loader against 2.5.46: 5/9

Now, we add support for the PARAM(foo, type, perms) macro:

o Module parameters appear as "foo", kernel parameters appear as
"<modulename>.foo"
o Parameters are typechecked.
o Standard types are implemented, you can implement your own.
o Name "PARAM" clashes with include/asm-i386/setup.h, so we rename
that to "PARAMS".
o Final permissions arg can be used for exposing parameters through
sysfs (000 means no exposure).

Linus, please apply,
Rusty.
--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.

Name: Parameter Core Patch
Author: Rusty Russell
Status: Tested on 2.5.38
Depends: Misc/strcspn.patch.gz
Depends: Module/module-i386.patch.gz

D: This patch is a rewrite of the insmod and boot parameter handling,
D: to unify them.
D:
D: The new format is fairly simple: built on top of __PARAM_CALL there
D: are several helpers, eg "PARAM(foo, int, 000)". The final argument
D: is the permissions bits, for exposing parameters in driverfs (if
D: non-zero) at a later stage.

diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .2447-linux-2.5-bk/arch/i386/vmlinux.lds.S .2447-linux-2.5-bk.updated/arch/i386/vmlinux.lds.S
--- .2447-linux-2.5-bk/arch/i386/vmlinux.lds.S 2002-11-01 18:41:03.000000000 +1100
+++ .2447-linux-2.5-bk.updated/arch/i386/vmlinux.lds.S 2002-11-01 18:41:39.000000000 +1100
@@ -67,6 +67,9 @@ SECTIONS
__setup_start = .;
.init.setup : { *(.init.setup) }
__setup_end = .;
+ __param_start = .;
+ .param.init : { *(.param.init) }
+ __param_end = .;
__initcall_start = .;
.initcall.init : {
*(.initcall1.init)
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .2447-linux-2.5-bk/arch/ia64/vmlinux.lds.S .2447-linux-2.5-bk.updated/arch/ia64/vmlinux.lds.S
--- .2447-linux-2.5-bk/arch/ia64/vmlinux.lds.S 2002-10-31 12:36:20.000000000 +1100
+++ .2447-linux-2.5-bk.updated/arch/ia64/vmlinux.lds.S 2002-11-01 18:41:39.000000000 +1100
@@ -102,6 +102,10 @@ SECTIONS
.init.setup : AT(ADDR(.init.setup) - PAGE_OFFSET)
{ *(.init.setup) }
__setup_end = .;
+ __param_start = .;
+ .param.init : AT(ADDR(.param.init) - PAGE_OFFSET)
+ { *(.param.init) }
+ __param_end = .;
__initcall_start = .;
.initcall.init : AT(ADDR(.initcall.init) - PAGE_OFFSET)
{
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .2447-linux-2.5-bk/arch/ppc/vmlinux.lds.S .2447-linux-2.5-bk.updated/arch/ppc/vmlinux.lds.S
--- .2447-linux-2.5-bk/arch/ppc/vmlinux.lds.S 2002-10-19 17:47:50.000000000 +1000
+++ .2447-linux-2.5-bk.updated/arch/ppc/vmlinux.lds.S 2002-11-01 18:41:39.000000000 +1100
@@ -101,6 +101,9 @@ SECTIONS
__setup_start = .;
.init.setup : { *(.init.setup) }
__setup_end = .;
+ __param_start = .;
+ .param.init : { *(.param.init) }
+ __param_end = .;
__initcall_start = .;
.initcall.init : {
*(.initcall1.init)
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .2447-linux-2.5-bk/arch/ppc64/vmlinux.lds.S .2447-linux-2.5-bk.updated/arch/ppc64/vmlinux.lds.S
--- .2447-linux-2.5-bk/arch/ppc64/vmlinux.lds.S 2002-09-18 16:04:37.000000000 +1000
+++ .2447-linux-2.5-bk.updated/arch/ppc64/vmlinux.lds.S 2002-11-01 18:41:39.000000000 +1100
@@ -99,6 +99,9 @@ SECTIONS
__setup_start = .;
.setup.init : { *(.setup.init) }
__setup_end = .;
+ __param_start = .;
+ .param.init : { *(.param.init) }
+ __param_end = .;
__initcall_start = .;
.initcall.init : {
*(.initcall1.init)
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .2447-linux-2.5-bk/arch/sparc64/vmlinux.lds.S .2447-linux-2.5-bk.updated/arch/sparc64/vmlinux.lds.S
--- .2447-linux-2.5-bk/arch/sparc64/vmlinux.lds.S 2002-10-31 12:36:22.000000000 +1100
+++ .2447-linux-2.5-bk.updated/arch/sparc64/vmlinux.lds.S 2002-11-01 18:41:39.000000000 +1100
@@ -46,6 +46,9 @@ SECTIONS
__setup_start = .;
.init.setup : { *(.init.setup) }
__setup_end = .;
+ __param_start = .;
+ .param.init : { *(.param.init) }
+ __param_end = .;
__initcall_start = .;
.initcall.init : {
*(.initcall1.init)
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .2447-linux-2.5-bk/include/asm-i386/setup.h .2447-linux-2.5-bk.updated/include/asm-i386/setup.h
--- .2447-linux-2.5-bk/include/asm-i386/setup.h 2002-10-19 17:48:09.000000000 +1000
+++ .2447-linux-2.5-bk.updated/include/asm-i386/setup.h 2002-11-01 18:41:39.000000000 +1100
@@ -19,27 +19,27 @@
/*
* This is set up by the setup-routine at boot-time
*/
-#define PARAM ((unsigned char *)empty_zero_page)
-#define SCREEN_INFO (*(struct screen_info *) (PARAM+0))
-#define EXT_MEM_K (*(unsigned short *) (PARAM+2))
-#define ALT_MEM_K (*(unsigned long *) (PARAM+0x1e0))
-#define E820_MAP_NR (*(char*) (PARAM+E820NR))
-#define E820_MAP ((struct e820entry *) (PARAM+E820MAP))
-#define APM_BIOS_INFO (*(struct apm_bios_info *) (PARAM+0x40))
-#define DRIVE_INFO (*(struct drive_info_struct *) (PARAM+0x80))
-#define SYS_DESC_TABLE (*(struct sys_desc_table_struct*)(PARAM+0xa0))
-#define MOUNT_ROOT_RDONLY (*(unsigned short *) (PARAM+0x1F2))
-#define RAMDISK_FLAGS (*(unsigned short *) (PARAM+0x1F8))
-#define VIDEO_MODE (*(unsigned short *) (PARAM+0x1FA))
-#define ORIG_ROOT_DEV (*(unsigned short *) (PARAM+0x1FC))
-#define AUX_DEVICE_INFO (*(unsigned char *) (PARAM+0x1FF))
-#define LOADER_TYPE (*(unsigned char *) (PARAM+0x210))
-#define KERNEL_START (*(unsigned long *) (PARAM+0x214))
-#define INITRD_START (*(unsigned long *) (PARAM+0x218))
-#define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c))
-#define EDD_NR (*(unsigned char *) (PARAM+EDDNR))
-#define EDD_BUF ((struct edd_info *) (PARAM+EDDBUF))
-#define COMMAND_LINE ((char *) (PARAM+2048))
+#define PARAMS ((unsigned char *)empty_zero_page)
+#define SCREEN_INFO (*(struct screen_info *) (PARAMS+0))
+#define EXT_MEM_K (*(unsigned short *) (PARAMS+2))
+#define ALT_MEM_K (*(unsigned long *) (PARAMS+0x1e0))
+#define E820_MAP_NR (*(char*) (PARAMS+E820NR))
+#define E820_MAP ((struct e820entry *) (PARAMS+E820MAP))
+#define APM_BIOS_INFO (*(struct apm_bios_info *) (PARAMS+0x40))
+#define DRIVE_INFO (*(struct drive_info_struct *) (PARAMS+0x80))
+#define SYS_DESC_TABLE (*(struct sys_desc_table_struct*)(PARAMS+0xa0))
+#define MOUNT_ROOT_RDONLY (*(unsigned short *) (PARAMS+0x1F2))
+#define RAMDISK_FLAGS (*(unsigned short *) (PARAMS+0x1F8))
+#define VIDEO_MODE (*(unsigned short *) (PARAMS+0x1FA))
+#define ORIG_ROOT_DEV (*(unsigned short *) (PARAMS+0x1FC))
+#define AUX_DEVICE_INFO (*(unsigned char *) (PARAMS+0x1FF))
+#define LOADER_TYPE (*(unsigned char *) (PARAMS+0x210))
+#define KERNEL_START (*(unsigned long *) (PARAMS+0x214))
+#define INITRD_START (*(unsigned long *) (PARAMS+0x218))
+#define INITRD_SIZE (*(unsigned long *) (PARAMS+0x21c))
+#define EDD_NR (*(unsigned char *) (PARAMS+EDDNR))
+#define EDD_BUF ((struct edd_info *) (PARAMS+EDDBUF))
+#define COMMAND_LINE ((char *) (PARAMS+2048))
#define COMMAND_LINE_SIZE 256

#endif /* _i386_SETUP_H */
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .2447-linux-2.5-bk/include/linux/init.h .2447-linux-2.5-bk.updated/include/linux/init.h
--- .2447-linux-2.5-bk/include/linux/init.h 2002-11-01 18:41:01.000000000 +1100
+++ .2447-linux-2.5-bk.updated/include/linux/init.h 2002-11-01 18:42:59.000000000 +1100
@@ -86,19 +86,15 @@ typedef void (*exitcall_t)(void);
#define __exitcall(fn) \
static exitcall_t __exitcall_##fn __exit_call = fn

-/*
- * Used for kernel command line parameter setup
- */
-struct kernel_param {
+struct obs_kernel_param {
const char *str;
int (*setup_func)(char *);
};

-extern struct kernel_param __setup_start, __setup_end;
-
+/* OBSOLETE: see params.h for the right way. */
#define __setup(str, fn) \
static char __setup_str_##fn[] __initdata = str; \
- static struct kernel_param __setup_##fn \
+ static struct obs_kernel_param __setup_##fn \
__attribute__((unused,__section__ (".init.setup"))) \
= { __setup_str_##fn, fn }

@@ -177,6 +173,16 @@ extern struct kernel_param __setup_start
/* Data marked not to be saved by software_suspend() */
#define __nosavedata __attribute__ ((__section__ (".data.nosave")))

+/* This means "can be init if no module support, otherwise module load
+ may call it." */
+#ifdef CONFIG_MODULES
+#define __init_or_module
+#define __initdata_or_module
+#else
+#define __init_or_module __init
+#define __initdata_or_module __initdata
+#endif /*CONFIG_MODULES*/
+
#ifdef CONFIG_HOTPLUG
#define __devinit
#define __devinitdata
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .2447-linux-2.5-bk/include/linux/kernel.h .2447-linux-2.5-bk.updated/include/linux/kernel.h
--- .2447-linux-2.5-bk/include/linux/kernel.h 2002-10-19 17:48:10.000000000 +1000
+++ .2447-linux-2.5-bk.updated/include/linux/kernel.h 2002-11-01 18:41:39.000000000 +1100
@@ -71,7 +71,7 @@ extern int sscanf(const char *, const ch
extern int vsscanf(const char *, const char *, va_list);

extern int get_option(char **str, int *pint);
-extern char *get_options(char *str, int nints, int *ints);
+extern char *get_options(const char *str, int nints, int *ints);
extern unsigned long long memparse(char *ptr, char **retptr);
extern void dev_probe_lock(void);
extern void dev_probe_unlock(void);
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .2447-linux-2.5-bk/include/linux/params.h .2447-linux-2.5-bk.updated/include/linux/params.h
--- .2447-linux-2.5-bk/include/linux/params.h 1970-01-01 10:00:00.000000000 +1000
+++ .2447-linux-2.5-bk.updated/include/linux/params.h 2002-11-01 18:41:39.000000000 +1100
@@ -0,0 +1,123 @@
+#ifndef _LINUX_PARAMS_H
+#define _LINUX_PARAMS_H
+/* (C) Copyright 2001, 2002 Rusty Russell IBM Corporation */
+#include <linux/init.h>
+#include <linux/stringify.h>
+
+/* You can override this manually, but generally this should match the
+ module name. */
+#define PARAM_PREFIX __stringify(KBUILD_MODNAME) "."
+
+struct kernel_param;
+
+/* Returns 0, or -errno. arg is in kp->arg. */
+typedef int (*param_set_fn)(const char *val, struct kernel_param *kp);
+/* Returns length written or -errno. Buffer is 4k (ie. be short!) */
+typedef int (*param_get_fn)(char *buffer, struct kernel_param *kp);
+
+struct kernel_param {
+ const char *name;
+ unsigned int perm;
+ param_set_fn set;
+ param_get_fn get;
+ void *arg;
+};
+
+/* Special one for strings we want to copy into */
+struct kparam_string {
+ unsigned int maxlen;
+ char *string;
+};
+
+/* This is the fundamental function for registering boot/module
+ parameters. perm sets the visibility in driverfs: 000 means it's
+ not there, read bits mean it's readable, write bits mean it's
+ writable. */
+#define __PARAM_CALL(prefix, name, set, get, arg, perm) \
+ static char __param_str_##name[] __initdata = prefix #name; \
+ static struct kernel_param __param_##name \
+ __attribute__ ((unused,__section__ (".param.init"))) \
+ = { __param_str_##name, perm, set, get, arg }
+
+#define PARAM_CALL(name, set, get, arg, perm) \
+ __PARAM_CALL(PARAM_PREFIX, name, set, get, arg, perm)
+
+/* Helper functions: type is byte, short, ushort, int, uint, long,
+ ulong, charp, bool or invbool, or XXX if you define param_get_XXX,
+ param_set_XXX and param_check_XXX. */
+#define PARAM_NAMED(name, value, type, perm) \
+ param_check_##type(name, &(value)); \
+ PARAM_CALL(name, param_set_##type, param_get_##type, &value, perm)
+
+#define PARAM(name, type, perm) \
+ PARAM_NAMED(name, name, type, perm)
+
+/* Actually copy string: maxlen param is usually sizeof(string). */
+#define PARAM_STRING(name, string, len, perm) \
+ static struct kparam_string __param_string_##name __initdata \
+ = { len, string }; \
+ PARAM_CALL(name, param_set_copystring, param_get_charp, \
+ &__param_string_##name, perm)
+
+/* Called on module insert or kernel boot */
+extern int parse_args(const char *name,
+ char *args,
+ struct kernel_param *params,
+ unsigned num,
+ int (*unknown)(char *param, char *val));
+
+/* All the helper functions */
+/* The macros to do compile-time type checking stolen from Jakub
+ Jelinek, who IIRC came up with this idea for the 2.4 module init code. */
+#define __param_check(name, p, type) \
+ static inline type *__check_##name(void) { return(p); }
+
+extern int param_set_short(const char *val, struct kernel_param *kp);
+extern int param_get_short(char *buffer, struct kernel_param *kp);
+#define param_check_short(name, p) __param_check(name, p, short)
+
+extern int param_set_ushort(const char *val, struct kernel_param *kp);
+extern int param_get_ushort(char *buffer, struct kernel_param *kp);
+#define param_check_ushort(name, p) __param_check(name, p, unsigned short)
+
+extern int param_set_int(const char *val, struct kernel_param *kp);
+extern int param_get_int(char *buffer, struct kernel_param *kp);
+#define param_check_int(name, p) __param_check(name, p, int)
+
+extern int param_set_uint(const char *val, struct kernel_param *kp);
+extern int param_get_uint(char *buffer, struct kernel_param *kp);
+#define param_check_uint(name, p) __param_check(name, p, unsigned int)
+
+extern int param_set_long(const char *val, struct kernel_param *kp);
+extern int param_get_long(char *buffer, struct kernel_param *kp);
+#define param_check_long(name, p) __param_check(name, p, long)
+
+extern int param_set_ulong(const char *val, struct kernel_param *kp);
+extern int param_get_ulong(char *buffer, struct kernel_param *kp);
+#define param_check_ulong(name, p) __param_check(name, p, unsigned long)
+
+extern int param_set_charp(const char *val, struct kernel_param *kp);
+extern int param_get_charp(char *buffer, struct kernel_param *kp);
+#define param_check_charp(name, p) __param_check(name, p, char *)
+
+extern int param_set_bool(const char *val, struct kernel_param *kp);
+extern int param_get_bool(char *buffer, struct kernel_param *kp);
+#define param_check_bool(name, p) __param_check(name, p, int)
+
+extern int param_set_invbool(const char *val, struct kernel_param *kp);
+extern int param_get_invbool(char *buffer, struct kernel_param *kp);
+#define param_check_invbool(name, p) __param_check(name, p, int)
+
+/* First two elements are the max and min array length (which don't change) */
+extern int param_set_intarray(const char *val, struct kernel_param *kp);
+extern int param_get_intarray(char *buffer, struct kernel_param *kp);
+#define param_check_intarray(name, p) __param_check(name, p, int *)
+
+extern int param_set_copystring(const char *val, struct kernel_param *kp);
+
+int param_array(const char *name,
+ const char *val,
+ unsigned int min, unsigned int max,
+ void *elem, int elemsize,
+ int (*set)(const char *, struct kernel_param *kp));
+#endif /* _LINUX_PARAM_TYPES_H */
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .2447-linux-2.5-bk/init/main.c .2447-linux-2.5-bk.updated/init/main.c
--- .2447-linux-2.5-bk/init/main.c 2002-11-01 18:41:01.000000000 +1100
+++ .2447-linux-2.5-bk.updated/init/main.c 2002-11-01 18:41:39.000000000 +1100
@@ -33,6 +33,7 @@
#include <linux/workqueue.h>
#include <linux/profile.h>
#include <linux/rcupdate.h>
+#include <linux/params.h>

#include <asm/io.h>
#include <asm/bugs.h>
@@ -134,9 +135,10 @@ char * envp_init[MAX_INIT_ENVS+2] = { "H

__setup("profile=", profile_setup);

-static int __init checksetup(char *line)
+static int __init obsolete_checksetup(char *line)
{
- struct kernel_param *p;
+ struct obs_kernel_param *p;
+ extern struct obs_kernel_param __setup_start, __setup_end;

p = &__setup_start;
do {
@@ -219,74 +221,45 @@ static int __init quiet_kernel(char *str
__setup("debug", debug_kernel);
__setup("quiet", quiet_kernel);

-/*
- * This is a simple kernel command line parsing function: it parses
- * the command line, and fills in the arguments/environment to init
- * as appropriate. Any cmd-line option is taken to be an environment
- * variable if it contains the character '='.
- *
- * This routine also checks for options meant for the kernel.
- * These options are not given to init - they are for internal kernel use only.
- */
-static void __init parse_options(char *line)
+/* Unknown boot options get handed to init, unless they look like
+ failed parameters */
+static int unknown_bootoption(char *param, char *val)
{
- char *next,*quote;
- int args, envs;
+ /* Change NUL term back to "=", to make "param" the whole string. */
+ if (val)
+ val[-1] = '=';

- if (!*line)
- return;
- args = 0;
- envs = 1; /* TERM is set to 'linux' by default */
- next = line;
- while ((line = next) != NULL) {
- quote = strchr(line,'"');
- next = strchr(line, ' ');
- while (next != NULL && quote != NULL && quote < next) {
- /* we found a left quote before the next blank
- * now we have to find the matching right quote
- */
- next = strchr(quote+1, '"');
- if (next != NULL) {
- quote = strchr(next+1, '"');
- next = strchr(next+1, ' ');
- }
- }
- if (next != NULL)
- *next++ = 0;
- if (!strncmp(line,"init=",5)) {
- line += 5;
- execute_command = line;
- /* In case LILO is going to boot us with default command line,
- * it prepends "auto" before the whole cmdline which makes
- * the shell think it should execute a script with such name.
- * So we ignore all arguments entered _before_ init=... [MJ]
- */
- args = 0;
- continue;
+ /* Handle obsolete-style parameters */
+ if (obsolete_checksetup(param))
+ return 0;
+
+ /* Preemptive maintenance for "why didn't my mispelled command
+ line work?" */
+ if (strchr(param, '.') && (!val || strchr(param, '.') < val)) {
+ printk(KERN_ERR "Unknown boot option `%s': ignoring\n", param);
+ return 0;
+ }
+
+ if (val) {
+ /* Environment option */
+ unsigned int i;
+ for (i = 0; envp_init[i]; i++) {
+ if (i == MAX_INIT_ENVS)
+ panic("Too many boot env vars at `%s'", param);
}
- if (checksetup(line))
- continue;
-
- /*
- * Then check if it's an environment variable or
- * an option.
- */
- if (strchr(line,'=')) {
- if (envs >= MAX_INIT_ENVS)
- break;
- envp_init[++envs] = line;
- } else {
- if (args >= MAX_INIT_ARGS)
- break;
- if (*line)
- argv_init[++args] = line;
+ envp_init[i] = param;
+ } else {
+ /* Command line option */
+ unsigned int i;
+ for (i = 0; argv_init[i]; i++) {
+ if (i == MAX_INIT_ARGS)
+ panic("Too many boot init vars at `%s'",param);
}
+ argv_init[i] = param;
}
- argv_init[args+1] = NULL;
- envp_init[envs+1] = NULL;
+ return 0;
}

-
extern void setup_arch(char **);
extern void cpu_idle(void);

@@ -380,6 +353,7 @@ asmlinkage void __init start_kernel(void
{
char * command_line;
extern char saved_command_line[];
+ extern struct kernel_param __param_start, __param_end;
/*
* Interrupts are still disabled. Do necessary setups, then
* enable them
@@ -391,7 +365,9 @@ asmlinkage void __init start_kernel(void
build_all_zonelists();
page_alloc_init();
printk("Kernel command line: %s\n", saved_command_line);
- parse_options(command_line);
+ parse_args("Booting kernel", command_line, &__param_start,
+ &__param_end - &__param_start - 1,
+ &unknown_bootoption);
trap_init();
rcu_init();
init_IRQ();
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .2447-linux-2.5-bk/kernel/Makefile .2447-linux-2.5-bk.updated/kernel/Makefile
--- .2447-linux-2.5-bk/kernel/Makefile 2002-11-01 18:41:01.000000000 +1100
+++ .2447-linux-2.5-bk.updated/kernel/Makefile 2002-11-01 18:41:39.000000000 +1100
@@ -4,13 +4,13 @@

export-objs = signal.o sys.o kmod.o workqueue.o ksyms.o pm.o exec_domain.o \
printk.o platform.o suspend.o dma.o module.o cpufreq.o \
- profile.o rcupdate.o intermodule.o
+ profile.o rcupdate.o intermodule.o params.o

obj-y = sched.o fork.o exec_domain.o panic.o printk.o profile.o \
exit.o itimer.o time.o softirq.o resource.o \
sysctl.o capability.o ptrace.o timer.o user.o \
signal.o sys.o kmod.o workqueue.o futex.o platform.o pid.o \
- rcupdate.o intermodule.o
+ rcupdate.o intermodule.o params.o

obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o
obj-$(CONFIG_SMP) += cpu.o
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .2447-linux-2.5-bk/kernel/params.c .2447-linux-2.5-bk.updated/kernel/params.c
--- .2447-linux-2.5-bk/kernel/params.c 1970-01-01 10:00:00.000000000 +1000
+++ .2447-linux-2.5-bk.updated/kernel/params.c 2002-11-01 18:41:39.000000000 +1100
@@ -0,0 +1,338 @@
+/* Helpers for initial module or kernel cmdline parsing
+ Copyright (C) 2001 Rusty Russell.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+#include <linux/params.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(fmt , ...)
+#endif
+
+static int parse_one(char *param,
+ char *val,
+ struct kernel_param *params,
+ unsigned num_params,
+ int (*handle_unknown)(char *param, char *val))
+{
+ unsigned int i;
+
+ /* Find parameter */
+ for (i = 0; i < num_params; i++) {
+ if (strcmp(param, params[i].name) == 0) {
+ DEBUGP("They are equal! Calling %p\n",
+ params[i].set);
+ return params[i].set(val, &params[i]);
+ }
+ }
+
+ if (handle_unknown) {
+ DEBUGP("Unknown argument: calling %p\n", handle_unknown);
+ return handle_unknown(param, val);
+ }
+
+ DEBUGP("Unknown argument `%s'\n", param);
+ return -ENOENT;
+}
+
+/* You can use " around spaces, but can't escape ". */
+/* Hyphens and underscores equivalent in parameter names. */
+static char *next_arg(char *args, char **param, char **val)
+{
+ unsigned int i, equals = 0;
+ int in_quote = 0;
+
+ /* Chew any extra spaces */
+ while (*args == ' ') args++;
+
+ for (i = 0; args[i]; i++) {
+ if (args[i] == ' ' && !in_quote)
+ break;
+ if (equals == 0) {
+ if (args[i] == '=')
+ equals = i;
+ else if (args[i] == '-')
+ args[i] = '_';
+ }
+ if (args[i] == '"')
+ in_quote = !in_quote;
+ }
+
+ *param = args;
+ if (!equals)
+ *val = NULL;
+ else {
+ args[equals] = '\0';
+ *val = args + equals + 1;
+ }
+
+ if (args[i]) {
+ args[i] = '\0';
+ return args + i + 1;
+ } else
+ return args + i;
+}
+
+/* Args looks like "foo=bar,bar2 baz=fuz wiz". */
+int parse_args(const char *name,
+ char *args,
+ struct kernel_param *params,
+ unsigned num,
+ int (*unknown)(char *param, char *val))
+{
+ char *param, *val;
+
+ DEBUGP("Parsing ARGS: %s\n", args);
+
+ while (*args) {
+ int ret;
+
+ args = next_arg(args, &param, &val);
+ ret = parse_one(param, val, params, num, unknown);
+ switch (ret) {
+ case -ENOENT:
+ printk(KERN_ERR "%s: Unknown parameter `%s'\n",
+ name, param);
+ return ret;
+ case -ENOSPC:
+ printk(KERN_ERR
+ "%s: `%s' too large for parameter `%s'\n",
+ name, val ?: "", param);
+ return ret;
+ case 0:
+ break;
+ default:
+ printk(KERN_ERR
+ "%s: `%s' invalid for parameter `%s'\n",
+ name, val ?: "", param);
+ return ret;
+ }
+ }
+
+ /* All parsed OK. */
+ return 0;
+}
+
+/* Lazy bastard, eh? */
+#define STANDARD_PARAM_DEF(name, type, format, tmptype, strtolfn) \
+ int param_set_##name(const char *val, struct kernel_param *kp) \
+ { \
+ char *endp; \
+ tmptype l; \
+ \
+ if (!val) return -EINVAL; \
+ l = strtolfn(val, &endp, 0); \
+ if (endp == val || *endp || ((type)l != l)) \
+ return -EINVAL; \
+ *((type *)kp->arg) = l; \
+ return 0; \
+ } \
+ int param_get_##name(char *buffer, struct kernel_param *kp) \
+ { \
+ return sprintf(buffer, format, *((type *)kp->arg)); \
+ }
+
+STANDARD_PARAM_DEF(short, short, "%hi", long, simple_strtol);
+STANDARD_PARAM_DEF(ushort, unsigned short, "%hu", long, simple_strtol);
+STANDARD_PARAM_DEF(int, int, "%i", long, simple_strtol);
+STANDARD_PARAM_DEF(uint, unsigned int, "%u", long, simple_strtol);
+STANDARD_PARAM_DEF(long, long, "%li", long, simple_strtol);
+STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", unsigned long, simple_strtoul);
+
+int param_set_charp(const char *val, struct kernel_param *kp)
+{
+ if (!val) {
+ printk(KERN_ERR "%s: string parameter expected\n",
+ kp->name);
+ return -EINVAL;
+ }
+
+ if (strlen(val) > 1024) {
+ printk(KERN_ERR "%s: string parameter too long\n",
+ kp->name);
+ return -ENOSPC;
+ }
+
+ *(char **)kp->arg = (char *)val;
+ return 0;
+}
+
+int param_get_charp(char *buffer, struct kernel_param *kp)
+{
+ return sprintf(buffer, "%s", *((char **)kp->arg));
+}
+
+int param_set_bool(const char *val, struct kernel_param *kp)
+{
+ /* No equals means "set"... */
+ if (!val) val = "1";
+
+ /* One of =[yYnN01] */
+ switch (val[0]) {
+ case 'y': case 'Y': case '1':
+ *(int *)kp->arg = 1;
+ return 0;
+ case 'n': case 'N': case '0':
+ *(int *)kp->arg = 0;
+ return 0;
+ }
+ return -EINVAL;
+}
+
+int param_get_bool(char *buffer, struct kernel_param *kp)
+{
+ /* Y and N chosen as being relatively non-coder friendly */
+ return sprintf(buffer, "%c", (*(int *)kp->arg) ? 'Y' : 'N');
+}
+
+int param_set_invbool(const char *val, struct kernel_param *kp)
+{
+ int boolval, ret;
+ struct kernel_param dummy = { .arg = &boolval };
+
+ ret = param_set_bool(val, &dummy);
+ if (ret == 0)
+ *(int *)kp->arg = !boolval;
+ return ret;
+}
+
+int param_get_invbool(char *buffer, struct kernel_param *kp)
+{
+ int val;
+ struct kernel_param dummy = { .arg = &val };
+
+ val = !*(int *)kp->arg;
+ return param_get_bool(buffer, &dummy);
+}
+
+/* We cheat here and temporarily mangle the string. */
+int param_array(const char *name,
+ const char *val,
+ unsigned int min, unsigned int max,
+ void *elem, int elemsize,
+ int (*set)(const char *, struct kernel_param *kp))
+{
+ int ret;
+ unsigned int count = 0;
+ struct kernel_param kp;
+
+ /* Get the name right for errors. */
+ kp.name = name;
+ kp.arg = elem;
+
+ /* No equals sign? */
+ if (!val) {
+ printk(KERN_ERR "%s: expects arguments\n", name);
+ return -EINVAL;
+ }
+
+ /* We expect a comma-separated list of values. */
+ do {
+ int len;
+ char save;
+
+ if (count > max) {
+ printk(KERN_ERR "%s: can only take %i arguments\n",
+ name, max);
+ return -EINVAL;
+ }
+ len = strcspn(val, ",");
+
+ /* Temporarily nul-terminate and parse */
+ save = val[len];
+ ((char *)val)[len] = '\0';
+ ret = set(val, &kp);
+ ((char *)val)[len] = save;
+
+ if (ret != 0)
+ return ret;
+ kp.arg += elemsize;
+ val += len+1;
+ count++;
+ } while (val[-1] == ',');
+
+ if (count < min) {
+ printk(KERN_ERR "%s: needs at least %i arguments\n",
+ name, min);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/* First two elements are the max and min array length (which don't change) */
+int param_set_intarray(const char *val, struct kernel_param *kp)
+{
+ int *array;
+
+ /* Grab min and max as first two elements */
+ array = kp->arg;
+ return param_array(kp->name, val, array[0], array[1], &array[2],
+ sizeof(int), param_set_int);
+}
+
+int param_get_intarray(char *buffer, struct kernel_param *kp)
+{
+ int max;
+ int *array;
+ unsigned int i;
+
+ array = kp->arg;
+ max = array[1];
+
+ for (i = 2; i < max + 2; i++)
+ sprintf(buffer, "%s%i", i > 2 ? "," : "", array[i]);
+ return strlen(buffer);
+}
+
+int param_set_copystring(const char *val, struct kernel_param *kp)
+{
+ struct kparam_string *kps = kp->arg;
+
+ if (strlen(val)+1 > kps->maxlen) {
+ printk(KERN_ERR "%s: string doesn't fit in %u chars.\n",
+ kp->name, kps->maxlen-1);
+ return -ENOSPC;
+ }
+ strcpy(kps->string, val);
+ return 0;
+}
+
+EXPORT_SYMBOL(param_set_short);
+EXPORT_SYMBOL(param_get_short);
+EXPORT_SYMBOL(param_set_ushort);
+EXPORT_SYMBOL(param_get_ushort);
+EXPORT_SYMBOL(param_set_int);
+EXPORT_SYMBOL(param_get_int);
+EXPORT_SYMBOL(param_set_uint);
+EXPORT_SYMBOL(param_get_uint);
+EXPORT_SYMBOL(param_set_long);
+EXPORT_SYMBOL(param_get_long);
+EXPORT_SYMBOL(param_set_ulong);
+EXPORT_SYMBOL(param_get_ulong);
+EXPORT_SYMBOL(param_set_charp);
+EXPORT_SYMBOL(param_get_charp);
+EXPORT_SYMBOL(param_set_bool);
+EXPORT_SYMBOL(param_get_bool);
+EXPORT_SYMBOL(param_set_invbool);
+EXPORT_SYMBOL(param_get_invbool);
+EXPORT_SYMBOL(param_set_intarray);
+EXPORT_SYMBOL(param_get_intarray);
+EXPORT_SYMBOL(param_set_copystring);
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .2447-linux-2.5-bk/lib/cmdline.c .2447-linux-2.5-bk.updated/lib/cmdline.c
--- .2447-linux-2.5-bk/lib/cmdline.c 2001-04-13 05:25:53.000000000 +1000
+++ .2447-linux-2.5-bk.updated/lib/cmdline.c 2002-11-01 18:41:39.000000000 +1100
@@ -33,11 +33,11 @@

int get_option (char **str, int *pint)
{
- char *cur = *str;
+ const char *cur = *str;

if (!cur || !(*cur))
return 0;
- *pint = simple_strtol (cur, str, 0);
+ *pint = simple_strtol (cur, (char **)str, 0);
if (cur == *str)
return 0;
if (**str == ',') {
@@ -64,12 +64,12 @@ int get_option (char **str, int *pint)
* completely parseable).
*/

-char *get_options (char *str, int nints, int *ints)
+char *get_options (const char *str, int nints, int *ints)
{
int res, i = 1;

while (i < nints) {
- res = get_option (&str, ints + i);
+ res = get_option ((char **)&str, ints + i);
if (res == 0)
break;
i++;
@@ -77,7 +77,7 @@ char *get_options (char *str, int nints,
break;
}
ints[0] = i - 1;
- return (str);
+ return (char *)str;
}

/**

2002-11-05 00:51:01

by Rusty Russell

[permalink] [raw]
Subject: [PATCH] Module loader against 2.5.46: 6/9

Trivially remove the #if 0 in module.c to enable the parameter parsing
for modules.

Linus, please apply.
Rusty.

Name: Parameter Implementation for modules
Author: Rusty Russell
Status: Tested on 2.5.38
Depends: Module/param.patch.gz

D: This activates parameter parsing for PARAM() declarations in modules.

diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .31807-linux-2.5.43/kernel/module.c .31807-linux-2.5.43.updated/kernel/module.c
--- .31807-linux-2.5.43/kernel/module.c 2002-10-18 17:17:25.000000000 +1000
+++ .31807-linux-2.5.43.updated/kernel/module.c 2002-10-18 17:17:57.000000000 +1000
@@ -25,6 +25,7 @@
#include <linux/fcntl.h>
#include <linux/rcupdate.h>
#include <linux/cpu.h>
+#include <linux/params.h>
#include <asm/uaccess.h>
#include <asm/semaphore.h>
#include <asm/pgalloc.h>
@@ -951,8 +952,7 @@ static struct module *load_module(void *
if (err < 0)
goto cleanup;

-#if 0 /* Needs param support */
- /* Size of section 0 is 0, so this works well */
+ /* Size of section 0 is 0, so this works well if no params */
err = parse_args(mod->args,
(struct kernel_param *)
sechdrs[setupindex].sh_offset,
@@ -961,7 +961,6 @@ static struct module *load_module(void *
NULL);
if (err < 0)
goto cleanup;
-#endif

/* Get rid of temporary copy */
vfree(hdr);

--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.

2002-11-05 00:52:24

by Rusty Russell

[permalink] [raw]
Subject: Re: [PATCH] Module loader against 2.5.46: 9/9

Since I believe kallsyms is important, this reimplements it sanely,
using the current module infrastructure, and not using an external
kallsyms script.

FYI, the previous interface was:

int kallsyms_symbol_to_address(
const char *name, /* Name to lookup */
unsigned long *token, /* Which module to start with */
const char **mod_name, /* Set to module name or "kernel" */
unsigned long *mod_start, /* Set to start address of module */
unsigned long *mod_end, /* Set to end address of module */
const char **sec_name, /* Set to section name */
unsigned long *sec_start, /* Set to start address of section */
unsigned long *sec_end, /* Set to end address of section */
const char **sym_name, /* Set to full symbol name */
unsigned long *sym_start, /* Set to start address of symbol */
unsigned long *sym_end /* Set to end address of symbol */
);

The new one is:
/* Lookup an address. modname is set to NULL if it's in the kernel. */
const char *kallsyms_lookup(unsigned long addr,
unsigned long *symbolsize,
unsigned long *offset,
char **modname);

Rusty.

Name: kallsyms support
Author: Rusty Russell
Status: Documentation
Depends: Module/param-oldstyle.patch.gz

D: Reintroduces kallsyms support.

diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .7287-linux-2.5.46/Makefile .7287-linux-2.5.46.updated/Makefile
--- .7287-linux-2.5.46/Makefile 2002-11-05 11:12:39.000000000 +1100
+++ .7287-linux-2.5.46.updated/Makefile 2002-11-05 11:13:10.000000000 +1100
@@ -157,7 +157,7 @@ OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
AWK = awk
GENKSYMS = /sbin/genksyms
-KALLSYMS = /sbin/kallsyms
+KALLSYMS = scripts/kallsyms
PERL = perl
MODFLAGS = -DMODULE
CFLAGS_MODULE = $(MODFLAGS)
@@ -335,7 +335,7 @@ ifdef CONFIG_KALLSYMS
kallsyms.o := .tmp_kallsyms2.o

quiet_cmd_kallsyms = KSYM $@
-cmd_kallsyms = $(KALLSYMS) $< > $@
+cmd_kallsyms = sh $(KALLSYMS) $< $@

.tmp_kallsyms1.o: .tmp_vmlinux1
$(call cmd,kallsyms)
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .7287-linux-2.5.46/arch/i386/Kconfig .7287-linux-2.5.46.updated/arch/i386/Kconfig
--- .7287-linux-2.5.46/arch/i386/Kconfig 2002-11-05 11:12:39.000000000 +1100
+++ .7287-linux-2.5.46.updated/arch/i386/Kconfig 2002-11-05 11:13:10.000000000 +1100
@@ -1605,14 +1605,13 @@ config DEBUG_HIGHMEM
This options enables addition error checking for high memory systems.
Disable for production systems.

-# Reimplemented RSN.
-#config KALLSYMS
-# bool "Load all symbols for debugging/kksymoops"
-# depends on DEBUG_KERNEL
-# help
-# Say Y here to let the kernel print out symbolic crash information and
-# symbolic stack backtraces. This increases the size of the kernel
-# somewhat, as all symbols have to be loaded into the kernel image.
+config KALLSYMS
+ bool "Load all symbols for debugging/kksymoops"
+ depends on DEBUG_KERNEL
+ help
+ Say Y here to let the kernel print out symbolic crash information and
+ symbolic stack backtraces. This increases the size of the kernel
+ somewhat, as all symbols have to be loaded into the kernel image.

config X86_EXTRA_IRQS
bool
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .7287-linux-2.5.46/arch/ia64/Kconfig .7287-linux-2.5.46.updated/arch/ia64/Kconfig
--- .7287-linux-2.5.46/arch/ia64/Kconfig 2002-11-05 11:12:39.000000000 +1100
+++ .7287-linux-2.5.46.updated/arch/ia64/Kconfig 2002-11-05 11:13:10.000000000 +1100
@@ -813,13 +813,13 @@ config DEBUG_KERNEL
Say Y here if you are developing drivers or trying to debug and
identify kernel problems.

-# config KALLSYMS
-# bool "Load all symbols for debugging/kksymoops"
-# depends on DEBUG_KERNEL
-# help
-# Say Y here to let the kernel print out symbolic crash information and
-# symbolic stack backtraces. This increases the size of the kernel
-# somewhat, as all symbols have to be loaded into the kernel image.
+config KALLSYMS
+ bool "Load all symbols for debugging/kksymoops"
+ depends on DEBUG_KERNEL
+ help
+ Say Y here to let the kernel print out symbolic crash information and
+ symbolic stack backtraces. This increases the size of the kernel
+ somewhat, as all symbols have to be loaded into the kernel image.

config IA64_PRINT_HAZARDS
bool "Print possible IA-64 dependency violations to console"
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .7287-linux-2.5.46/arch/ppc/Kconfig .7287-linux-2.5.46.updated/arch/ppc/Kconfig
--- .7287-linux-2.5.46/arch/ppc/Kconfig 2002-11-05 11:12:39.000000000 +1100
+++ .7287-linux-2.5.46.updated/arch/ppc/Kconfig 2002-11-05 11:13:10.000000000 +1100
@@ -1784,9 +1784,9 @@ config DEBUG_HIGHMEM
bool "Highmem debugging"
depends on DEBUG_KERNEL && HIGHMEM

-# config KALLSYMS
-# bool "Load all symbols for debugging/kksymoops"
-# depends on DEBUG_KERNEL
+config KALLSYMS
+ bool "Load all symbols for debugging/kksymoops"
+ depends on DEBUG_KERNEL

config KGDB
bool "Include kgdb kernel debugger"
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .7287-linux-2.5.46/arch/ppc/kernel/process.c .7287-linux-2.5.46.updated/arch/ppc/kernel/process.c
--- .7287-linux-2.5.46/arch/ppc/kernel/process.c 2002-10-15 15:30:52.000000000 +1000
+++ .7287-linux-2.5.46.updated/arch/ppc/kernel/process.c 2002-11-05 11:13:10.000000000 +1100
@@ -34,6 +34,7 @@
#include <linux/prctl.h>
#include <linux/init_task.h>
#include <linux/module.h>
+#include <linux/kallsyms.h>

#include <asm/pgtable.h>
#include <asm/uaccess.h>
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .7287-linux-2.5.46/arch/x86_64/Kconfig .7287-linux-2.5.46.updated/arch/x86_64/Kconfig
--- .7287-linux-2.5.46/arch/x86_64/Kconfig 2002-11-05 11:12:39.000000000 +1100
+++ .7287-linux-2.5.46.updated/arch/x86_64/Kconfig 2002-11-05 11:13:10.000000000 +1100
@@ -739,13 +739,13 @@ config INIT_DEBUG
help
Fill __init and __initdata at the end of boot. This is only for debugging.

-# config KALLSYMS
-# bool "Load all symbols for debugging/kksymoops"
-# depends on DEBUG_KERNEL
-# help
-# Say Y here to let the kernel print out symbolic crash information and
-# symbolic stack backtraces. This increases the size of the kernel
-# somewhat, as all symbols have to be loaded into the kernel image.
+config KALLSYMS
+ bool "Load all symbols for debugging/kksymoops"
+ depends on DEBUG_KERNEL
+ help
+ Say Y here to let the kernel print out symbolic crash information and
+ symbolic stack backtraces. This increases the size of the kernel
+ somewhat, as all symbols have to be loaded into the kernel image.

endmenu

diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .7287-linux-2.5.46/fs/proc/base.c .7287-linux-2.5.46.updated/fs/proc/base.c
--- .7287-linux-2.5.46/fs/proc/base.c 2002-11-05 10:54:27.000000000 +1100
+++ .7287-linux-2.5.46.updated/fs/proc/base.c 2002-11-05 11:13:10.000000000 +1100
@@ -257,20 +257,18 @@ out:
*/
static int proc_pid_wchan(struct task_struct *task, char *buffer)
{
- const char *sym_name, *ignore;
- unsigned long wchan, dummy;
+ char *modname;
+ const char *sym_name;
+ unsigned long wchan, size, offset;

wchan = get_wchan(task);

- if (!kallsyms_address_to_symbol(wchan, &ignore, &dummy, &dummy,
- &ignore, &dummy, &dummy, &sym_name,
- &dummy, &dummy)) {
- return sprintf(buffer, "%lu", wchan);
- }
-
- return sprintf(buffer, "%s", sym_name);
+ sym_name = kallsyms_lookup(wchan, &size, &offset, &modname);
+ if (sym_name)
+ return sprintf(buffer, "%s", sym_name);
+ return sprintf(buffer, "%lu", wchan);
}
-#endif
+#endif /* CONFIG_KALLSYMS */

/************************************************************************/
/* Here the fs part begins */
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .7287-linux-2.5.46/include/linux/kallsyms.h .7287-linux-2.5.46.updated/include/linux/kallsyms.h
--- .7287-linux-2.5.46/include/linux/kallsyms.h 2002-10-15 15:19:44.000000000 +1000
+++ .7287-linux-2.5.46.updated/include/linux/kallsyms.h 2002-11-05 11:13:11.000000000 +1100
@@ -1,163 +1,47 @@
-/* kallsyms headers
- Copyright 2000 Keith Owens <[email protected]>
-
- This file is part of the Linux modutils. It is exported to kernel
- space so debuggers can access the kallsyms data.
-
- The kallsyms data contains all the non-stack symbols from a kernel
- or a module. The kernel symbols are held between __start___kallsyms
- and __stop___kallsyms. The symbols for a module are accessed via
- the struct module chain which is based at module_list.
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2 of the License, or (at your
- option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ident "$Id: linux-2.4.9-kallsyms.patch,v 1.8 2002/02/11 18:34:53 arjanv Exp $"
-
-#ifndef MODUTILS_KALLSYMS_H
-#define MODUTILS_KALLSYMS_H 1
-
-/* Have to (re)define these ElfW entries here because external kallsyms
- * code does not have access to modutils/include/obj.h. This code is
- * included from user spaces tools (modutils) and kernel, they need
- * different includes.
+/* Rewritten and vastly simplified by Rusty Russell for in-kernel
+ * module loader:
+ * Copyright 2002 Rusty Russell <[email protected]> IBM Corporation
*/
+#ifndef _LINUX_KALLSYMS_H
+#define _LINUX_KALLSYMS_H

-#ifndef ELFCLASS32
-#ifdef __KERNEL__
-#include <linux/elf.h>
-#else /* __KERNEL__ */
-#include <elf.h>
-#endif /* __KERNEL__ */
-#endif /* ELFCLASS32 */
-
-#ifndef ELFCLASSM
-#define ELFCLASSM ELF_CLASS
-#endif
-
-#ifndef ElfW
-# if ELFCLASSM == ELFCLASS32
-# define ElfW(x) Elf32_ ## x
-# define ELFW(x) ELF32_ ## x
-# else
-# define ElfW(x) Elf64_ ## x
-# define ELFW(x) ELF64_ ## x
-# endif
-#endif
-
-/* Format of data in the kallsyms section.
- * Most of the fields are small numbers but the total size and all
- * offsets can be large so use the 32/64 bit types for these fields.
- *
- * Do not use sizeof() on these structures, modutils may be using extra
- * fields. Instead use the size fields in the header to access the
- * other bits of data.
- */
-
-struct kallsyms_header {
- int size; /* Size of this header */
- ElfW(Word) total_size; /* Total size of kallsyms data */
- int sections; /* Number of section entries */
- ElfW(Off) section_off; /* Offset to first section entry */
- int section_size; /* Size of one section entry */
- int symbols; /* Number of symbol entries */
- ElfW(Off) symbol_off; /* Offset to first symbol entry */
- int symbol_size; /* Size of one symbol entry */
- ElfW(Off) string_off; /* Offset to first string */
- ElfW(Addr) start; /* Start address of first section */
- ElfW(Addr) end; /* End address of last section */
-};
-
-struct kallsyms_section {
- ElfW(Addr) start; /* Start address of section */
- ElfW(Word) size; /* Size of this section */
- ElfW(Off) name_off; /* Offset to section name */
- ElfW(Word) flags; /* Flags from section */
-};
-
-struct kallsyms_symbol {
- ElfW(Off) section_off; /* Offset to section that owns this symbol */
- ElfW(Addr) symbol_addr; /* Address of symbol */
- ElfW(Off) name_off; /* Offset to symbol name */
-};
-
-#define KALLSYMS_SEC_NAME "__kallsyms"
-#define KALLSYMS_IDX 2 /* obj_kallsyms creates kallsyms as section 2 */
-
-#define kallsyms_next_sec(h,s) \
- ((s) = (struct kallsyms_section *)((char *)(s) + (h)->section_size))
-#define kallsyms_next_sym(h,s) \
- ((s) = (struct kallsyms_symbol *)((char *)(s) + (h)->symbol_size))
+#include <linux/config.h>

#ifdef CONFIG_KALLSYMS
+/* Lookup an address. modname is set to NULL if it's in the kernel. */
+const char *kallsyms_lookup(unsigned long addr,
+ unsigned long *symbolsize,
+ unsigned long *offset,
+ char **modname);

-int kallsyms_symbol_to_address(
- const char *name, /* Name to lookup */
- unsigned long *token, /* Which module to start with */
- const char **mod_name, /* Set to module name or "kernel" */
- unsigned long *mod_start, /* Set to start address of module */
- unsigned long *mod_end, /* Set to end address of module */
- const char **sec_name, /* Set to section name */
- unsigned long *sec_start, /* Set to start address of section */
- unsigned long *sec_end, /* Set to end address of section */
- const char **sym_name, /* Set to full symbol name */
- unsigned long *sym_start, /* Set to start address of symbol */
- unsigned long *sym_end /* Set to end address of symbol */
- );
+/* Replace "%s" in format with address, if found */
+extern void __print_symbol(const char *fmt, unsigned long address);

-int kallsyms_address_to_symbol(
- unsigned long address, /* Address to lookup */
- const char **mod_name, /* Set to module name */
- unsigned long *mod_start, /* Set to start address of module */
- unsigned long *mod_end, /* Set to end address of module */
- const char **sec_name, /* Set to section name */
- unsigned long *sec_start, /* Set to start address of section */
- unsigned long *sec_end, /* Set to end address of section */
- const char **sym_name, /* Set to full symbol name */
- unsigned long *sym_start, /* Set to start address of symbol */
- unsigned long *sym_end /* Set to end address of symbol */
- );
+#else /* !CONFIG_KALLSYMS */

-int kallsyms_sections(void *token,
- int (*callback)(void *, /* token */
- const char *, /* module name */
- const char *, /* section name */
- ElfW(Addr), /* Section start */
- ElfW(Addr), /* Section end */
- ElfW(Word) /* Section flags */
- )
- );
+static inline const char *kallsyms_lookup(unsigned long addr,
+ unsigned long *symbolsize,
+ unsigned long *offset,
+ char **modname)
+{
+ return NULL;
+}

-#else
+/* Stupid that this does nothing, but I didn't create this mess. */
+#define __print_symbol(fmt, addr)
+#endif /*CONFIG_KALLSYMS*/

-static inline int kallsyms_address_to_symbol(
- unsigned long address, /* Address to lookup */
- const char **mod_name, /* Set to module name */
- unsigned long *mod_start, /* Set to start address of module */
- unsigned long *mod_end, /* Set to end address of module */
- const char **sec_name, /* Set to section name */
- unsigned long *sec_start, /* Set to start address of section */
- unsigned long *sec_end, /* Set to end address of section */
- const char **sym_name, /* Set to full symbol name */
- unsigned long *sym_start, /* Set to start address of symbol */
- unsigned long *sym_end /* Set to end address of symbol */
- )
+/* This macro allows us to keep printk typechecking */
+static void __check_printsym_format(const char *fmt, ...)
+__attribute__((format(printf,1,2)));
+static inline void __check_printsym_format(const char *fmt, ...)
{
- return -ESRCH;
}

-#endif
+#define print_symbol(fmt, addr) \
+do { \
+ __check_printsym_format(fmt, ""); \
+ __print_symbol(fmt, addr); \
+} while(0)

-#endif /* kallsyms.h */
+#endif /*_LINUX_KALLSYMS_H*/
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .7287-linux-2.5.46/include/linux/module.h .7287-linux-2.5.46.updated/include/linux/module.h
--- .7287-linux-2.5.46/include/linux/module.h 2002-11-05 11:12:43.000000000 +1100
+++ .7287-linux-2.5.46.updated/include/linux/module.h 2002-11-05 11:13:11.000000000 +1100
@@ -27,8 +27,6 @@
#define MODULE_GENERIC_TABLE(gtype,name)
#define MODULE_DEVICE_TABLE(type,name)
#define MODULE_PARM_DESC(var,desc)
-#define print_symbol(format, addr)
-#define print_modules()

#define MODULE_NAME_LEN (64 - sizeof(unsigned long))
struct kernel_symbol
@@ -136,6 +134,13 @@ struct module
void (*exit)(void);
#endif

+#ifdef CONFIG_KALLSYMS
+ /* We keep the symbol and string tables for kallsyms. */
+ Elf_Sym *symtab;
+ unsigned long num_syms;
+ char *strtab;
+#endif
+
/* The command line arguments (may be mangled). People like
keeping pointers to this stuff */
char args[0];
@@ -248,6 +253,12 @@ do { \
} \
} while(0)

+/* For kallsyms to ask for address resolution. NULL means not found. */
+const char *module_address_lookup(unsigned long addr,
+ unsigned long *symbolsize,
+ unsigned long *offset,
+ char **modname);
+
#else /* !CONFIG_MODULES... */
#define EXPORT_SYMBOL(sym)
#define EXPORT_SYMBOL_GPL(sym)
@@ -261,6 +272,15 @@ do { \
#define module_put(module) do { } while(0)

#define __unsafe(mod)
+
+/* For kallsyms to ask for address resolution. NULL means not found. */
+static inline const char *module_address_lookup(unsigned long addr,
+ unsigned long *symbolsize,
+ unsigned long *offset,
+ char **modname)
+{
+ return NULL;
+}
#endif /* CONFIG_MODULES */

/* For archs to search exception tables */
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .7287-linux-2.5.46/kernel/Makefile .7287-linux-2.5.46.updated/kernel/Makefile
--- .7287-linux-2.5.46/kernel/Makefile 2002-11-05 11:12:41.000000000 +1100
+++ .7287-linux-2.5.46.updated/kernel/Makefile 2002-11-05 11:14:07.000000000 +1100
@@ -4,7 +4,7 @@

export-objs = signal.o sys.o kmod.o workqueue.o ksyms.o pm.o exec_domain.o \
printk.o platform.o suspend.o dma.o module.o cpufreq.o \
- profile.o rcupdate.o intermodule.o params.o
+ profile.o rcupdate.o intermodule.o params.o kallsyms.o

obj-y = sched.o fork.o exec_domain.o panic.o printk.o profile.o \
exit.o itimer.o time.o softirq.o resource.o \
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .7287-linux-2.5.46/kernel/kallsyms.c .7287-linux-2.5.46.updated/kernel/kallsyms.c
--- .7287-linux-2.5.46/kernel/kallsyms.c 2002-10-15 15:30:05.000000000 +1000
+++ .7287-linux-2.5.46.updated/kernel/kallsyms.c 2002-11-05 11:13:11.000000000 +1100
@@ -1,233 +1,105 @@
/*
- * kksymoops.c: in-kernel printing of symbolic oopses and stack traces.
- *
- * Copyright 2000 Keith Owens <[email protected]> April 2000
- * Copyright 2002 Arjan van de Ven <[email protected]>
+ * kallsyms.c: in-kernel printing of symbolic oopses and stack traces.
*
- This code uses the list of all kernel and module symbols to :-
+ * Rewritten and vastly simplified by Rusty Russell for in-kernel
+ * module loader:
+ * Copyright 2002 Rusty Russell <[email protected]> IBM Corporation
+ */
+#include <linux/kallsyms.h>
+#include <linux/module.h>

- * Find any non-stack symbol in a kernel or module. Symbols do
- not have to be exported for debugging.
+static char kallsyms_dummy;

- * Convert an address to the module (or kernel) that owns it, the
- section it is in and the nearest symbol. This finds all non-stack
- symbols, not just exported ones.
+/* These get overridden when the real kallsyms.o is linked in. */
+extern unsigned long kallsyms_addresses[1]
+ __attribute__((alias("kallsyms_dummy"), weak));
+extern unsigned long kallsyms_num_syms
+ __attribute__((alias("kallsyms_dummy"), weak));
+extern char kallsyms_names[1]
+ __attribute__((alias("kallsyms_dummy"), weak));

- */
+/* Defined by the linker script. */
+extern char _stext[], _etext[];

-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/kallsyms.h>
+/* Lookup an address. modname is set to NULL if it's in the kernel. */
+const char *kallsyms_lookup(unsigned long addr,
+ unsigned long *symbolsize,
+ unsigned long *offset,
+ char **modname)
+{
+ unsigned long i, best = 0;

-/* A symbol can appear in more than one module. A token is used to
- * restart the scan at the next module, set the token to 0 for the
- * first scan of each symbol.
- */
+ /* This kernel should never had been booted. */
+ if ((void *)kallsyms_addresses == &kallsyms_dummy)
+ BUG();

-int kallsyms_symbol_to_address(
- const char *name, /* Name to lookup */
- unsigned long *token, /* Which module to start at */
- const char **mod_name, /* Set to module name */
- unsigned long *mod_start, /* Set to start address of module */
- unsigned long *mod_end, /* Set to end address of module */
- const char **sec_name, /* Set to section name */
- unsigned long *sec_start, /* Set to start address of section */
- unsigned long *sec_end, /* Set to end address of section */
- const char **sym_name, /* Set to full symbol name */
- unsigned long *sym_start, /* Set to start address of symbol */
- unsigned long *sym_end /* Set to end address of symbol */
- )
-{
- const struct kallsyms_header *ka_hdr = NULL; /* stupid gcc */
- const struct kallsyms_section *ka_sec;
- const struct kallsyms_symbol *ka_sym = NULL;
- const char *ka_str = NULL;
- const struct module *m;
- int i = 0, l;
- const char *p, *pt_R;
- char *p2;
+ if (addr >= (unsigned long)_stext && addr <= (unsigned long)_etext) {
+ unsigned long symbol_end;
+ char *name = kallsyms_names;

- /* Restart? */
- m = module_list;
- if (token && *token) {
- for (; m; m = m->next)
- if ((unsigned long)m == *token)
- break;
- if (m)
- m = m->next;
- }
+ /* They're sorted, we could be clever here, but who cares? */
+ for (i = 0; i < kallsyms_num_syms; i++) {
+ if (kallsyms_addresses[i] > kallsyms_addresses[best] &&
+ kallsyms_addresses[i] <= addr)
+ best = i;
+ }

- for (; m; m = m->next) {
- if (!mod_member_present(m, kallsyms_start) ||
- !mod_member_present(m, kallsyms_end) ||
- m->kallsyms_start >= m->kallsyms_end)
- continue;
- ka_hdr = (struct kallsyms_header *)m->kallsyms_start;
- ka_sym = (struct kallsyms_symbol *)
- ((char *)(ka_hdr) + ka_hdr->symbol_off);
- ka_str =
- ((char *)(ka_hdr) + ka_hdr->string_off);
- for (i = 0; i < ka_hdr->symbols; ++i, kallsyms_next_sym(ka_hdr, ka_sym)) {
- p = ka_str + ka_sym->name_off;
- if (strcmp(p, name) == 0)
+ /* Grab name */
+ for (i = 0; i < best; i++)
+ name += strlen(name)+1;
+
+ /* Base symbol size on next symbol, but beware aliases. */
+ symbol_end = (unsigned long)_etext;
+ for (i = best+1; i < kallsyms_num_syms; i++) {
+ if (kallsyms_addresses[i] != kallsyms_addresses[best]){
+ symbol_end = kallsyms_addresses[i];
break;
- /* Unversioned requests match versioned names */
- if (!(pt_R = strstr(p, "_R")))
- continue;
- l = strlen(pt_R);
- if (l < 10)
- continue; /* Not _R.*xxxxxxxx */
- (void)simple_strtoul(pt_R+l-8, &p2, 16);
- if (*p2)
- continue; /* Not _R.*xxxxxxxx */
- if (strncmp(p, name, pt_R-p) == 0)
- break; /* Match with version */
+ }
}
- if (i < ka_hdr->symbols)
- break;
- }

- if (token)
- *token = (unsigned long)m;
- if (!m)
- return(0); /* not found */
-
- ka_sec = (const struct kallsyms_section *)
- ((char *)ka_hdr + ka_hdr->section_off + ka_sym->section_off);
- *mod_name = m->name;
- *mod_start = ka_hdr->start;
- *mod_end = ka_hdr->end;
- *sec_name = ka_sec->name_off + ka_str;
- *sec_start = ka_sec->start;
- *sec_end = ka_sec->start + ka_sec->size;
- *sym_name = ka_sym->name_off + ka_str;
- *sym_start = ka_sym->symbol_addr;
- if (i < ka_hdr->symbols-1) {
- const struct kallsyms_symbol *ka_symn = ka_sym;
- kallsyms_next_sym(ka_hdr, ka_symn);
- *sym_end = ka_symn->symbol_addr;
+ *symbolsize = symbol_end - kallsyms_addresses[best];
+ *modname = NULL;
+ *offset = addr - kallsyms_addresses[best];
+ return name;
}
- else
- *sym_end = *sec_end;
- return(1);
+
+ return module_address_lookup(addr, symbolsize, offset, modname);
}

-int kallsyms_address_to_symbol(
- unsigned long address, /* Address to lookup */
- const char **mod_name, /* Set to module name */
- unsigned long *mod_start, /* Set to start address of module */
- unsigned long *mod_end, /* Set to end address of module */
- const char **sec_name, /* Set to section name */
- unsigned long *sec_start, /* Set to start address of section */
- unsigned long *sec_end, /* Set to end address of section */
- const char **sym_name, /* Set to full symbol name */
- unsigned long *sym_start, /* Set to start address of symbol */
- unsigned long *sym_end /* Set to end address of symbol */
- )
+/* Replace "%s" in format with address, or returns -errno. */
+void __print_symbol(const char *fmt, unsigned long address)
{
- const struct kallsyms_header *ka_hdr = NULL; /* stupid gcc */
- const struct kallsyms_section *ka_sec = NULL;
- const struct kallsyms_symbol *ka_sym;
- const char *ka_str;
- const struct module *m;
- int i;
- unsigned long end;
-
- for (m = module_list; m; m = m->next) {
-
- if (!mod_member_present(m, kallsyms_start) ||
- !mod_member_present(m, kallsyms_end) ||
- m->kallsyms_start >= m->kallsyms_end)
- continue;
- ka_hdr = (struct kallsyms_header *)m->kallsyms_start;
- ka_sec = (const struct kallsyms_section *)
- ((char *)ka_hdr + ka_hdr->section_off);
- /* Is the address in any section in this module? */
- for (i = 0; i < ka_hdr->sections; ++i, kallsyms_next_sec(ka_hdr, ka_sec)) {
- if (ka_sec->start <= address &&
- (ka_sec->start + ka_sec->size) > address)
- break;
- }
- if (i < ka_hdr->sections)
- break; /* Found a matching section */
- }
+ char *modname;
+ const char *name;
+ unsigned long offset, size;

- if (!m)
- return(0); /* not found */
+ name = kallsyms_lookup(address, &size, &offset, &modname);

- ka_sym = (struct kallsyms_symbol *)
- ((char *)(ka_hdr) + ka_hdr->symbol_off);
- ka_str =
- ((char *)(ka_hdr) + ka_hdr->string_off);
- *mod_name = m->name;
- *mod_start = ka_hdr->start;
- *mod_end = ka_hdr->end;
- *sec_name = ka_sec->name_off + ka_str;
- *sec_start = ka_sec->start;
- *sec_end = ka_sec->start + ka_sec->size;
- *sym_name = *sec_name; /* In case we find no matching symbol */
- *sym_start = *sec_start;
- *sym_end = *sec_end;
+ if (!name) {
+ char addrstr[sizeof("0x%lx") + (BITS_PER_LONG*3/10)];

- for (i = 0; i < ka_hdr->symbols; ++i, kallsyms_next_sym(ka_hdr, ka_sym)) {
- if (ka_sym->symbol_addr > address)
- continue;
- if (i < ka_hdr->symbols-1) {
- const struct kallsyms_symbol *ka_symn = ka_sym;
- kallsyms_next_sym(ka_hdr, ka_symn);
- end = ka_symn->symbol_addr;
- }
- else
- end = *sec_end;
- if (end <= address)
- continue;
- if ((char *)ka_hdr + ka_hdr->section_off + ka_sym->section_off
- != (char *)ka_sec)
- continue; /* wrong section */
- *sym_name = ka_str + ka_sym->name_off;
- *sym_start = ka_sym->symbol_addr;
- *sym_end = end;
- break;
+ sprintf(addrstr, "0x%lx", address);
+ printk(fmt, addrstr);
+ return;
}
- return(1);
-}

-/* List all sections in all modules. The callback routine is invoked with
- * token, module name, section name, section start, section end, section flags.
- */
-int kallsyms_sections(void *token,
- int (*callback)(void *, const char *, const char *, ElfW(Addr), ElfW(Addr), ElfW(Word)))
-{
- const struct kallsyms_header *ka_hdr = NULL; /* stupid gcc */
- const struct kallsyms_section *ka_sec = NULL;
- const char *ka_str;
- const struct module *m;
- int i;
+ if (modname) {
+ /* This is pretty small. */
+ char buffer[sizeof("%s+%#lx/%#lx [%s]")
+ + strlen(name) + 2*(BITS_PER_LONG*3/10)
+ + strlen(modname)];

- for (m = module_list; m; m = m->next) {
- if (!mod_member_present(m, kallsyms_start) ||
- !mod_member_present(m, kallsyms_end) ||
- m->kallsyms_start >= m->kallsyms_end)
- continue;
- ka_hdr = (struct kallsyms_header *)m->kallsyms_start;
- ka_sec = (const struct kallsyms_section *) ((char *)ka_hdr + ka_hdr->section_off);
- ka_str = ((char *)(ka_hdr) + ka_hdr->string_off);
- for (i = 0; i < ka_hdr->sections; ++i, kallsyms_next_sec(ka_hdr, ka_sec)) {
- if (callback(
- token,
- *(m->name) ? m->name : "kernel",
- ka_sec->name_off + ka_str,
- ka_sec->start,
- ka_sec->start + ka_sec->size,
- ka_sec->flags))
- return(0);
- }
+ sprintf(buffer, "%s+%#lx/%#lx [%s]",
+ name, offset, size, modname);
+ printk(fmt, buffer);
+ } else {
+ char buffer[sizeof("%s+%#lx/%#lx")
+ + strlen(name) + 2*(BITS_PER_LONG*3/10)];
+
+ sprintf(buffer, "%s+%#lx/%#lx", name, offset, size);
+ printk(fmt, buffer);
}
- return(1);
}

-/* Allocate the __kallsyms section, so it's already present in
- * the temporary vmlinux that kallsyms is run on, so the first
- * run will pick up the section info already. */
-
-__asm__(".section __kallsyms,\"a\"\n.previous");
+EXPORT_SYMBOL(kallsyms_lookup);
+EXPORT_SYMBOL(__print_symbol);
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .7287-linux-2.5.46/kernel/module.c .7287-linux-2.5.46.updated/kernel/module.c
--- .7287-linux-2.5.46/kernel/module.c 2002-11-05 11:12:43.000000000 +1100
+++ .7287-linux-2.5.46.updated/kernel/module.c 2002-11-05 11:13:11.000000000 +1100
@@ -1026,6 +1026,11 @@ static struct module *load_module(void *
DEBUGP("Obsolete param found in section %u\n", i);
obsparmindex = i;
}
+#ifdef CONFIG_KALLSYMS
+ /* symbol and string tables for decoding later. */
+ if (sechdrs[i].sh_type == SHT_SYMTAB || i == hdr->e_shstrndx)
+ sechdrs[i].sh_flags |= SHF_ALLOC;
+#endif
#ifndef CONFIG_MODULE_UNLOAD
/* Don't load .exit sections */
if (strstr(secstrings+sechdrs[i].sh_name, ".exit"))
@@ -1138,6 +1143,11 @@ static struct module *load_module(void *
goto cleanup;
}

+#ifdef CONFIG_KALLSYMS
+ mod->symtab = (void *)sechdrs[symindex].sh_offset;
+ mod->num_syms = sechdrs[symindex].sh_size / sizeof(Elf_Sym);
+ mod->strtab = (void *)sechdrs[strindex].sh_offset;
+#endif
err = module_finalize(hdr, sechdrs, mod);
if (err < 0)
goto cleanup;
@@ -1252,9 +1262,82 @@ sys_init_module(void *umod,
return 0;
}

-/* Called by the /proc file system to return a current list of
- modules. Al Viro came up with this interface as an "improvement".
- God save us from any more such interface improvements. */
+#ifdef CONFIG_KALLSYMS
+static inline int inside_init(struct module *mod, unsigned long addr)
+{
+ if (mod->module_init
+ && (unsigned long)mod->module_init <= addr
+ && (unsigned long)mod->module_init + mod->init_size > addr)
+ return 1;
+ return 0;
+}
+
+static inline int inside_core(struct module *mod, unsigned long addr)
+{
+ if ((unsigned long)mod->module_core <= addr
+ && (unsigned long)mod->module_core + mod->core_size > addr)
+ return 1;
+ return 0;
+}
+
+static const char *get_ksymbol(struct module *mod,
+ unsigned long addr,
+ unsigned long *size,
+ unsigned long *offset)
+{
+ unsigned int i, next = 0, best = 0;
+
+ /* Scan for closest preceeding symbol, and next symbol. (ELF
+ starts real symbols at 1). */
+ for (i = 1; i < mod->num_syms; i++) {
+ if (mod->symtab[i].st_shndx == SHN_UNDEF)
+ continue;
+
+ if (mod->symtab[i].st_value <= addr
+ && mod->symtab[i].st_value > mod->symtab[best].st_value)
+ best = i;
+ if (mod->symtab[i].st_value > addr
+ && mod->symtab[i].st_value < mod->symtab[next].st_value)
+ next = i;
+ }
+
+ if (!best)
+ return NULL;
+
+ if (!next) {
+ /* Last symbol? It ends at the end of the module then. */
+ if (inside_core(mod, addr))
+ *size = mod->module_core+mod->core_size - (void*)addr;
+ else
+ *size = mod->module_init+mod->init_size - (void*)addr;
+ } else
+ *size = mod->symtab[next].st_value - addr;
+
+ *offset = addr - mod->symtab[best].st_value;
+ return mod->strtab + mod->symtab[best].st_name;
+}
+
+/* For kallsyms to ask for address resolution. NULL means not found.
+ We don't lock, as this is used for oops resolution and races are a
+ lesser concern. */
+const char *module_address_lookup(unsigned long addr,
+ unsigned long *size,
+ unsigned long *offset,
+ char **modname)
+{
+ struct module *mod;
+
+ list_for_each_entry(mod, &modules, list) {
+ if (inside_core(mod, addr) || inside_init(mod, addr)) {
+ *modname = mod->name;
+ return get_ksymbol(mod, addr, size, offset);
+ }
+ }
+ return NULL;
+}
+#endif /* CONFIG_KALLSYMS */
+
+/* Called by the /proc file system to return a list of modules. */
static void *m_start(struct seq_file *m, loff_t *pos)
{
struct list_head *i;
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .7287-linux-2.5.46/scripts/kallsyms .7287-linux-2.5.46.updated/scripts/kallsyms
--- .7287-linux-2.5.46/scripts/kallsyms 1970-01-01 10:00:00.000000000 +1000
+++ .7287-linux-2.5.46.updated/scripts/kallsyms 2002-11-05 11:13:11.000000000 +1100
@@ -0,0 +1,40 @@
+#! /bin/sh
+# Written by Rusty Russell <[email protected]> 2002.
+
+if [ $# -ne 2 ]; then
+ echo Usage: kallsyms vmlinux objfile >&2
+
+ echo Adds a .kallsyms section containing symbol info.
+ exit 1
+fi
+
+set -e
+
+# Clean up on exit.
+trap "rm -f kallsyms.map kallsyms.c $2" 0
+
+# Takes nm output from $1, produces a .c file on standard output.
+encode_symbols()
+{
+ # First take addresses.
+ echo "unsigned long kallsyms_addresses[] = {"
+ sed 's/^[ ]*\([A-Fa-f0-9]*\).*/0x\1UL,/' < $1
+ echo "};"
+
+ # Now output size.
+ echo "unsigned long kallsyms_num_syms = `wc -l < $1`;"
+
+ # Now output names.
+ echo "char kallsyms_names[] = ";
+ sed 's/^[ ]*[A-Fa-f0-9]*[ ]*.[ ]\(.*\)/"\1\\0"/' < $1
+ echo ";"
+}
+
+# FIXME: Use System.map as input, and regenerate each time in Makefile.
+$NM $1 | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > kallsyms.map
+
+encode_symbols kallsyms.map > kallsyms.c
+$CC $CFLAGS -c -o $2 kallsyms.c
+
+trap "rm -f kallsyms.map kallsyms.c" 0
+exit 0

--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.

2002-11-05 03:12:44

by Werner Almesberger

[permalink] [raw]
Subject: Re: [PATCH] Module loader against 2.5.46: 8/9

[ Cc: trimmed ]

Rusty Russell wrote:
> +config OBSOLETE_MODPARM
> + bool
> + default y
> + help
> + Without this option you will not be able to use module parameters on
> + modules which have not been converted to the new module parameter
> + system yet. If unsure, say Y.

Triple negation, cool :-) How about something like

You need this option to use module parameters on
modules which have not been converted to the new module parameter
system yet. If unsure, say Y.

instead ?

- Werner

--
_________________________________________________________________________
/ Werner Almesberger, Buenos Aires, Argentina [email protected] /
/_http://www.almesberger.net/____________________________________________/

2002-11-05 03:46:03

by Rusty Russell

[permalink] [raw]
Subject: Re: [PATCH] Module loader against 2.5.46: 8/9

In message <[email protected]> you write:
> [ Cc: trimmed ]
>
> Rusty Russell wrote:
> > +config OBSOLETE_MODPARM
> > + bool
> > + default y
> > + help
> > + Without this option you will not be able to use module parameters on
> > + modules which have not been converted to the new module parameter
> > + system yet. If unsure, say Y.
>
> Triple negation, cool :-) How about something like
>
> You need this option to use module parameters on
> modules which have not been converted to the new module parameter
> system yet. If unsure, say Y.
>

No. I don't think that my original version wasn't clear, nor do I
have time to negate every suggestion, no matter how well meaning or
not, even if I had no better things to do, which does not seem likely,
does it not?

Point taken (although note that this option is never prompted for).
Rusty.
--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.

Name: MODULE_PARM support for older modules
Author: Rusty Russell
Status: Experimental
Depends: Module/param-modules.patch.gz
Depends: Module/forceunload.patch.gz

D: This is the backwards compatibility code for MODULE_PARM.

diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .8562-linux-2.5.46/include/linux/module.h .8562-linux-2.5.46.updated/include/linux/module.h
--- .8562-linux-2.5.46/include/linux/module.h 2002-11-05 14:50:29.000000000 +1100
+++ .8562-linux-2.5.46.updated/include/linux/module.h 2002-11-05 14:50:34.000000000 +1100
@@ -15,6 +15,7 @@
#include <linux/compiler.h>
#include <linux/cache.h>
#include <linux/kmod.h>
+#include <linux/stringify.h>
#include <asm/module.h>
#include <asm/uaccess.h> /* For struct exception_table_entry */

@@ -274,6 +275,17 @@ extern spinlock_t modlist_lock;
#define __MOD_DEC_USE_COUNT(mod) module_put(mod)
#define SET_MODULE_OWNER(dev) ((dev)->owner = THIS_MODULE)

+struct obsolete_modparm { char name[64]; char type[64]; void *addr; };
+#ifdef MODULE
+/* DEPRECATED: Do not use. */
+#define MODULE_PARM(var,type) \
+struct obsolete_modparm __parm_##var __attribute__((section(".obsparm"))) = \
+{ __stringify(var), type };
+
+#else
+#define MODULE_PARM(var,type)
+#endif
+
/* People do this inside their init routines, when the module isn't
"live" yet. They should no longer be doing that, but
meanwhile... */
@@ -286,11 +298,11 @@ extern spinlock_t modlist_lock;
#endif
#define MOD_DEC_USE_COUNT module_put(THIS_MODULE)
#define try_inc_mod_count(mod) try_module_get(mod)
-#define MODULE_PARM(parm,string)
#define EXPORT_NO_SYMBOLS
extern int module_dummy_usage;
#define GET_USE_COUNT(module) (module_dummy_usage)
#define MOD_IN_USE 0
+#define __MODULE_STRING(x) __stringify(x)
#define __mod_between(a_start, a_len, b_start, b_len) \
(((a_start) >= (b_start) && (a_start) <= (b_start)+(b_len)) \
|| ((a_start)+(a_len) >= (b_start) \
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .8562-linux-2.5.46/init/Kconfig .8562-linux-2.5.46.updated/init/Kconfig
--- .8562-linux-2.5.46/init/Kconfig 2002-11-05 14:50:32.000000000 +1100
+++ .8562-linux-2.5.46.updated/init/Kconfig 2002-11-05 14:51:03.000000000 +1100
@@ -135,6 +135,15 @@ config MODULE_FORCE_UNLOAD
rmmod). This is mainly for kernel developers and desparate users.
If unsure, say N.

+config OBSOLETE_MODPARM
+ bool
+ default y
+ depends on MODULES
+ help
+ You need this option to use module parameters on modules which
+ have not been converted to the new module parameter system yet.
+ If unsure, say Y.
+
config KMOD
bool "Kernel module loader"
depends on MODULES
@@ -150,4 +159,3 @@ config KMOD
in <file:Documentation/kmod.txt>.

endmenu
-
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .8562-linux-2.5.46/kernel/module.c .8562-linux-2.5.46.updated/kernel/module.c
--- .8562-linux-2.5.46/kernel/module.c 2002-11-05 14:50:32.000000000 +1100
+++ .8562-linux-2.5.46.updated/kernel/module.c 2002-11-05 14:50:34.000000000 +1100
@@ -512,6 +512,129 @@ sys_delete_module(const char *name_user,

#endif /* CONFIG_MODULE_UNLOAD */

+#ifdef CONFIG_OBSOLETE_MODPARM
+static int param_set_byte(const char *val, struct kernel_param *kp)
+{
+ char *endp;
+ long l;
+
+ if (!val) return -EINVAL;
+ l = simple_strtol(val, &endp, 0);
+ if (endp == val || *endp || ((char)l != l))
+ return -EINVAL;
+ *((char *)kp->arg) = l;
+ return 0;
+}
+
+static int param_string(const char *name, const char *val,
+ unsigned int min, unsigned int max,
+ char *dest)
+{
+ if (strlen(val) < min || strlen(val) > max) {
+ printk(KERN_ERR
+ "Parameter %s length must be %u-%u characters\n",
+ name, min, max);
+ return -EINVAL;
+ }
+ strcpy(dest, val);
+ return 0;
+}
+
+extern int set_obsolete(const char *val, struct kernel_param *kp)
+{
+ unsigned int min, max;
+ char *p, *endp;
+ struct obsolete_modparm *obsparm = kp->arg;
+
+ if (!val) {
+ printk(KERN_ERR "Parameter %s needs an argument\n", kp->name);
+ return -EINVAL;
+ }
+
+ /* type is: [min[-max]]{b,h,i,l,s} */
+ p = obsparm->type;
+ min = simple_strtol(p, &endp, 10);
+ if (endp == obsparm->type)
+ min = max = 1;
+ else if (*endp == '-') {
+ p = endp+1;
+ max = simple_strtol(p, &endp, 10);
+ } else
+ max = min;
+ switch (*endp) {
+ case 'b':
+ return param_array(kp->name, val, min, max, obsparm->addr,
+ 1, param_set_byte);
+ case 'h':
+ return param_array(kp->name, val, min, max, obsparm->addr,
+ sizeof(short), param_set_short);
+ case 'i':
+ return param_array(kp->name, val, min, max, obsparm->addr,
+ sizeof(int), param_set_int);
+ case 'l':
+ return param_array(kp->name, val, min, max, obsparm->addr,
+ sizeof(long), param_set_long);
+ case 's':
+ return param_string(kp->name, val, min, max, obsparm->addr);
+ }
+ printk(KERN_ERR "Unknown obsolete parameter type %s\n", obsparm->type);
+ return -EINVAL;
+}
+
+static int obsolete_params(const char *name,
+ char *args,
+ struct obsolete_modparm obsparm[],
+ unsigned int num,
+ Elf_Shdr *sechdrs,
+ unsigned int symindex,
+ const char *strtab)
+{
+ struct kernel_param *kp;
+ unsigned int i;
+ int ret;
+
+ kp = kmalloc(sizeof(kp[0]) * num, GFP_KERNEL);
+ if (!kp)
+ return -ENOMEM;
+
+ for (i = 0; i < num; i++) {
+ kp[i].name = obsparm[i].name;
+ kp[i].perm = 000;
+ kp[i].set = set_obsolete;
+ kp[i].get = NULL;
+ obsparm[i].addr
+ = (void *)find_local_symbol(sechdrs, symindex, strtab,
+ obsparm[i].name);
+ if (!obsparm[i].addr) {
+ printk("%s: falsely claims to have parameter %s\n",
+ name, obsparm[i].name);
+ ret = -EINVAL;
+ goto out;
+ }
+ kp[i].arg = &obsparm[i];
+ }
+
+ ret = parse_args(name, args, kp, num, NULL);
+ out:
+ kfree(kp);
+ return ret;
+}
+#else
+static int obsolete_params(const char *name,
+ char *args,
+ struct obsolete_modparm obsparm[],
+ unsigned int num,
+ Elf_Shdr *sechdrs,
+ unsigned int symindex,
+ const char *strtab)
+{
+ if (num != 0)
+ printk(KERN_WARNING "%s: Ignoring obsolete parameters\n",
+ name);
+ return 0;
+}
+#endif /* CONFIG_OBSOLETE_MODPARM */
+
/* Find an symbol for this module (ie. resolve internals first).
It we find one, record usage. Must be holding module_mutex. */
unsigned long find_symbol_internal(Elf_Shdr *sechdrs,
@@ -823,7 +946,7 @@ static struct module *load_module(void *
Elf_Shdr *sechdrs;
char *secstrings;
unsigned int i, symindex, exportindex, strindex, setupindex, exindex,
- modnameindex;
+ modnameindex, obsparmindex;
long arglen;
unsigned long common_length;
struct sizes sizes, used;
@@ -861,7 +984,7 @@ static struct module *load_module(void *

/* May not export symbols, or have setup params, so these may
not exist */
- exportindex = setupindex = 0;
+ exportindex = setupindex = obsparmindex = 0;

/* And these should exist, but gcc whinges if we don't init them */
symindex = strindex = exindex = modnameindex = 0;
@@ -897,6 +1020,11 @@ static struct module *load_module(void *
/* Exception table */
DEBUGP("Exception table found in section %u\n", i);
exindex = i;
+ } else if (strcmp(secstrings+sechdrs[i].sh_name, ".obsparm")
+ == 0) {
+ /* Obsolete MODULE_PARM() table */
+ DEBUGP("Obsolete param found in section %u\n", i);
+ obsparmindex = i;
}
#ifndef CONFIG_MODULE_UNLOAD
/* Don't load .exit sections */
@@ -1014,13 +1142,23 @@ static struct module *load_module(void *
if (err < 0)
goto cleanup;

- /* Size of section 0 is 0, so this works well if no params */
- err = parse_args(mod->args,
- (struct kernel_param *)
- sechdrs[setupindex].sh_offset,
- sechdrs[setupindex].sh_size
- / sizeof(struct kernel_param),
- NULL);
+ if (obsparmindex) {
+ err = obsolete_params(mod->name, mod->args,
+ (struct obsolete_modparm *)
+ sechdrs[obsparmindex].sh_offset,
+ sechdrs[obsparmindex].sh_size
+ / sizeof(struct obsolete_modparm),
+ sechdrs, symindex,
+ (char *)sechdrs[strindex].sh_offset);
+ } else {
+ /* Size of section 0 is 0, so this works well if no params */
+ err = parse_args(mod->name, mod->args,
+ (struct kernel_param *)
+ sechdrs[setupindex].sh_offset,
+ sechdrs[setupindex].sh_size
+ / sizeof(struct kernel_param),
+ NULL);
+ }
if (err < 0)
goto cleanup;

2002-11-05 04:02:33

by Werner Almesberger

[permalink] [raw]
Subject: Re: [PATCH] Module loader against 2.5.46: 8/9

Rusty Russell wrote:
> Point taken

Thanks :-)

> (although note that this option is never prompted for).

Aha, learned something new about Kconfig. Subtle ! ;-)
Well, I guess, some fine day, it will ...

- Werner

--
_________________________________________________________________________
/ Werner Almesberger, Buenos Aires, Argentina [email protected] /
/_http://www.almesberger.net/____________________________________________/

2002-11-05 04:18:46

by Rusty Russell

[permalink] [raw]
Subject: Re: [PATCH] Module loader against 2.5.46: 8/9

In message <[email protected]> you write:
> Rusty Russell wrote:
> > (although note that this option is never prompted for).
>
> Aha, learned something new about Kconfig. Subtle ! ;-)
> Well, I guess, some fine day, it will ...

Kconfig is way cool. The transition to a CONFIG_OBSOLETE version
sometime soon (eg 2.7) is now trivial.

Rusty.
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.

2002-11-06 12:37:21

by Keith Owens

[permalink] [raw]
Subject: Re: [PATCH] Module loader against 2.5.46: 9/9

On Tue, 05 Nov 2002 11:47:27 +1100,
Rusty Russell <[email protected]> wrote:
>Since I believe kallsyms is important, this reimplements it sanely,
>using the current module infrastructure, and not using an external
>kallsyms script.
>
>FYI, the previous interface was:
>
>int kallsyms_symbol_to_address(
> const char *name, /* Name to lookup */
> unsigned long *token, /* Which module to start with */
> const char **mod_name, /* Set to module name or "kernel" */
> unsigned long *mod_start, /* Set to start address of module */
> unsigned long *mod_end, /* Set to end address of module */
> const char **sec_name, /* Set to section name */
> unsigned long *sec_start, /* Set to start address of section */
> unsigned long *sec_end, /* Set to end address of section */
> const char **sym_name, /* Set to full symbol name */
> unsigned long *sym_start, /* Set to start address of symbol */
> unsigned long *sym_end /* Set to end address of symbol */
> );
>
>The new one is:
>/* Lookup an address. modname is set to NULL if it's in the kernel. */
>const char *kallsyms_lookup(unsigned long addr,
> unsigned long *symbolsize,
> unsigned long *offset,
> char **modname);

If you are going to change the interface then don't call it kallsyms.
kallsyms and that interface were designed to kernel debugging in
general and kdb in particular. I need all the fields for decent
debugging and I refuse to allow my kallsyms code to be appropiated for
somebody else's usage if it stops kdb from working!

2002-11-06 16:39:14

by Bill Davidsen

[permalink] [raw]
Subject: Re: [PATCH] Module loader against 2.5.46: 8/9

On Tue, 5 Nov 2002, Rusty Russell wrote:

> In message <[email protected]> you write:
> > [ Cc: trimmed ]
> >
> > Rusty Russell wrote:
> > > +config OBSOLETE_MODPARM
> > > + bool
> > > + default y
> > > + help
> > > + Without this option you will not be able to use module parameters on
> > > + modules which have not been converted to the new module parameter
> > > + system yet. If unsure, say Y.
> >
> > Triple negation, cool :-) How about something like
> >
> > You need this option to use module parameters on
> > modules which have not been converted to the new module parameter
> > system yet. If unsure, say Y.
> >
>
> No. I don't think that my original version wasn't clear, nor do I
> have time to negate every suggestion, no matter how well meaning or
> not, even if I had no better things to do, which does not seem likely,
> does it not?

Please don't take this personally, but you just used another double
negative in your response. Now you may think that way, and talk that way,
but a lot of people who use Linux are not native speakers of English, and
from experience I suggest that the complex gramatical constructs in all
the help stuff should be avoided. Eschew obfuscation.

> Point taken (although note that this option is never prompted for).

Then why have help at all? In fact why have the whole option if it can't
be used? I assume you meant something else entirely, other than "can't be
used."

--
bill davidsen <[email protected]>
CTO, TMR Associates, Inc
Doing interesting things with little computers since 1979.

2002-11-08 00:25:59

by Rusty Russell

[permalink] [raw]
Subject: Re: [PATCH] Module loader against 2.5.46: 8/9

In message <[email protected]> you w
rite:
> On Tue, 5 Nov 2002, Rusty Russell wrote:
> > No. I don't think that my original version wasn't clear, nor do I
> > have time to negate every suggestion, no matter how well meaning or
> > not, even if I had no better things to do, which does not seem likely,
> > does it not?
>
> Please don't take this personally, but you just used another double
> negative in your response.

Did I? Not that I'm not sorry, but I just didn't realize my lack of
clarity was causing confusion. I shall take your words to heart.

> Now you may think that way, and talk that way, but a lot of people
> who use Linux are not native speakers of English, and from
> experience I suggest that the complex gramatical constructs in all
> the help stuff should be avoided.

I'd never have thought of that myself, but you're right. Even among
our peers on this mailing list, for example, the nuances of English
sometimes go astray.

I will try to ensure my writing is straigtforward and impossible to
misunderstand.

> Eschew obfuscation.

Sorry, I don't understand?

But thankyou for your insight!
Rusty.
--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.

2002-11-08 00:25:58

by Rusty Russell

[permalink] [raw]
Subject: Re: [PATCH] Module loader against 2.5.46: 9/9

In message <[email protected]> you write:
> On Tue, 05 Nov 2002 11:47:27 +1100,
> Rusty Russell <[email protected]> wrote:
> >The new one is:
> >/* Lookup an address. modname is set to NULL if it's in the kernel. */
> >const char *kallsyms_lookup(unsigned long addr,
> > unsigned long *symbolsize,
> > unsigned long *offset,
> > char **modname);
>
> If you are going to change the interface then don't call it kallsyms.
> kallsyms and that interface were designed to kernel debugging in
> general and kdb in particular.

That explains it: I didn't think you were insane 8). Thanks, I'll
move it to some other name which just does the "add symbols to oops"
minimum.

Thanks!
Rusty.
--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.

2002-11-08 03:13:35

by Randy.Dunlap

[permalink] [raw]
Subject: Re: [PATCH] Module loader against 2.5.46: 8/9

On Thu, 7 Nov 2002, Rusty Russell wrote:

| In message <[email protected]> you w
| rite:
| > On Tue, 5 Nov 2002, Rusty Russell wrote:
| > > No. I don't think that my original version wasn't clear, nor do I
| > > have time to negate every suggestion, no matter how well meaning or
| > > not, even if I had no better things to do, which does not seem likely,
| > > does it not?
| >
| > Please don't take this personally, but you just used another double
| > negative in your response.
|
| Did I? Not that I'm not sorry, but I just didn't realize my lack of
| clarity was causing confusion. I shall take your words to heart.

So you did it again, this time on purpose, right? ;)
("Not that I'm not sorry")

| > Now you may think that way, and talk that way, but a lot of people
| > who use Linux are not native speakers of English, and from
| > experience I suggest that the complex gramatical constructs in all
| > the help stuff should be avoided.
|
| I'd never have thought of that myself, but you're right. Even among
| our peers on this mailing list, for example, the nuances of English
| sometimes go astray.
|
| I will try to ensure my writing is straigtforward and impossible to
| misunderstand.
|
| But thankyou for your insight!
| Rusty.
| --

--
~Randy
location: NPP-4E

2002-11-08 09:28:51

by Russell King

[permalink] [raw]
Subject: Re: [PATCH] Module loader against 2.5.46: 9/9

On Thu, Nov 07, 2002 at 10:08:24PM +1100, Rusty Russell wrote:
> That explains it: I didn't think you were insane 8). Thanks, I'll
> move it to some other name which just does the "add symbols to oops"
> minimum.

I doubt that we need all of the kallsyms data in the kernel as well (unless
you're using kdb.)

One of the things on my todo list is to look into a kallsyms replacement
that allows cross-compilation (and actually allows kallsyms to work at
all on ARM.)

ARM requires the ELF architecture private flags to be set correctly to link
two objects together. So there's two problems with the current setup:

1. can't cross-compile with kallsyms
2. can't natively compile with kallsyms on architectures that require
the private flags to be set correctly.

--
Russell King ([email protected]) The developer of ARM Linux
http://www.arm.linux.org.uk/personal/aboutme.html

2002-11-08 21:09:12

by Bill Davidsen

[permalink] [raw]
Subject: Re: [PATCH] Module loader against 2.5.46: 8/9

On Thu, 7 Nov 2002, Rusty Russell wrote:

> In message <[email protected]> you w
> rite:
> > On Tue, 5 Nov 2002, Rusty Russell wrote:
> > > No. I don't think that my original version wasn't clear, nor do I
> > > have time to negate every suggestion, no matter how well meaning or
> > > not, even if I had no better things to do, which does not seem likely,
> > > does it not?
> >
> > Please don't take this personally, but you just used another double
> > negative in your response.
>
> Did I? Not that I'm not sorry, but I just didn't realize my lack of
> clarity was causing confusion. I shall take your words to heart.
>
> > Now you may think that way, and talk that way, but a lot of people
> > who use Linux are not native speakers of English, and from
> > experience I suggest that the complex gramatical constructs in all
> > the help stuff should be avoided.
>
> I'd never have thought of that myself, but you're right. Even among
> our peers on this mailing list, for example, the nuances of English
> sometimes go astray.

Sure, we have people mentally translating English into totally dissimilar
languages like Finnish, German, Russian, Czech, and British.

>
> I will try to ensure my writing is straigtforward and impossible to
> misunderstand.
>
> > Eschew obfuscation.
>
> Sorry, I don't understand?
eschew = roughly "avoid" or "stay away from"
obfuscation = the process of making something obscure
>
> But thankyou for your insight!
> Rusty.
> --
> Anyone who quotes me in their sig is an idiot. -- Rusty Russell.
>

--
bill davidsen <[email protected]>
CTO, TMR Associates, Inc
Doing interesting things with little computers since 1979.

2002-11-09 04:09:18

by Rusty Russell

[permalink] [raw]
Subject: Re: [PATCH] Module loader against 2.5.46: 9/9

In message <[email protected]> you write:
> On Thu, Nov 07, 2002 at 10:08:24PM +1100, Rusty Russell wrote:
> > That explains it: I didn't think you were insane 8). Thanks, I'll
> > move it to some other name which just does the "add symbols to oops"
> > minimum.
>
> I doubt that we need all of the kallsyms data in the kernel as well (unless
> you're using kdb.)

Yes. From my IDE oops dumper experience, you can get the required
kernel symbols down to 70k w/o kdb (it's about 380k as stands). I
haven't made this optimization yet though.

> One of the things on my todo list is to look into a kallsyms replacement
> that allows cross-compilation (and actually allows kallsyms to work at
> all on ARM.)
>
> ARM requires the ELF architecture private flags to be set correctly to link
> two objects together. So there's two problems with the current setup:

Hmm, depends on state of module loader code. If it goes in, you'll
be getting a new one anyway which doesn't have this problem (I use $CC
to create kallsyms.o which gets linked in). Otherwise, yes.

Cheers,
Rusty.
--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.

2002-11-09 12:21:10

by Mark H. Wood

[permalink] [raw]
Subject: Re: [PATCH] Module loader against 2.5.46: 8/9

On Fri, 8 Nov 2002, Bill Davidsen wrote:
> On Thu, 7 Nov 2002, Rusty Russell wrote:
> > In message <[email protected]> you w
> > rite:
[snip]
> > > Eschew obfuscation.
> >
> > Sorry, I don't understand?
> eschew = roughly "avoid" or "stay away from"
Or "choose not to use". One does not say, "eschew that bear."
> obfuscation = the process of making something obscure

And the whole thing ("eschew obfuscation") is a stock expression in
English, meaning "don't use unfamiliar words when familiar words will
express what you mean." There's an implied self-reference: "eschew
obfuscation" is a very obscure way of saying "keep it simple". It's
mildly funny.

--
Mark H. Wood, amateur linguist [email protected]
MS Windows *is* user-friendly, but only for certain values of "user".

2002-11-10 03:51:25

by Rusty Russell

[permalink] [raw]
Subject: Re: [PATCH] Module loader against 2.5.46: 8/9

In message <[email protected]> you wri
te:
> On Fri, 8 Nov 2002, Bill Davidsen wrote:
> > eschew = roughly "avoid" or "stay away from"
> Or "choose not to use". One does not say, "eschew that bear."
> > obfuscation = the process of making something obscure
>
> And the whole thing ("eschew obfuscation") is a stock expression in
> English, meaning "don't use unfamiliar words when familiar words will
> express what you mean."

Thankyou both for your explanations.

Back on topic, I think Bill brought up a good point: someone willing
to criticize nontrivial uses of English in the kernel would fill a
much-needed void in Linux.

Bill, would you be prepared for such a role? I think we'd be lucky to
have either of you contribute patches.

Cheers!
Rusty.
--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.

2002-11-11 11:58:49

by Horst H. von Brand

[permalink] [raw]
Subject: Re: [PATCH] Module loader against 2.5.46: 8/9

Bill Davidsen <[email protected]> said:

[...]

> Sure, we have people mentally translating English into totally dissimilar
> languages like Finnish, German, Russian, Czech, and British.

"Mentally translating" doesn't work, you have to learn to think in the
"foreign" language(s).
--
Dr. Horst H. von Brand User #22616 counter.li.org
Departamento de Informatica Fono: +56 32 654431
Universidad Tecnica Federico Santa Maria +56 32 654239
Casilla 110-V, Valparaiso, Chile Fax: +56 32 797513

2002-11-11 12:27:01

by Richard B. Johnson

[permalink] [raw]
Subject: Re: [PATCH] Module loader against 2.5.46: 8/9

On Mon, 11 Nov 2002, Horst von Brand wrote:

> Bill Davidsen <[email protected]> said:
>
> [...]
>
> > Sure, we have people mentally translating English into totally dissimilar
> > languages like Finnish, German, Russian, Czech, and British.
^^^^^^^^
English into British, I love it!

> "Mentally translating" doesn't work, you have to learn to think in the
> "foreign" language(s).
> --
> Dr. Horst H. von Brand User #22616 counter.li.org
> Departamento de Informatica Fono: +56 32 654431
> Universidad Tecnica Federico Santa Maria +56 32 654239
> Casilla 110-V, Valparaiso, Chile Fax: +56 32 797513
> -

--- and the first thing you learn, when learning a new language,
is how to swear. It's important to align your thought processes!

Cheers,
Dick Johnson
Penguin : Linux version 2.4.18 on an i686 machine (797.90 BogoMips).
Bush : The Fourth Reich of America