Commit 66f67a6b authored by Rusty Russell's avatar Rusty Russell Committed by Linus Torvalds

[PATCH] Allocate struct module using special allocator

Sparc64 (and probably others) need all the kernel symbols within
32-bits, which includes the manufactured "__this_module" which refers
to the struct module *.

This changes the interface back to its old style: the arch-specific code
manipulates the init and core sizes, and we call module_alloc() ourselves.
parent 3d19ab58
...@@ -28,22 +28,15 @@ ...@@ -28,22 +28,15 @@
#define DEBUGP(fmt , ...) #define DEBUGP(fmt , ...)
#endif #endif
static void *alloc_and_zero(unsigned long size) void *module_alloc(unsigned long size)
{ {
void *ret;
/* We handle the zero case fine, unlike vmalloc */
if (size == 0) if (size == 0)
return NULL; return NULL;
return vmalloc(size);
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 */
/* Free memory returned from module_alloc */
void module_free(struct module *mod, void *module_region) void module_free(struct module *mod, void *module_region)
{ {
vfree(module_region); vfree(module_region);
...@@ -51,20 +44,21 @@ void module_free(struct module *mod, void *module_region) ...@@ -51,20 +44,21 @@ void module_free(struct module *mod, void *module_region)
table entries. */ table entries. */
} }
void *module_core_alloc(const Elf32_Ehdr *hdr, /* We don't need anything special. */
const Elf32_Shdr *sechdrs, long module_core_size(const Elf32_Ehdr *hdr,
const char *secstrings, const Elf32_Shdr *sechdrs,
struct module *module) const char *secstrings,
struct module *module)
{ {
return alloc_and_zero(module->core_size); return module->core_size;
} }
void *module_init_alloc(const Elf32_Ehdr *hdr, long module_init_size(const Elf32_Ehdr *hdr,
const Elf32_Shdr *sechdrs, const Elf32_Shdr *sechdrs,
const char *secstrings, const char *secstrings,
struct module *module) struct module *module)
{ {
return alloc_and_zero(module->init_size); return module->init_size;
} }
int apply_relocate(Elf32_Shdr *sechdrs, int apply_relocate(Elf32_Shdr *sechdrs,
......
...@@ -15,20 +15,26 @@ unsigned long find_symbol_internal(Elf_Shdr *sechdrs, ...@@ -15,20 +15,26 @@ unsigned long find_symbol_internal(Elf_Shdr *sechdrs,
/* These must be implemented by the specific architecture */ /* These must be implemented by the specific architecture */
/* vmalloc AND zero for the non-releasable code; return ERR_PTR() on error. */ /* Total size to allocate for the non-releasable code; return len or
void *module_core_alloc(const Elf_Ehdr *hdr, -error. mod->core_size is the current generic tally. */
const Elf_Shdr *sechdrs, long module_core_size(const Elf_Ehdr *hdr,
const char *secstrings, const Elf_Shdr *sechdrs,
struct module *mod); const char *secstrings,
struct module *mod);
/* vmalloc and zero (if any) for sections to be freed after init.
Return ERR_PTR() on error. */ /* Total size of (if any) sections to be freed after init. Return 0
void *module_init_alloc(const Elf_Ehdr *hdr, for none, len, or -error. mod->init_size is the current generic
const Elf_Shdr *sechdrs, tally. */
const char *secstrings, long module_init_size(const Elf_Ehdr *hdr,
struct module *mod); const Elf_Shdr *sechdrs,
const char *secstrings,
/* Free memory returned from module_core_alloc/module_init_alloc */ struct module *mod);
/* Allocator used for allocating struct module, core sections and init
sections. Returns NULL on failure. */
void *module_alloc(unsigned long size);
/* Free memory returned from module_alloc. */
void module_free(struct module *mod, void *module_region); void module_free(struct module *mod, void *module_region);
/* Apply the given relocation to the (simplified) ELF. Return -error /* Apply the given relocation to the (simplified) ELF. Return -error
......
...@@ -557,7 +557,7 @@ static void free_module(struct module *mod) ...@@ -557,7 +557,7 @@ static void free_module(struct module *mod)
module_unload_free(mod); module_unload_free(mod);
/* Finally, free the module structure */ /* Finally, free the module structure */
kfree(mod); module_free(mod, mod);
} }
void *__symbol_get(const char *symbol) void *__symbol_get(const char *symbol)
...@@ -805,7 +805,7 @@ static struct module *load_module(void *umod, ...@@ -805,7 +805,7 @@ static struct module *load_module(void *umod,
unsigned long common_length; unsigned long common_length;
struct sizes sizes, used; struct sizes sizes, used;
struct module *mod; struct module *mod;
int err = 0; long err = 0;
void *ptr = NULL; /* Stops spurious gcc uninitialized warning */ void *ptr = NULL; /* Stops spurious gcc uninitialized warning */
DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n", DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n",
...@@ -894,7 +894,7 @@ static struct module *load_module(void *umod, ...@@ -894,7 +894,7 @@ static struct module *load_module(void *umod,
goto free_hdr; goto free_hdr;
arglen = err; arglen = err;
mod = kmalloc(sizeof(*mod) + arglen+1, GFP_KERNEL); mod = module_alloc(sizeof(*mod) + arglen+1);
if (!mod) { if (!mod) {
err = -ENOMEM; err = -ENOMEM;
goto free_hdr; goto free_hdr;
...@@ -925,20 +925,36 @@ static struct module *load_module(void *umod, ...@@ -925,20 +925,36 @@ static struct module *load_module(void *umod,
common_length = read_commons(hdr, &sechdrs[symindex]); common_length = read_commons(hdr, &sechdrs[symindex]);
sizes.core_size += common_length; sizes.core_size += common_length;
/* Set these up: arch's can add to them */ /* Set these up, and allow archs to manipulate them. */
mod->core_size = sizes.core_size; mod->core_size = sizes.core_size;
mod->init_size = sizes.init_size; mod->init_size = sizes.init_size;
/* Allocate (this is arch specific) */ /* Allow archs to add to them. */
ptr = module_core_alloc(hdr, sechdrs, secstrings, mod); err = module_init_size(hdr, sechdrs, secstrings, mod);
if (IS_ERR(ptr)) if (err < 0)
goto free_mod; goto free_mod;
mod->init_size = err;
err = module_core_size(hdr, sechdrs, secstrings, mod);
if (err < 0)
goto free_mod;
mod->core_size = err;
/* Do the allocs. */
ptr = module_alloc(mod->core_size);
if (!ptr) {
err = -ENOMEM;
goto free_mod;
}
memset(ptr, 0, mod->core_size);
mod->module_core = ptr; mod->module_core = ptr;
ptr = module_init_alloc(hdr, sechdrs, secstrings, mod); ptr = module_alloc(mod->init_size);
if (IS_ERR(ptr)) if (!ptr) {
err = -ENOMEM;
goto free_core; goto free_core;
}
memset(ptr, 0, mod->init_size);
mod->module_init = ptr; mod->module_init = ptr;
/* Transfer each section which requires ALLOC, and set sh_offset /* Transfer each section which requires ALLOC, and set sh_offset
...@@ -1015,7 +1031,7 @@ static struct module *load_module(void *umod, ...@@ -1015,7 +1031,7 @@ static struct module *load_module(void *umod,
free_core: free_core:
module_free(mod, mod->module_core); module_free(mod, mod->module_core);
free_mod: free_mod:
kfree(mod); module_free(mod, mod);
free_hdr: free_hdr:
vfree(hdr); vfree(hdr);
if (err < 0) return ERR_PTR(err); if (err < 0) return ERR_PTR(err);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment