On Sat, 28 Apr 2012, Paul Goyette wrote:
How about another alternative?
Rather than using .ctor/dtor for _MODULE mode, and a link-set for the
built-in mode, we could extend the modinfo_t structure to include two new
members:
char *mi_ctor_section, *mi_dtor_section
Then the module's code can continue to use the link_set paradigm, and the
module loader can use the names provided rather than hard-coding ".ctor" and
".dtor". And that means that (this part of) the module doesn't need to be
aware of whether it is built-in or not.
This would also mean that net80211 module no longer needs its own code to
process the __link_set_foreach(), since the module loader would take care of
this automatically?
Of course, this would definitely require a kernel version bump, since
module_t would be changing. And I would propose we use a MODULE_NEW
declaration, and redefine MODULE to specify NULL values for the two new
members.
/* Module header structure. */
typedef struct modinfo {
u_int mi_version;
modclass_t mi_class;
int (*mi_modcmd)(modcmd_t, void *);
const char *mi_name;
const char *mi_required;
const char *mi_ctor_section;
const char *mi_dtor_section;
} const modinfo_t;
...
/*
* Per-module linkage. Loadable modules have a `link_set_modules' section
* containing only one entry, pointing to the module's modinfo_t record.
* For the kernel, `link_set_modules' can contain multiple entries and
* records all modules built into the kernel at link time.
*/
#define MODULE(class, name, required) \
MODULE_NEW(class, name, required, NULL, NULL)
#define MODULE_NEW(class, name, required, ctor, dtor) \
static int name##_modcmd(modcmd_t, void *); \
static const modinfo_t name##_modinfo = { \
.mi_version = __NetBSD_Version__, \
.mi_class = (class), \
.mi_modcmd = name##_modcmd, \
.mi_name = #name, \
.mi_required = (required), \
.mi_ctor_section = ctor, \
.mi_dtor_section = dtor \
}; \
Unfortunately, this approach doesn't work for built-in modules.
For built-in modules, we don't (seem to) have a list of the kernel's
program sections, and the module's mod->mod_kobj is NULL. So we can't
use the section table to get the start address or size of the section.
We do have the start/end symbols that __link_set_foreach() uses to
enumerate the members.
For non-built-in modules (whether loaded by boot loader, or later from
the file system), we have the section info (it's in the kobj->ko_progtab
member), but we don't seem to get the start/end symbols. (Perhaps this
could be resolved with some crt*.o type magic, but it appears that the
user-land crt stuff is GPL'd so not suitable for kernel use?)
So it seems that we just can't get a single mechanism to work for all
modules regardless of source (built-in, boot, or filesys).
-------------------------------------------------------------------------
| Paul Goyette | PGP Key fingerprint: | E-mail addresses: |
| Customer Service | FA29 0E3B 35AF E8AE 6651 | paul at whooppee.com |
| Network Engineer | 0786 F758 55DE 53BA 7731 | pgoyette at juniper.net |
| Kernel Developer | | pgoyette at netbsd.org |
-------------------------------------------------------------------------