extable_64.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. /*
  2. * arch/sh/mm/extable_64.c
  3. *
  4. * Copyright (C) 2003 Richard Curnow
  5. * Copyright (C) 2003, 2004 Paul Mundt
  6. *
  7. * Cloned from the 2.5 SH version..
  8. *
  9. * This file is subject to the terms and conditions of the GNU General Public
  10. * License. See the file "COPYING" in the main directory of this archive
  11. * for more details.
  12. */
  13. #include <linux/bsearch.h>
  14. #include <linux/rwsem.h>
  15. #include <linux/extable.h>
  16. #include <linux/uaccess.h>
  17. extern unsigned long copy_user_memcpy, copy_user_memcpy_end;
  18. extern void __copy_user_fixup(void);
  19. static const struct exception_table_entry __copy_user_fixup_ex = {
  20. .fixup = (unsigned long)&__copy_user_fixup,
  21. };
  22. /*
  23. * Some functions that may trap due to a bad user-mode address have too
  24. * many loads and stores in them to make it at all practical to label
  25. * each one and put them all in the main exception table.
  26. *
  27. * In particular, the fast memcpy routine is like this. It's fix-up is
  28. * just to fall back to a slow byte-at-a-time copy, which is handled the
  29. * conventional way. So it's functionally OK to just handle any trap
  30. * occurring in the fast memcpy with that fixup.
  31. */
  32. static const struct exception_table_entry *check_exception_ranges(unsigned long addr)
  33. {
  34. if ((addr >= (unsigned long)&copy_user_memcpy) &&
  35. (addr <= (unsigned long)&copy_user_memcpy_end))
  36. return &__copy_user_fixup_ex;
  37. return NULL;
  38. }
  39. static int cmp_ex_search(const void *key, const void *elt)
  40. {
  41. const struct exception_table_entry *_elt = elt;
  42. unsigned long _key = *(unsigned long *)key;
  43. /* avoid overflow */
  44. if (_key > _elt->insn)
  45. return 1;
  46. if (_key < _elt->insn)
  47. return -1;
  48. return 0;
  49. }
  50. /* Simple binary search */
  51. const struct exception_table_entry *
  52. search_extable(const struct exception_table_entry *base,
  53. const size_t num,
  54. unsigned long value)
  55. {
  56. const struct exception_table_entry *mid;
  57. mid = check_exception_ranges(value);
  58. if (mid)
  59. return mid;
  60. return bsearch(&value, base, num,
  61. sizeof(struct exception_table_entry), cmp_ex_search);
  62. }
  63. int fixup_exception(struct pt_regs *regs)
  64. {
  65. const struct exception_table_entry *fixup;
  66. fixup = search_exception_tables(regs->pc);
  67. if (fixup) {
  68. regs->pc = fixup->fixup;
  69. return 1;
  70. }
  71. return 0;
  72. }