jump_label.h 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef _ASM_ARC_JUMP_LABEL_H
  3. #define _ASM_ARC_JUMP_LABEL_H
  4. #ifndef __ASSEMBLY__
  5. #include <linux/stringify.h>
  6. #include <linux/types.h>
  7. #define JUMP_LABEL_NOP_SIZE 4
  8. /*
  9. * NOTE about '.balign 4':
  10. *
  11. * To make atomic update of patched instruction available we need to guarantee
  12. * that this instruction doesn't cross L1 cache line boundary.
  13. *
  14. * As of today we simply align instruction which can be patched by 4 byte using
  15. * ".balign 4" directive. In that case patched instruction is aligned with one
  16. * 16-bit NOP_S if this is required.
  17. * However 'align by 4' directive is much stricter than it actually required.
  18. * It's enough that our 32-bit instruction don't cross L1 cache line boundary /
  19. * L1 I$ fetch block boundary which can be achieved by using
  20. * ".bundle_align_mode" assembler directive. That will save us from adding
  21. * useless NOP_S padding in most of the cases.
  22. *
  23. * TODO: switch to ".bundle_align_mode" directive using whin it will be
  24. * supported by ARC toolchain.
  25. */
  26. static __always_inline bool arch_static_branch(struct static_key *key,
  27. bool branch)
  28. {
  29. asm_volatile_goto(".balign "__stringify(JUMP_LABEL_NOP_SIZE)" \n"
  30. "1: \n"
  31. "nop \n"
  32. ".pushsection __jump_table, \"aw\" \n"
  33. ".word 1b, %l[l_yes], %c0 \n"
  34. ".popsection \n"
  35. : : "i" (&((char *)key)[branch]) : : l_yes);
  36. return false;
  37. l_yes:
  38. return true;
  39. }
  40. static __always_inline bool arch_static_branch_jump(struct static_key *key,
  41. bool branch)
  42. {
  43. asm_volatile_goto(".balign "__stringify(JUMP_LABEL_NOP_SIZE)" \n"
  44. "1: \n"
  45. "b %l[l_yes] \n"
  46. ".pushsection __jump_table, \"aw\" \n"
  47. ".word 1b, %l[l_yes], %c0 \n"
  48. ".popsection \n"
  49. : : "i" (&((char *)key)[branch]) : : l_yes);
  50. return false;
  51. l_yes:
  52. return true;
  53. }
  54. typedef u32 jump_label_t;
  55. struct jump_entry {
  56. jump_label_t code;
  57. jump_label_t target;
  58. jump_label_t key;
  59. };
  60. #endif /* __ASSEMBLY__ */
  61. #endif