1/* 2 * arch/s390/mm/extable.c 3 * 4 * S390 version 5 * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation 6 * Author(s): Hartmut Penner (hp@de.ibm.com) 7 * 8 * Derived from "arch/i386/mm/extable.c" 9 */ 10 11#include <linux/config.h> 12#include <linux/module.h> 13#include <linux/spinlock.h> 14#include <asm/uaccess.h> 15 16extern const struct exception_table_entry __start___ex_table[]; 17extern const struct exception_table_entry __stop___ex_table[]; 18 19static inline unsigned long 20search_one_table(const struct exception_table_entry *first, 21 const struct exception_table_entry *last, 22 unsigned long value) 23{ 24 while (first <= last) { 25 const struct exception_table_entry *mid; 26 long diff; 27 28 mid = (last - first) / 2 + first; 29 diff = mid->insn - value; 30 if (diff == 0) 31 return mid->fixup; 32 else if (diff < 0) 33 first = mid+1; 34 else 35 last = mid-1; 36 } 37 return 0; 38} 39 40extern spinlock_t modlist_lock; 41 42unsigned long 43search_exception_table(unsigned long addr) 44{ 45 unsigned long ret = 0; 46 unsigned long flags; 47 48#ifndef CONFIG_MODULES 49 /* There is only the kernel to search. */ 50 ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr); 51 return ret; 52#else 53 /* The kernel is the last "module" -- no need to treat it special. */ 54 struct module *mp; 55 56 spin_lock_irqsave(&modlist_lock, flags); 57 for (mp = module_list; mp != NULL; mp = mp->next) { 58 if (mp->ex_table_start == NULL || !(mp->flags&(MOD_RUNNING|MOD_INITIALIZING))) 59 continue; 60 ret = search_one_table(mp->ex_table_start, 61 mp->ex_table_end - 1, addr); 62 if (ret) 63 break; 64 } 65 spin_unlock_irqrestore(&modlist_lock, flags); 66 return ret; 67#endif 68} 69