kup-booke.h 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef _ASM_POWERPC_KUP_BOOKE_H_
  3. #define _ASM_POWERPC_KUP_BOOKE_H_
  4. #include <asm/bug.h>
  5. #ifdef CONFIG_PPC_KUAP
  6. #ifdef __ASSEMBLY__
  7. .macro kuap_check_amr gpr1, gpr2
  8. .endm
  9. #else
  10. #include <linux/jump_label.h>
  11. #include <linux/sched.h>
  12. #include <asm/reg.h>
  13. extern struct static_key_false disable_kuap_key;
  14. static __always_inline bool kuap_is_disabled(void)
  15. {
  16. return static_branch_unlikely(&disable_kuap_key);
  17. }
  18. static inline void __kuap_lock(void)
  19. {
  20. mtspr(SPRN_PID, 0);
  21. isync();
  22. }
  23. static inline void __kuap_save_and_lock(struct pt_regs *regs)
  24. {
  25. regs->kuap = mfspr(SPRN_PID);
  26. mtspr(SPRN_PID, 0);
  27. isync();
  28. }
  29. static inline void kuap_user_restore(struct pt_regs *regs)
  30. {
  31. if (kuap_is_disabled())
  32. return;
  33. mtspr(SPRN_PID, current->thread.pid);
  34. /* Context synchronisation is performed by rfi */
  35. }
  36. static inline void __kuap_kernel_restore(struct pt_regs *regs, unsigned long kuap)
  37. {
  38. if (regs->kuap)
  39. mtspr(SPRN_PID, current->thread.pid);
  40. /* Context synchronisation is performed by rfi */
  41. }
  42. static inline unsigned long __kuap_get_and_assert_locked(void)
  43. {
  44. unsigned long kuap = mfspr(SPRN_PID);
  45. if (IS_ENABLED(CONFIG_PPC_KUAP_DEBUG))
  46. WARN_ON_ONCE(kuap);
  47. return kuap;
  48. }
  49. static inline void __allow_user_access(void __user *to, const void __user *from,
  50. unsigned long size, unsigned long dir)
  51. {
  52. mtspr(SPRN_PID, current->thread.pid);
  53. isync();
  54. }
  55. static inline void __prevent_user_access(unsigned long dir)
  56. {
  57. mtspr(SPRN_PID, 0);
  58. isync();
  59. }
  60. static inline unsigned long __prevent_user_access_return(void)
  61. {
  62. unsigned long flags = mfspr(SPRN_PID);
  63. mtspr(SPRN_PID, 0);
  64. isync();
  65. return flags;
  66. }
  67. static inline void __restore_user_access(unsigned long flags)
  68. {
  69. if (flags) {
  70. mtspr(SPRN_PID, current->thread.pid);
  71. isync();
  72. }
  73. }
  74. static inline bool
  75. __bad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write)
  76. {
  77. return !regs->kuap;
  78. }
  79. #endif /* !__ASSEMBLY__ */
  80. #endif /* CONFIG_PPC_KUAP */
  81. #endif /* _ASM_POWERPC_KUP_BOOKE_H_ */