scs.h 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef _ASM_SCS_H
  3. #define _ASM_SCS_H
  4. #ifdef __ASSEMBLY__
  5. #include <asm/asm-offsets.h>
  6. #include <asm/sysreg.h>
  7. #ifdef CONFIG_SHADOW_CALL_STACK
  8. scs_sp .req x18
  9. .macro scs_load_current
  10. get_current_task scs_sp
  11. ldr scs_sp, [scs_sp, #TSK_TI_SCS_SP]
  12. .endm
  13. .macro scs_save tsk
  14. str scs_sp, [\tsk, #TSK_TI_SCS_SP]
  15. .endm
  16. #else
  17. .macro scs_load_current
  18. .endm
  19. .macro scs_save tsk
  20. .endm
  21. #endif /* CONFIG_SHADOW_CALL_STACK */
  22. #else
  23. #include <linux/scs.h>
  24. #include <asm/cpufeature.h>
  25. #ifdef CONFIG_UNWIND_PATCH_PAC_INTO_SCS
  26. static inline bool should_patch_pac_into_scs(void)
  27. {
  28. u64 reg;
  29. /*
  30. * We only enable the shadow call stack dynamically if we are running
  31. * on a system that does not implement PAC or BTI. PAC and SCS provide
  32. * roughly the same level of protection, and BTI relies on the PACIASP
  33. * instructions serving as landing pads, preventing us from patching
  34. * those instructions into something else.
  35. */
  36. reg = read_sysreg_s(SYS_ID_AA64ISAR1_EL1);
  37. if (SYS_FIELD_GET(ID_AA64ISAR1_EL1, APA, reg) |
  38. SYS_FIELD_GET(ID_AA64ISAR1_EL1, API, reg))
  39. return false;
  40. reg = read_sysreg_s(SYS_ID_AA64ISAR2_EL1);
  41. if (SYS_FIELD_GET(ID_AA64ISAR2_EL1, APA3, reg))
  42. return false;
  43. if (IS_ENABLED(CONFIG_ARM64_BTI_KERNEL)) {
  44. reg = read_sysreg_s(SYS_ID_AA64PFR1_EL1);
  45. if (reg & (0xf << ID_AA64PFR1_EL1_BT_SHIFT))
  46. return false;
  47. }
  48. return true;
  49. }
  50. static inline void dynamic_scs_init(void)
  51. {
  52. if (should_patch_pac_into_scs()) {
  53. pr_info("Enabling dynamic shadow call stack\n");
  54. static_branch_enable(&dynamic_scs_enabled);
  55. }
  56. }
  57. #else
  58. static inline void dynamic_scs_init(void) {}
  59. #endif
  60. int scs_patch(const u8 eh_frame[], int size);
  61. #endif /* __ASSEMBLY __ */
  62. #endif /* _ASM_SCS_H */