extable.h 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef _ASM_EXTABLE_H
  3. #define _ASM_EXTABLE_H
  4. /*
  5. * About the exception table:
  6. *
  7. * - insn is a 32-bit pc-relative offset from the faulting insn.
  8. * - nextinsn is a 16-bit offset off of the faulting instruction
  9. * (not off of the *next* instruction as branches are).
  10. * - errreg is the register in which to place -EFAULT.
  11. * - valreg is the final target register for the load sequence
  12. * and will be zeroed.
  13. *
  14. * Either errreg or valreg may be $31, in which case nothing happens.
  15. *
  16. * The exception fixup information "just so happens" to be arranged
  17. * as in a MEM format instruction. This lets us emit our three
  18. * values like so:
  19. *
  20. * lda valreg, nextinsn(errreg)
  21. *
  22. */
  23. struct exception_table_entry
  24. {
  25. signed int insn;
  26. union exception_fixup {
  27. unsigned unit;
  28. struct {
  29. signed int nextinsn : 16;
  30. unsigned int errreg : 5;
  31. unsigned int valreg : 5;
  32. } bits;
  33. } fixup;
  34. };
  35. /* Returns the new pc */
  36. #define fixup_exception(map_reg, _fixup, pc) \
  37. ({ \
  38. if ((_fixup)->fixup.bits.valreg != 31) \
  39. map_reg((_fixup)->fixup.bits.valreg) = 0; \
  40. if ((_fixup)->fixup.bits.errreg != 31) \
  41. map_reg((_fixup)->fixup.bits.errreg) = -EFAULT; \
  42. (pc) + (_fixup)->fixup.bits.nextinsn; \
  43. })
  44. #define ARCH_HAS_RELATIVE_EXTABLE
  45. #define swap_ex_entry_fixup(a, b, tmp, delta) \
  46. do { \
  47. (a)->fixup.unit = (b)->fixup.unit; \
  48. (b)->fixup.unit = (tmp).fixup.unit; \
  49. } while (0)
  50. #endif