diff --git a/stand/common/modinfo.c b/stand/common/modinfo.c --- a/stand/common/modinfo.c +++ b/stand/common/modinfo.c @@ -114,6 +114,8 @@ const char md_modtype_obj[] = MODTYPE_OBJ; const char md_kerntype_mb[] = KERNTYPE_MB; +static vm_offset_t mod_align_size; + vm_offset_t md_copymodules(vm_offset_t addr, bool kern64) { @@ -195,6 +197,51 @@ return(last); } +static int +md_set_mod_align_size(struct env_var *ev, int flags, const void *value) +{ + long v; + char *ep; + + /* + * Must be at least as large as PAGE_SIZE, but no more than 32k times + * that (4k to 32MB on x86) and a power of 2. This should be more than + * adequate. + */ + v = strtol(value, &ep, 0); + if (v < PAGE_SIZE || v > PAGE_SIZE * 32768 || (v & (v - 1)) != 0) { + printf("bad value %s for mod_align_size\n", (const char *)value); + return (-1); + } + + /* + * First time through we set it as EV_DYNAMIC to the string + * representation of the page size. So now we just replace that string + * with the new value we set, converted to decimal. + */ + // assert(ev->ev_flags & EV_DYNAMIC); + free(ev->ev_value); + asprintf(&ep, "%ld", v); + ev->ev_value = ep; + + return (0); +} + +/* + * Initialize the module subsystem. It's optional, but to override the + * mod_align_size, it has to be called before we load the kernel, the first + * use of md_align. + */ +static void +md_init(void) +{ + char *value; + + asprintf(&value, "%d", (int)PAGE_SIZE); + env_setenv("mod_align_size", EV_DYNAMIC, value, md_set_mod_align_size, + env_nounset); +} + /* * Take the ending address and round it up to the currently required * alignment. This typically is the page size, but is the larger of the compiled @@ -211,5 +258,8 @@ vm_offset_t md_align(vm_offset_t addr) { - return (roundup(addr, PAGE_SIZE)); + if (mod_align_size == 0) + md_init(); + + return (roundup(addr, mod_align_size)); }