extable.h 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef __S390_EXTABLE_H
  3. #define __S390_EXTABLE_H
  4. #include <asm/ptrace.h>
  5. #include <linux/compiler.h>
  6. /*
  7. * The exception table consists of three addresses:
  8. *
  9. * - Address of an instruction that is allowed to fault.
  10. * - Address at which the program should continue.
  11. * - Optional address of handler that takes pt_regs * argument and runs in
  12. * interrupt context.
  13. *
  14. * No registers are modified, so it is entirely up to the continuation code
  15. * to figure out what to do.
  16. *
  17. * All the routines below use bits of fixup code that are out of line
  18. * with the main instruction path. This means when everything is well,
  19. * we don't even have to jump over them. Further, they do not intrude
  20. * on our cache or tlb entries.
  21. */
  22. struct exception_table_entry
  23. {
  24. int insn, fixup;
  25. long handler;
  26. };
  27. extern struct exception_table_entry *__start_dma_ex_table;
  28. extern struct exception_table_entry *__stop_dma_ex_table;
  29. const struct exception_table_entry *s390_search_extables(unsigned long addr);
  30. static inline unsigned long extable_fixup(const struct exception_table_entry *x)
  31. {
  32. return (unsigned long)&x->fixup + x->fixup;
  33. }
  34. typedef bool (*ex_handler_t)(const struct exception_table_entry *,
  35. struct pt_regs *);
  36. static inline ex_handler_t
  37. ex_fixup_handler(const struct exception_table_entry *x)
  38. {
  39. if (likely(!x->handler))
  40. return NULL;
  41. return (ex_handler_t)((unsigned long)&x->handler + x->handler);
  42. }
  43. static inline bool ex_handle(const struct exception_table_entry *x,
  44. struct pt_regs *regs)
  45. {
  46. ex_handler_t handler = ex_fixup_handler(x);
  47. if (unlikely(handler))
  48. return handler(x, regs);
  49. regs->psw.addr = extable_fixup(x);
  50. return true;
  51. }
  52. #define ARCH_HAS_RELATIVE_EXTABLE
  53. static inline void swap_ex_entry_fixup(struct exception_table_entry *a,
  54. struct exception_table_entry *b,
  55. struct exception_table_entry tmp,
  56. int delta)
  57. {
  58. a->fixup = b->fixup + delta;
  59. b->fixup = tmp.fixup - delta;
  60. a->handler = b->handler + delta;
  61. b->handler = tmp.handler - delta;
  62. }
  63. #endif