static_call.c 949 B

12345678910111213141516171819202122232425262728293031323334353637
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/memory.h>
  3. #include <linux/static_call.h>
  4. #include <asm/code-patching.h>
  5. void arch_static_call_transform(void *site, void *tramp, void *func, bool tail)
  6. {
  7. int err;
  8. bool is_ret0 = (func == __static_call_return0);
  9. unsigned long target = (unsigned long)(is_ret0 ? tramp + PPC_SCT_RET0 : func);
  10. bool is_short = is_offset_in_branch_range((long)target - (long)tramp);
  11. if (!tramp)
  12. return;
  13. mutex_lock(&text_mutex);
  14. if (func && !is_short) {
  15. err = patch_instruction(tramp + PPC_SCT_DATA, ppc_inst(target));
  16. if (err)
  17. goto out;
  18. }
  19. if (!func)
  20. err = patch_instruction(tramp, ppc_inst(PPC_RAW_BLR()));
  21. else if (is_short)
  22. err = patch_branch(tramp, target, 0);
  23. else
  24. err = patch_instruction(tramp, ppc_inst(PPC_RAW_NOP()));
  25. out:
  26. mutex_unlock(&text_mutex);
  27. if (err)
  28. panic("%s: patching failed %pS at %pS\n", __func__, func, tramp);
  29. }
  30. EXPORT_SYMBOL_GPL(arch_static_call_transform);