--- zzzz-none-000/linux-3.10.107/kernel/module.c 2017-06-27 09:49:32.000000000 +0000 +++ vr9-7490-729/linux-3.10.107/kernel/module.c 2021-11-10 11:53:56.000000000 +0000 @@ -63,6 +63,12 @@ #include #include #include "module-internal.h" +#if defined(CONFIG_AVM_ENHANCED) && defined(CONFIG_LANTIQ) +#include /*--- nur Lantiq ! ---*/ +#endif/*--- #if defined(CONFIG_AVM_ENHANCED) ---*/ +#if defined(CONFIG_BUG_EXTRA_INFO) +#include +#endif/*--- #if defined(CONFIG_BUG_EXTRA_INFO) ---*/ #define CREATE_TRACE_POINTS #include @@ -622,6 +628,12 @@ MODINFO_ATTR(srcversion); static char last_unloaded_module[MODULE_NAME_LEN+1]; +#if defined(CONFIG_AVM_ENHANCED) +static unsigned long last_unloaded_module_jiffies; +/*--- Berechnung bei ARCH_DMA_MINALIGN = 32 Byte korrekt, solange size <= 128 Byte ---*/ +#define MY_ALIGN_BIT (ffs(ARCH_DMA_MINALIGN) - 1) +#define SLAB_ORG_SIZE(size) (((((size-1) >> MY_ALIGN_BIT) + 1) << MY_ALIGN_BIT)) +#endif/*--- #if defined(CONFIG_AVM_ENHANCED) ---*/ #ifdef CONFIG_MODULE_UNLOAD @@ -828,7 +840,7 @@ { struct module *mod; char name[MODULE_NAME_LEN]; - int ret, forced = 0; + int ret, forced = 0, status; if (!capable(CAP_SYS_MODULE) || modules_disabled) return -EPERM; @@ -887,13 +899,19 @@ /* Final destruction now no one is using it. */ if (mod->exit != NULL) mod->exit(); - blocking_notifier_call_chain(&module_notify_list, - MODULE_STATE_GOING, mod); + status = blocking_notifier_call_chain(&module_notify_list, MODULE_STATE_GOING, mod); +#if defined(CONFIG_AVM_ENHANCED) + if(status == NOTIFY_BAD) { + return -EBUSY; + } +#endif/*--- #if defined(CONFIG_AVM_ENHANCED) ---*/ async_synchronize_full(); /* Store the name of the last unloaded module for diagnostic purposes */ strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module)); - +#if defined(CONFIG_AVM_ENHANCED) + last_unloaded_module_jiffies = jiffies; +#endif/*--- #if defined(CONFIG_AVM_ENHANCED) ---*/ free_module(mod); return 0; out: @@ -1337,6 +1355,11 @@ { struct attribute_group grp; unsigned int nsections; +#if defined(CONFIG_AVM_ENHANCED) + unsigned char *names_ptr; + unsigned int names_size; + unsigned int slab_names_size; +#endif/*--- #if defined(CONFIG_AVM_ENHANCED) ---*/ struct module_sect_attr attrs[0]; }; @@ -1348,10 +1371,24 @@ return sprintf(buf, "0x%pK\n", (void *)sattr->address); } +#if defined(CONFIG_AVM_ENHANCED) +static unsigned int global_modulesymbol_namesize; +static unsigned int global_modulesymbol_entries; +static unsigned int global_modulesymbol_slabsize; +#endif/*--- #if defined(CONFIG_AVM_ENHANCED) ---*/ + static void free_sect_attrs(struct module_sect_attrs *sect_attrs) { unsigned int section; +#if defined(CONFIG_AVM_ENHANCED) + if(sect_attrs->names_ptr) { + global_modulesymbol_namesize -= sect_attrs->names_size; + global_modulesymbol_entries -= sect_attrs->nsections; + global_modulesymbol_slabsize -= sect_attrs->slab_names_size; + free_pages_exact(sect_attrs->names_ptr, sect_attrs->names_size); + } else +#endif/*--- #if defined(CONFIG_AVM_ENHANCED) ---*/ for (section = 0; section < sect_attrs->nsections; section++) kfree(sect_attrs->attrs[section].name); kfree(sect_attrs); @@ -1363,11 +1400,25 @@ struct module_sect_attrs *sect_attrs; struct module_sect_attr *sattr; struct attribute **gattr; - +#if defined(CONFIG_AVM_ENHANCED) + unsigned int needed_size, sum_slab_names_size = 0, sum_names_size = 0, name_size; + unsigned char *names_ptr = NULL; + /* Count loaded sections and allocate structures */ + for (i = 0; i < info->hdr->e_shnum; i++) { + Elf_Shdr *sec = &info->sechdrs[i]; + if (sect_empty(sec)) + continue; + nloaded++; + name_size = strlen(info->secstrings + sec->sh_name) + 1; + sum_names_size += name_size; + sum_slab_names_size += SLAB_ORG_SIZE(name_size); + } +#else/*--- #if defined(CONFIG_AVM_ENHANCED) ---*/ /* Count loaded sections and allocate structures */ for (i = 0; i < info->hdr->e_shnum; i++) if (!sect_empty(&info->sechdrs[i])) nloaded++; +#endif/*--- #else ---*//*--- #if defined(CONFIG_AVM_ENHANCED) ---*/ size[0] = ALIGN(sizeof(*sect_attrs) + nloaded * sizeof(sect_attrs->attrs[0]), sizeof(sect_attrs->grp.attrs[0])); @@ -1379,6 +1430,21 @@ /* Setup section attributes. */ sect_attrs->grp.name = "sections"; sect_attrs->grp.attrs = (void *)sect_attrs + size[0]; +#if defined(CONFIG_AVM_ENHANCED) + needed_size = (sum_names_size + PAGE_SIZE - 1) & PAGE_MASK; + if(needed_size < sum_slab_names_size) { + names_ptr = alloc_pages_exact(needed_size, GFP_KERNEL | __GFP_ZERO); + if(names_ptr) { + sect_attrs->names_ptr = names_ptr; + sect_attrs->names_size = needed_size; + sect_attrs->slab_names_size = sum_slab_names_size; + global_modulesymbol_namesize += needed_size; + global_modulesymbol_entries += nloaded; + global_modulesymbol_slabsize += sum_slab_names_size; + /*--- printk(KERN_INFO"%s: symbols=%u size=%u(%u) saved-memory=%u byte\n", __func__, nloaded, needed_size, sum_names_size, sum_slab_names_size - needed_size); ---*/ + } + } +#endif/*--- #if defined(CONFIG_AVM_ENHANCED) ---*/ sect_attrs->nsections = 0; sattr = §_attrs->attrs[0]; @@ -1388,7 +1454,13 @@ if (sect_empty(sec)) continue; sattr->address = sec->sh_addr; - sattr->name = kstrdup(info->secstrings + sec->sh_name, +#if defined(CONFIG_AVM_ENHANCED) + if(names_ptr) { + sattr->name = names_ptr; + names_ptr += sprintf(names_ptr, "%s", info->secstrings + sec->sh_name) + 1; + } else +#endif/*--- #if defined(CONFIG_AVM_ENHANCED) ---*/ + sattr->name = kstrdup(info->secstrings + sec->sh_name, GFP_KERNEL); if (sattr->name == NULL) goto out; @@ -1855,10 +1927,13 @@ static void unset_module_init_ro_nx(struct module *mod) { } #endif +#if !defined(CONFIG_AVM_ENHANCED) || !defined(CONFIG_MIPS) +/*--- mbahr@avm.de: special case distingtion (kseg0/kseg1 vs virtual) free for mips ---*/ void __weak module_free(struct module *mod, void *module_region) { vfree(module_region); } +#endif /*--- #if !defined(CONFIG_AVM_ENHANCED) || !defined(CONFIG_MIPS) ---*/ void __weak module_arch_cleanup(struct module *mod) { @@ -1903,6 +1978,10 @@ /* Free lock-classes: */ lockdep_free_key_range(mod->module_core, mod->core_size); +#if defined(CONFIG_BUG_EXTRA_INFO) + release_bug_debug_table(mod->name); +#endif/*--- #if defined(CONFIG_BUG_EXTRA_INFO) ---*/ + /* Finally, free the core (containing the module structure) */ unset_module_core_ro_nx(mod); module_free(mod, mod->module_core); @@ -2426,14 +2505,24 @@ ddebug_remove_module(debug->modname); } +#if !defined(CONFIG_AVM_ENHANCED) || !defined(CONFIG_MIPS) void * __weak module_alloc(unsigned long size) { return vmalloc_exec(size); } +#endif/*--- #if !defined(CONFIG_AVM_ENHANCED) || !defined(CONFIG_MIPS) ---*/ -static void *module_alloc_update_bounds(unsigned long size) -{ - void *ret = module_alloc(size); +static void *module_alloc_update_bounds(unsigned long size, char *name +#if defined(CONFIG_AVM_ENHANCED) && defined(CONFIG_MIPS) + , enum _module_alloc_type_ type +#endif/*--- #if defined(CONFIG_AVM_ENHANCED) ---*/ + ) { + void *ret; + ret = module_alloc(size +#if defined(CONFIG_AVM_ENHANCED) && defined(CONFIG_MIPS) + , name , type +#endif/*--- #if defined(CONFIG_AVM_ENHANCED) ---*/ + ); if (ret) { mutex_lock(&module_mutex); @@ -2446,6 +2535,10 @@ } return ret; } +#if defined(CONFIG_AVM_ENHANCED) && defined(CONFIG_MIPS) +/*--- mbahr@avm.de: if we use KSEG0 it produce a kmemleak-warning: unknown object ???? ---*/ +#undef CONFIG_DEBUG_KMEMLEAK +#endif/*--- #if defined(CONFIG_AVM_ENHANCED) && defined(CONFIG_MIPS) ---*/ #ifdef CONFIG_DEBUG_KMEMLEAK static void kmemleak_load_module(const struct module *mod, @@ -2455,7 +2548,6 @@ /* only scan the sections containing data */ kmemleak_scan_area(mod, sizeof(struct module), GFP_KERNEL); - for (i = 1; i < info->hdr->e_shnum; i++) { /* Scan all writable sections that's not executable */ if (!(info->sechdrs[i].sh_flags & SHF_ALLOC) || @@ -2830,13 +2922,19 @@ void *ptr; /* Do the allocs. */ - ptr = module_alloc_update_bounds(mod->core_size); + ptr = module_alloc_update_bounds(mod->core_size, mod->name +#if defined(CONFIG_AVM_ENHANCED) && defined(CONFIG_MIPS) + , module_alloc_type_core +#endif/*--- #if defined(CONFIG_AVM_ENHANCED) && defined(CONFIG_MIPS) ---*/ + ); /* * The pointer to this block is stored in the module structure * which is inside the block. Just mark it as not being a * leak. */ +#ifdef CONFIG_DEBUG_KMEMLEAK kmemleak_not_leak(ptr); +#endif/*--- #ifdef CONFIG_DEBUG_KMEMLEAK ---*/ if (!ptr) return -ENOMEM; @@ -2844,14 +2942,20 @@ mod->module_core = ptr; if (mod->init_size) { - ptr = module_alloc_update_bounds(mod->init_size); + ptr = module_alloc_update_bounds(mod->init_size, mod->name +#if defined(CONFIG_AVM_ENHANCED) && defined(CONFIG_MIPS) + , module_alloc_type_init +#endif/*--- #if defined(CONFIG_AVM_ENHANCED) && defined(CONFIG_MIPS) ---*/ + ); /* * The pointer to this block is stored in the module structure * which is inside the block. This block doesn't need to be * scanned as it contains data and code that will be freed * after the module is initialized. */ +#ifdef CONFIG_DEBUG_KMEMLEAK kmemleak_ignore(ptr); +#endif/*--- #ifdef CONFIG_DEBUG_KMEMLEAK ---*/ if (!ptr) { module_free(mod, mod->module_core); return -ENOMEM; @@ -3061,8 +3165,13 @@ #endif } -/* This is where the real work happens */ -static int do_init_module(struct module *mod) +/* + * This is where the real work happens. + * + * Keep it uninlined to provide a reliable breakpoint target, e.g. for the gdb + * helper command 'lx-symbols'. + */ +static noinline int do_init_module(struct module *mod) { int ret = 0; @@ -3224,6 +3333,21 @@ mutex_unlock(&module_mutex); return err; } +#if defined(CONFIG_BUG_EXTRA_INFO) +/*--------------------------------------------------------------------------------*\ +\*--------------------------------------------------------------------------------*/ +static void __register_module_bugtable(struct module *mod, struct load_info *info) { + struct bug_debug_table_entry *bug_info; + unsigned int num_bug_info; + bug_info = section_objs(info, "__bug_debug_table", + sizeof(struct bug_debug_table_entry), &num_bug_info); + + /*--- printk(KERN_INFO"%s: %s: bug_info_start: %p num=%u\n", __func__, mod->name, bug_info, num_bug_info); ---*/ + if(num_bug_info && bug_info) { + register_bug_debug_table(mod->name, (unsigned long)bug_info, (unsigned long)&bug_info[num_bug_info]); + } +} +#endif/*--- #if defined(CONFIG_BUG_EXTRA_INFO) ---*/ /* Allocate and load the module: note that size of section 0 is always zero, and we rely on this for optional sections. */ @@ -3328,6 +3452,9 @@ if (err < 0) goto bug_cleanup; +#if defined(CONFIG_BUG_EXTRA_INFO) + __register_module_bugtable(mod, info); +#endif/*--- #if defined(CONFIG_BUG_EXTRA_INFO) ---*/ /* Get rid of temporary copy. */ free_copy(info); @@ -3482,7 +3609,6 @@ { struct module *mod; const char *ret = NULL; - preempt_disable(); list_for_each_entry_rcu(mod, &modules, list) { if (mod->state == MODULE_STATE_UNFORMED) @@ -3686,6 +3812,11 @@ static void m_stop(struct seq_file *m, void *p) { +#if defined(CONFIG_AVM_ENHANCED) + if(strcmp(current->comm, "cat") == 0) { + seq_printf(m, "sum of module-symbols: %u (%u KiB) saved-memory %u KiB\n", global_modulesymbol_entries, global_modulesymbol_namesize / 1000, (global_modulesymbol_slabsize - global_modulesymbol_namesize) / 1000); + } +#endif/*--- #if defined(CONFIG_AVM_ENHANCED) ---*/ mutex_unlock(&module_mutex); } @@ -3873,8 +4004,15 @@ printk(" %s%s", mod->name, module_flags(mod, buf)); } preempt_enable(); - if (last_unloaded_module[0]) + if (last_unloaded_module[0]) { +#if defined(CONFIG_AVM_ENHANCED) + struct timespec sincetime; + jiffies_to_timespec(jiffies - last_unloaded_module_jiffies, &sincetime); + printk(" [last unloaded: %s before %lu.%03lu s]", last_unloaded_module, sincetime.tv_sec, sincetime.tv_nsec / (1000* 1000)); +#else/*--- #if defined(CONFIG_AVM_ENHANCED) ---*/ printk(" [last unloaded: %s]", last_unloaded_module); +#endif/*--- #else ---*//*--- #if defined(CONFIG_AVM_ENHANCED) ---*/ + } printk("\n"); }