~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/powerpc/include/asm/inst.h

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* SPDX-License-Identifier: GPL-2.0-or-later */
  2 #ifndef _ASM_POWERPC_INST_H
  3 #define _ASM_POWERPC_INST_H
  4 
  5 #include <asm/ppc-opcode.h>
  6 #include <asm/reg.h>
  7 #include <asm/disassemble.h>
  8 #include <asm/uaccess.h>
  9 
 10 #define ___get_user_instr(gu_op, dest, ptr)                             \
 11 ({                                                                      \
 12         long __gui_ret;                                                 \
 13         u32 __user *__gui_ptr = (u32 __user *)ptr;                      \
 14         ppc_inst_t __gui_inst;                                          \
 15         unsigned int __prefix, __suffix;                                \
 16                                                                         \
 17         __chk_user_ptr(ptr);                                            \
 18         __gui_ret = gu_op(__prefix, __gui_ptr);                         \
 19         if (__gui_ret == 0) {                                           \
 20                 if (IS_ENABLED(CONFIG_PPC64) && (__prefix >> 26) == OP_PREFIX) { \
 21                         __gui_ret = gu_op(__suffix, __gui_ptr + 1);     \
 22                         __gui_inst = ppc_inst_prefix(__prefix, __suffix); \
 23                 } else {                                                \
 24                         __gui_inst = ppc_inst(__prefix);                \
 25                 }                                                       \
 26                 if (__gui_ret == 0)                                     \
 27                         (dest) = __gui_inst;                            \
 28         }                                                               \
 29         __gui_ret;                                                      \
 30 })
 31 
 32 #define get_user_instr(x, ptr) ___get_user_instr(get_user, x, ptr)
 33 
 34 #define __get_user_instr(x, ptr) ___get_user_instr(__get_user, x, ptr)
 35 
 36 /*
 37  * Instruction data type for POWER
 38  */
 39 
 40 #if defined(CONFIG_PPC64) || defined(__CHECKER__)
 41 static inline u32 ppc_inst_val(ppc_inst_t x)
 42 {
 43         return x.val;
 44 }
 45 
 46 #define ppc_inst(x) ((ppc_inst_t){ .val = (x) })
 47 
 48 #else
 49 static inline u32 ppc_inst_val(ppc_inst_t x)
 50 {
 51         return x;
 52 }
 53 #define ppc_inst(x) (x)
 54 #endif
 55 
 56 static inline int ppc_inst_primary_opcode(ppc_inst_t x)
 57 {
 58         return ppc_inst_val(x) >> 26;
 59 }
 60 
 61 #ifdef CONFIG_PPC64
 62 #define ppc_inst_prefix(x, y) ((ppc_inst_t){ .val = (x), .suffix = (y) })
 63 
 64 static inline u32 ppc_inst_suffix(ppc_inst_t x)
 65 {
 66         return x.suffix;
 67 }
 68 
 69 #else
 70 #define ppc_inst_prefix(x, y) ((void)y, ppc_inst(x))
 71 
 72 static inline u32 ppc_inst_suffix(ppc_inst_t x)
 73 {
 74         return 0;
 75 }
 76 
 77 #endif /* CONFIG_PPC64 */
 78 
 79 static inline ppc_inst_t ppc_inst_read(const u32 *ptr)
 80 {
 81         if (IS_ENABLED(CONFIG_PPC64) && (*ptr >> 26) == OP_PREFIX)
 82                 return ppc_inst_prefix(*ptr, *(ptr + 1));
 83         else
 84                 return ppc_inst(*ptr);
 85 }
 86 
 87 static inline bool ppc_inst_prefixed(ppc_inst_t x)
 88 {
 89         return IS_ENABLED(CONFIG_PPC64) && ppc_inst_primary_opcode(x) == OP_PREFIX;
 90 }
 91 
 92 static inline ppc_inst_t ppc_inst_swab(ppc_inst_t x)
 93 {
 94         return ppc_inst_prefix(swab32(ppc_inst_val(x)), swab32(ppc_inst_suffix(x)));
 95 }
 96 
 97 static inline bool ppc_inst_equal(ppc_inst_t x, ppc_inst_t y)
 98 {
 99         if (ppc_inst_val(x) != ppc_inst_val(y))
100                 return false;
101         if (!ppc_inst_prefixed(x))
102                 return true;
103         return ppc_inst_suffix(x) == ppc_inst_suffix(y);
104 }
105 
106 static inline int ppc_inst_len(ppc_inst_t x)
107 {
108         return ppc_inst_prefixed(x) ? 8 : 4;
109 }
110 
111 /*
112  * Return the address of the next instruction, if the instruction @value was
113  * located at @location.
114  */
115 static inline u32 *ppc_inst_next(u32 *location, u32 *value)
116 {
117         ppc_inst_t tmp;
118 
119         tmp = ppc_inst_read(value);
120 
121         return (void *)location + ppc_inst_len(tmp);
122 }
123 
124 static inline unsigned long ppc_inst_as_ulong(ppc_inst_t x)
125 {
126         if (IS_ENABLED(CONFIG_PPC32))
127                 return ppc_inst_val(x);
128         else if (IS_ENABLED(CONFIG_CPU_LITTLE_ENDIAN))
129                 return (u64)ppc_inst_suffix(x) << 32 | ppc_inst_val(x);
130         else
131                 return (u64)ppc_inst_val(x) << 32 | ppc_inst_suffix(x);
132 }
133 
134 static inline void ppc_inst_write(u32 *ptr, ppc_inst_t x)
135 {
136         if (!ppc_inst_prefixed(x))
137                 *ptr = ppc_inst_val(x);
138         else
139                 *(u64 *)ptr = ppc_inst_as_ulong(x);
140 }
141 
142 static inline int __copy_inst_from_kernel_nofault(ppc_inst_t *inst, u32 *src)
143 {
144         unsigned int val, suffix;
145 
146 /* See https://github.com/ClangBuiltLinux/linux/issues/1521 */
147 #if defined(CONFIG_CC_IS_CLANG) && CONFIG_CLANG_VERSION < 140000
148         val = suffix = 0;
149 #endif
150         __get_kernel_nofault(&val, src, u32, Efault);
151         if (IS_ENABLED(CONFIG_PPC64) && get_op(val) == OP_PREFIX) {
152                 __get_kernel_nofault(&suffix, src + 1, u32, Efault);
153                 *inst = ppc_inst_prefix(val, suffix);
154         } else {
155                 *inst = ppc_inst(val);
156         }
157         return 0;
158 Efault:
159         return -EFAULT;
160 }
161 
162 static inline int copy_inst_from_kernel_nofault(ppc_inst_t *inst, u32 *src)
163 {
164         if (unlikely(!is_kernel_addr((unsigned long)src)))
165                 return -ERANGE;
166 
167         return __copy_inst_from_kernel_nofault(inst, src);
168 }
169 
170 #endif /* _ASM_POWERPC_INST_H */
171 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php