linux/arch/powerpc/include/asm/nohash/32/kup-8xx.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2#ifndef _ASM_POWERPC_KUP_8XX_H_
   3#define _ASM_POWERPC_KUP_8XX_H_
   4
   5#include <asm/bug.h>
   6#include <asm/mmu.h>
   7
   8#ifdef CONFIG_PPC_KUAP
   9
  10#ifndef __ASSEMBLY__
  11
  12#include <linux/jump_label.h>
  13
  14#include <asm/reg.h>
  15
  16extern struct static_key_false disable_kuap_key;
  17
  18static __always_inline bool kuap_is_disabled(void)
  19{
  20        return static_branch_unlikely(&disable_kuap_key);
  21}
  22
  23static inline void kuap_save_and_lock(struct pt_regs *regs)
  24{
  25        if (kuap_is_disabled())
  26                return;
  27
  28        regs->kuap = mfspr(SPRN_MD_AP);
  29        mtspr(SPRN_MD_AP, MD_APG_KUAP);
  30}
  31
  32static inline void kuap_user_restore(struct pt_regs *regs)
  33{
  34}
  35
  36static inline void kuap_kernel_restore(struct pt_regs *regs, unsigned long kuap)
  37{
  38        if (kuap_is_disabled())
  39                return;
  40
  41        mtspr(SPRN_MD_AP, regs->kuap);
  42}
  43
  44static inline unsigned long kuap_get_and_assert_locked(void)
  45{
  46        unsigned long kuap;
  47
  48        if (kuap_is_disabled())
  49                return MD_APG_INIT;
  50
  51        kuap = mfspr(SPRN_MD_AP);
  52
  53        if (IS_ENABLED(CONFIG_PPC_KUAP_DEBUG))
  54                WARN_ON_ONCE(kuap >> 16 != MD_APG_KUAP >> 16);
  55
  56        return kuap;
  57}
  58
  59static inline void kuap_assert_locked(void)
  60{
  61        if (IS_ENABLED(CONFIG_PPC_KUAP_DEBUG) && !kuap_is_disabled())
  62                kuap_get_and_assert_locked();
  63}
  64
  65static inline void allow_user_access(void __user *to, const void __user *from,
  66                                     unsigned long size, unsigned long dir)
  67{
  68        if (kuap_is_disabled())
  69                return;
  70
  71        mtspr(SPRN_MD_AP, MD_APG_INIT);
  72}
  73
  74static inline void prevent_user_access(unsigned long dir)
  75{
  76        if (kuap_is_disabled())
  77                return;
  78
  79        mtspr(SPRN_MD_AP, MD_APG_KUAP);
  80}
  81
  82static inline unsigned long prevent_user_access_return(void)
  83{
  84        unsigned long flags;
  85
  86        if (kuap_is_disabled())
  87                return MD_APG_INIT;
  88
  89        flags = mfspr(SPRN_MD_AP);
  90
  91        mtspr(SPRN_MD_AP, MD_APG_KUAP);
  92
  93        return flags;
  94}
  95
  96static inline void restore_user_access(unsigned long flags)
  97{
  98        if (kuap_is_disabled())
  99                return;
 100
 101        mtspr(SPRN_MD_AP, flags);
 102}
 103
 104static inline bool
 105bad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write)
 106{
 107        if (kuap_is_disabled())
 108                return false;
 109
 110        return !((regs->kuap ^ MD_APG_KUAP) & 0xff000000);
 111}
 112
 113#endif /* !__ASSEMBLY__ */
 114
 115#endif /* CONFIG_PPC_KUAP */
 116
 117#endif /* _ASM_POWERPC_KUP_8XX_H_ */
 118