Name: New Module Loader Base: Sparc64 support Author: Rusty Russell Status: Experimental Depends: Module/module-base.patch.gz D: This patch provides basic Sparc64 support for modules. diff -urNp -I \$.*\$ --exclude TAGS -X /home/rusty/current-dontdiff --minimal linux-2.5.27/include/asm-sparc64/module.h working-2.5.27-modules/include/asm-sparc64/module.h --- linux-2.5.27/include/asm-sparc64/module.h Fri Sep 14 09:33:03 2001 +++ working-2.5.27-modules/include/asm-sparc64/module.h Tue Jul 23 15:04:44 2002 @@ -1,12 +1,14 @@ #ifndef _ASM_SPARC64_MODULE_H #define _ASM_SPARC64_MODULE_H -/* - * This file contains the sparc64 architecture specific module code. - */ +/* Sparc64 is simple */ +struct mod_arch_specific +{ +}; -extern void * module_map (unsigned long size); -extern void module_unmap (void *addr); -#define module_arch_init(x) (0) -#define arch_init_modules(x) do { } while (0) +#define Elf_Shdr Elf64_Shdr +#define Elf_Sym Elf64_Sym +#define Elf_Ehdr Elf64_Ehdr +/* Used by ioctl32 as well */ +void *module_map(unsigned long size); #endif /* _ASM_SPARC64_MODULE_H */ diff -urNp -I \$.*\$ --exclude TAGS -X /home/rusty/current-dontdiff --minimal linux-2.5.27/arch/sparc64/kernel/module.c working-2.5.27-modules/arch/sparc64/kernel/module.c --- linux-2.5.27/arch/sparc64/kernel/module.c Thu Jan 1 10:00:00 1970 +++ working-2.5.27-modules/arch/sparc64/kernel/module.c Wed Jul 24 15:52:42 2002 @@ -0,0 +1,226 @@ +/* Kernel module help for Sparc 64. + Copyright (C) 2001 Rusty Russell. + + Sparc64 module region code stolen from old arch/sparc64/mm/modutil.c, + Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + Based upon code written by Linus Torvalds and others. + + 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 +#include +#include +#include +#include +#include +#include + +#include +#include + +#define MODULES_VADDR 0x0000000001000000ULL /* Where to map modules */ +#define MODULES_LEN 0x000000007f000000ULL +#define MODULES_END 0x0000000080000000ULL + +static struct vm_struct * modvmlist = NULL; + +void module_free(struct module *mod, void *module_region) +{ + struct vm_struct **p, *tmp; + + /* FIXME: If module_region == mod->init_region, trim exception + table entries. */ + if (!module_region) + return; + if ((PAGE_SIZE-1) & (unsigned long)module_region) { + printk("Trying to free module with bad address (%p)\n", + module_region); + return; + } + for (p = &modvmlist ; (tmp = *p) ; p = &tmp->next) { + if (tmp->addr == module_region) { + *p = tmp->next; + vmfree_area_pages(VMALLOC_VMADDR(tmp->addr), tmp->size); + kfree(tmp); + return; + } + } + printk("Trying to free nonexistent module vm area of %s (%p)\n", + mod->name, module_region); +} + +/* Special module allocator: since sparc64 uses the "medlow" arg to + GCC, functions are assumed to be in the low 32 bits of memory. + Hence we need to allocate space for modules within the bottom 4GB, + even if we have more memory, otherwise we'd need trampolines ala + PPC --RR */ +void *module_map(unsigned long size) +{ + void * addr; + struct vm_struct **p, *tmp, *area; + + size = PAGE_ALIGN(size); + if (!size || size > MODULES_LEN) return NULL; + + addr = (void *) MODULES_VADDR; + for (p = &modvmlist; (tmp = *p) ; p = &tmp->next) { + if (size + (unsigned long) addr < (unsigned long) tmp->addr) + break; + addr = (void *) (tmp->size + (unsigned long) tmp->addr); + } + if ((unsigned long) addr + size >= MODULES_END) return NULL; + + area = (struct vm_struct *) kmalloc(sizeof(*area), GFP_KERNEL); + if (!area) return NULL; + area->size = size + PAGE_SIZE; + area->addr = addr; + area->next = *p; + *p = area; + + if (vmalloc_area_pages(VMALLOC_VMADDR(addr), size, GFP_KERNEL, PAGE_KERNEL)) { + module_free(addr); + return NULL; + } + return addr; +} + +static void *alloc_and_zero(unsigned long size) +{ + void *ret; + + ret = module_map(size); + if (!ret) ret = ERR_PTR(-ENOMEM); + else memset(ret, 0, size); + + return ret; +} + +void *module_core_alloc(const Elf64_Ehdr *hdr, + const Elf64_Shdr *sechdrs, + const char *secstrings, + struct module *module) +{ + return alloc_and_zero(module->core_size); +} + +void *module_init_alloc(const Elf64_Ehdr *hdr, + const Elf64_Shdr *sechdrs, + const char *secstrings, + struct module *module) +{ + return alloc_and_zero(module->init_size); +} + +int apply_relocate(Elf64_Shdr *sechdrs, + const char *strtab, + unsigned int symindex, + unsigned int relsec, + struct module *module) +{ + printk(KERN_ERR "%s: Non-ADD RELOCATION unsupported\n", + module->name); + return -ENOEXEC; +} + +int apply_relocate_add(Elf64_Shdr *sechdrs, + const char *strtab, + unsigned int symindex, + unsigned int relsec, + struct module *me) +{ + unsigned int i; + Elf64_Rela *rela = (void *)sechdrs[relsec].sh_offset; + Elf64_Sym *sym; + uint64_t *location; + uint64_t value; + + printk("Applying ADD relocate section %u to %u\n", relsec, + sechdrs[relsec].sh_info); + + for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) { + /* This is where to make the change */ + location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_offset + + rela[i].r_offset; + /* This is the symbol it is referring to */ + sym = (Elf64_Sym *)sechdrs[symindex].sh_offset + + ELF64_R_SYM(rela[i].r_info); + if (!sym->st_value) { + printk("%s: Unknown symbol %s\n", + me->name, strtab + sym->st_name); + return -ENOENT; + } + /* `Everything is relative'. */ + value = sym->st_value + rela[i].r_addend; + + switch (ELF64_R_TYPE(rela[i].r_info)) { + case R_SPARC_32: + ((unsigned char *) location)[0] = value >> 24; + ((unsigned char *) location)[1] = value >> 16; + ((unsigned char *) location)[2] = value >> 8; + ((unsigned char *) location)[3] = value; + break; + + case R_SPARC_WDISP30: + *((unsigned int *)location) + = (*((unsigned int *)location) & ~0x3fffffff) + | (((value - (uint64_t)location)>>2 + & 0x3fffffff)); + break; + + case R_SPARC_WDISP22: + *((unsigned int *)location) + = (*((unsigned int *)location) & ~0x3fffff) + | (((value - (uint64_t)location)>>2 + & 0x3fffff)); + break; + + case R_SPARC_HI22: + *((unsigned int *)location) + = (*((unsigned int *)location) & ~0x3fffff) + | (value >> 10); + break; + + case R_SPARC_LO10: + *((unsigned int *)location) + = (*((unsigned int *)location) & ~0x3ff) + | (value & 0x3ff); + break; + + case R_SPARC_64: + ((unsigned char *) location) [0] = value >> 56; + ((unsigned char *) location) [1] = value >> 48; + ((unsigned char *) location) [2] = value >> 40; + ((unsigned char *) location) [3] = value >> 32; + ((unsigned char *) location) [4] = value >> 24; + ((unsigned char *) location) [5] = value >> 16; + ((unsigned char *) location) [6] = value >> 8; + ((unsigned char *) location) [7] = value; + break; + + default: + printk("Unknown ADD relocation: %lu\n", + (unsigned long)ELF64_R_TYPE(rela[i].r_info)); + return -ENOEXEC; + } + } + return 0; +} + +int module_finalize(const Elf_Ehdr *hdr, + const Elf_Shdr *sechdrs, + struct module *me) +{ + return 0; +} diff -urNp -I \$.*\$ --exclude TAGS -X /home/rusty/current-dontdiff --minimal linux-2.5.27/arch/sparc64/kernel/sys_sparc32.c working-2.5.27-modules/arch/sparc64/kernel/sys_sparc32.c --- linux-2.5.27/arch/sparc64/kernel/sys_sparc32.c Mon Jun 17 23:19:16 2002 +++ working-2.5.27-modules/arch/sparc64/kernel/sys_sparc32.c Tue Jul 23 15:04:43 2002 @@ -2978,418 +2978,41 @@ out: #ifdef CONFIG_MODULES -extern asmlinkage unsigned long sys_create_module(const char *name_user, size_t size); - -asmlinkage unsigned long sys32_create_module(const char *name_user, __kernel_size_t32 size) -{ - return sys_create_module(name_user, (size_t)size); -} - -extern asmlinkage int sys_init_module(const char *name_user, struct module *mod_user); - -/* Hey, when you're trying to init module, take time and prepare us a nice 64bit - * module structure, even if from 32bit modutils... Why to pollute kernel... :)) - */ -asmlinkage int sys32_init_module(const char *name_user, struct module *mod_user) -{ - return sys_init_module(name_user, mod_user); -} - -extern asmlinkage int sys_delete_module(const char *name_user); - -asmlinkage int sys32_delete_module(const char *name_user) -{ - return sys_delete_module(name_user); -} - -struct module_info32 { - u32 addr; - u32 size; - u32 flags; - s32 usecount; -}; - -/* Query various bits about modules. */ - -static inline long -get_mod_name(const char *user_name, char **buf) -{ - unsigned long page; - long retval; - - if ((unsigned long)user_name >= TASK_SIZE - && !segment_eq(get_fs (), KERNEL_DS)) - return -EFAULT; - - page = __get_free_page(GFP_KERNEL); - if (!page) - return -ENOMEM; - - retval = strncpy_from_user((char *)page, user_name, PAGE_SIZE); - if (retval > 0) { - if (retval < PAGE_SIZE) { - *buf = (char *)page; - return retval; - } - retval = -ENAMETOOLONG; - } else if (!retval) - retval = -EINVAL; - - free_page(page); - return retval; -} - -static inline void -put_mod_name(char *buf) -{ - free_page((unsigned long)buf); -} - -static __inline__ struct module *find_module(const char *name) -{ - struct module *mod; - - for (mod = module_list; mod ; mod = mod->next) { - if (mod->flags & MOD_DELETED) - continue; - if (!strcmp(mod->name, name)) - break; - } - - return mod; -} - -static int -qm_modules(char *buf, size_t bufsize, __kernel_size_t32 *ret) -{ - struct module *mod; - size_t nmod, space, len; - - nmod = space = 0; - - for (mod = module_list; mod->next != NULL; mod = mod->next, ++nmod) { - len = strlen(mod->name)+1; - if (len > bufsize) - goto calc_space_needed; - if (copy_to_user(buf, mod->name, len)) - return -EFAULT; - buf += len; - bufsize -= len; - space += len; - } - - if (put_user(nmod, ret)) - return -EFAULT; - else - return 0; - -calc_space_needed: - space += len; - while ((mod = mod->next)->next != NULL) - space += strlen(mod->name)+1; - - if (put_user(space, ret)) - return -EFAULT; - else - return -ENOSPC; -} - -static int -qm_deps(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret) -{ - size_t i, space, len; - - if (mod->next == NULL) - return -EINVAL; - if (!MOD_CAN_QUERY(mod)) - return put_user(0, ret); - - space = 0; - for (i = 0; i < mod->ndeps; ++i) { - const char *dep_name = mod->deps[i].dep->name; - - len = strlen(dep_name)+1; - if (len > bufsize) - goto calc_space_needed; - if (copy_to_user(buf, dep_name, len)) - return -EFAULT; - buf += len; - bufsize -= len; - space += len; - } - - return put_user(i, ret); - -calc_space_needed: - space += len; - while (++i < mod->ndeps) - space += strlen(mod->deps[i].dep->name)+1; - - if (put_user(space, ret)) - return -EFAULT; - else - return -ENOSPC; -} - -static int -qm_refs(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret) -{ - size_t nrefs, space, len; - struct module_ref *ref; - - if (mod->next == NULL) - return -EINVAL; - if (!MOD_CAN_QUERY(mod)) - if (put_user(0, ret)) - return -EFAULT; - else - return 0; - - space = 0; - for (nrefs = 0, ref = mod->refs; ref ; ++nrefs, ref = ref->next_ref) { - const char *ref_name = ref->ref->name; - - len = strlen(ref_name)+1; - if (len > bufsize) - goto calc_space_needed; - if (copy_to_user(buf, ref_name, len)) - return -EFAULT; - buf += len; - bufsize -= len; - space += len; - } - - if (put_user(nrefs, ret)) - return -EFAULT; - else - return 0; - -calc_space_needed: - space += len; - while ((ref = ref->next_ref) != NULL) - space += strlen(ref->ref->name)+1; - - if (put_user(space, ret)) - return -EFAULT; - else - return -ENOSPC; -} - -static inline int -qm_symbols(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret) -{ - size_t i, space, len; - struct module_symbol *s; - char *strings; - unsigned *vals; - - if (!MOD_CAN_QUERY(mod)) - if (put_user(0, ret)) - return -EFAULT; - else - return 0; - - space = mod->nsyms * 2*sizeof(u32); - - i = len = 0; - s = mod->syms; - - if (space > bufsize) - goto calc_space_needed; - - if (!access_ok(VERIFY_WRITE, buf, space)) - return -EFAULT; - - bufsize -= space; - vals = (unsigned *)buf; - strings = buf+space; - - for (; i < mod->nsyms ; ++i, ++s, vals += 2) { - len = strlen(s->name)+1; - if (len > bufsize) - goto calc_space_needed; - - if (copy_to_user(strings, s->name, len) - || __put_user(s->value, vals+0) - || __put_user(space, vals+1)) - return -EFAULT; - - strings += len; - bufsize -= len; - space += len; - } - - if (put_user(i, ret)) - return -EFAULT; - else - return 0; - -calc_space_needed: - for (; i < mod->nsyms; ++i, ++s) - space += strlen(s->name)+1; - - if (put_user(space, ret)) - return -EFAULT; - else - return -ENOSPC; -} - -static inline int -qm_info(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret) -{ - int error = 0; - - if (mod->next == NULL) - return -EINVAL; - - if (sizeof(struct module_info32) <= bufsize) { - struct module_info32 info; - info.addr = (unsigned long)mod; - info.size = mod->size; - info.flags = mod->flags; - info.usecount = - ((mod_member_present(mod, can_unload) - && mod->can_unload) - ? -1 : atomic_read(&mod->uc.usecount)); - - if (copy_to_user(buf, &info, sizeof(struct module_info32))) - return -EFAULT; - } else - error = -ENOSPC; - - if (put_user(sizeof(struct module_info32), ret)) - return -EFAULT; - - return error; -} +extern asmlinkage int sys_init_module(const char *uname, + void *umod, + unsigned long len, + const char *uargs); -asmlinkage int sys32_query_module(char *name_user, int which, char *buf, __kernel_size_t32 bufsize, u32 ret) +asmlinkage int sys32_init_module(const char *uname, + void *umod, + unsigned int len, + const char *uargs) { - struct module *mod; - int err; - - lock_kernel(); - if (name_user == 0) { - /* This finds "kernel_module" which is not exported. */ - for(mod = module_list; mod->next != NULL; mod = mod->next) - ; - } else { - long namelen; - char *name; - - if ((namelen = get_mod_name(name_user, &name)) < 0) { - err = namelen; - goto out; - } - err = -ENOENT; - if (namelen == 0) { - /* This finds "kernel_module" which is not exported. */ - for(mod = module_list; mod->next != NULL; mod = mod->next) - ; - } else if ((mod = find_module(name)) == NULL) { - put_mod_name(name); - goto out; - } - put_mod_name(name); - } - - switch (which) - { - case 0: - err = 0; - break; - case QM_MODULES: - err = qm_modules(buf, bufsize, (__kernel_size_t32 *)AA(ret)); - break; - case QM_DEPS: - err = qm_deps(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret)); - break; - case QM_REFS: - err = qm_refs(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret)); - break; - case QM_SYMBOLS: - err = qm_symbols(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret)); - break; - case QM_INFO: - err = qm_info(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret)); - break; - default: - err = -EINVAL; - break; - } -out: - unlock_kernel(); - return err; + return sys_init_module(uname, umod, len, uargs); } -struct kernel_sym32 { - u32 value; - char name[60]; -}; - -extern asmlinkage int sys_get_kernel_syms(struct kernel_sym *table); +extern asmlinkage long sys_delete_module(const char *name_user, + unsigned int flags); -asmlinkage int sys32_get_kernel_syms(struct kernel_sym32 *table) +asmlinkage int sys32_delete_module(const char *name_user, unsigned int flags) { - int len, i; - struct kernel_sym *tbl; - mm_segment_t old_fs; - - len = sys_get_kernel_syms(NULL); - if (!table) return len; - tbl = kmalloc (len * sizeof (struct kernel_sym), GFP_KERNEL); - if (!tbl) return -ENOMEM; - old_fs = get_fs(); - set_fs (KERNEL_DS); - sys_get_kernel_syms(tbl); - set_fs (old_fs); - for (i = 0; i < len; i++, table++) { - if (put_user (tbl[i].value, &table->value) || - copy_to_user (table->name, tbl[i].name, 60)) - break; - } - kfree (tbl); - return i; + return sys_delete_module(name_user, flags); } #else /* CONFIG_MODULES */ -asmlinkage unsigned long -sys32_create_module(const char *name_user, size_t size) -{ - return -ENOSYS; -} - -asmlinkage int -sys32_init_module(const char *name_user, struct module *mod_user) -{ - return -ENOSYS; -} - -asmlinkage int -sys32_delete_module(const char *name_user) -{ - return -ENOSYS; -} - -asmlinkage int -sys32_query_module(const char *name_user, int which, char *buf, size_t bufsize, - size_t *ret) +asmlinkage int sys32_init_module(const char *uname, + void *umod, + unsigned int len, + const char *uargs) { - /* Let the program know about the new interface. Not that - it'll do them much good. */ - if (which == 0) - return 0; - return -ENOSYS; } -asmlinkage int -sys32_get_kernel_syms(struct kernel_sym *table) +asmlinkage int sys32_delete_module(const char *name_user, unsigned int flags) { return -ENOSYS; } - #endif /* CONFIG_MODULES */ #if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE) @@ -3898,12 +3521,6 @@ asmlinkage ssize_t32 sys32_pwrite(unsign return sys_pwrite(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo)); } -extern asmlinkage ssize_t sys_readahead(int fd, loff_t offset, size_t count); - -asmlinkage ssize_t32 sys32_readahead(int fd, u32 offhi, u32 offlo, s32 count) -{ - return sys_readahead(fd, ((loff_t)AA(offhi) << 32) | AA(offlo), count); -} extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count); diff -urNp -I \$.*\$ --exclude TAGS -X /home/rusty/current-dontdiff --minimal linux-2.5.27/arch/sparc64/kernel/systbls.S working-2.5.27-modules/arch/sparc64/kernel/systbls.S --- linux-2.5.27/arch/sparc64/kernel/systbls.S Thu May 30 10:00:49 2002 +++ working-2.5.27-modules/arch/sparc64/kernel/systbls.S Tue Jul 23 15:04:43 2002 @@ -55,7 +55,7 @@ sys_call_table32: .word sys_quotactl, sys_nis_syscall, sys32_mount, sys_ustat, sys_setxattr /*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys32_getdents .word sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr -/*180*/ .word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys32_sigpending, sys32_query_module +/*180*/ .word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys32_sigpending, sys_nis_syscall .word sys_setpgid, sys_fremovexattr, sys_tkill, sys_nis_syscall, sparc64_newuname /*190*/ .word sys32_init_module, sparc64_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall .word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys32_sigaction, sys_sgetmask @@ -63,7 +63,7 @@ sys_call_table32: .word sys32_readahead, sys32_socketcall, sys_syslog, sys_nis_syscall, sys_nis_syscall /*210*/ .word sys_nis_syscall, sys_nis_syscall, sys_waitpid, sys_swapoff, sys32_sysinfo .word sys32_ipc, sys32_sigreturn, sys_clone, sys_nis_syscall, sys32_adjtimex -/*220*/ .word sys32_sigprocmask, sys32_create_module, sys32_delete_module, sys32_get_kernel_syms, sys_getpgid +/*220*/ .word sys32_sigprocmask, sys_nis_syscall, sys32_delete_module, sys32_get_kernel_syms, sys_getpgid .word sys32_bdflush, sys32_sysfs, sys_nis_syscall, sys32_setfsuid16, sys32_setfsgid16 /*230*/ .word sys32_select, sys_time, sys_nis_syscall, sys_stime, sys_nis_syscall .word sys_nis_syscall, sys_llseek, sys_mlock, sys_munlock, sys_mlockall @@ -114,7 +114,7 @@ sys_call_table: .word sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_setxattr /*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents .word sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr -/*180*/ .word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_nis_syscall, sys_query_module +/*180*/ .word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_nis_syscall, sys_nis_syscall .word sys_setpgid, sys_fremovexattr, sys_tkill, sys_nis_syscall, sparc64_newuname /*190*/ .word sys_init_module, sparc64_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall .word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys_nis_syscall, sys_sgetmask @@ -122,7 +122,7 @@ sys_call_table: .word sys_readahead, sys_socketcall, sys_syslog, sys_nis_syscall, sys_nis_syscall /*210*/ .word sys_nis_syscall, sys_nis_syscall, sys_waitpid, sys_swapoff, sys_sysinfo .word sys_ipc, sys_nis_syscall, sys_clone, sys_nis_syscall, sys_adjtimex -/*220*/ .word sys_nis_syscall, sys_create_module, sys_delete_module, sys_get_kernel_syms, sys_getpgid +/*220*/ .word sys_nis_syscall, sys_nis_syscall, sys_delete_module, sys_get_kernel_syms, sys_getpgid .word sys_bdflush, sys_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid /*230*/ .word sys_select, sys_nis_syscall, sys_nis_syscall, sys_stime, sys_nis_syscall .word sys_nis_syscall, sys_llseek, sys_mlock, sys_munlock, sys_mlockall diff -urNp -I \$.*\$ --exclude TAGS -X /home/rusty/current-dontdiff --minimal linux-2.5.27/arch/sparc64/mm/extable.c working-2.5.27-modules/arch/sparc64/mm/extable.c --- linux-2.5.27/arch/sparc64/mm/extable.c Wed Feb 20 17:55:22 2002 +++ working-2.5.27-modules/arch/sparc64/mm/extable.c Tue Jul 23 15:04:44 2002 @@ -70,15 +70,18 @@ search_exception_table(unsigned long add __stop___ex_table-1, addr, g2); return ret; #else - /* 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, g2); + ret = search_one_table(ex->entry, + ex->entry + ex->num_entries - 1, + addr, g2); if (ret) break; }