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 7 #ifdef CONFIG_PPC64 8 9 #define ___get_user_instr(gu_op, dest, ptr) \ 10 ({ \ 11 long __gui_ret; \ 12 u32 __user *__gui_ptr = (u32 __user *)ptr; \ 13 struct ppc_inst __gui_inst; \ 14 unsigned int __prefix, __suffix; \ 15 \ 16 __chk_user_ptr(ptr); \ 17 __gui_ret = gu_op(__prefix, __gui_ptr); \ 18 if (__gui_ret == 0) { \ 19 if ((__prefix >> 26) == OP_PREFIX) { \ 20 __gui_ret = gu_op(__suffix, __gui_ptr + 1); \ 21 __gui_inst = ppc_inst_prefix(__prefix, __suffix); \ 22 } else { \ 23 __gui_inst = ppc_inst(__prefix); \ 24 } \ 25 if (__gui_ret == 0) \ 26 (dest) = __gui_inst; \ 27 } \ 28 __gui_ret; \ 29 }) 30 #else /* !CONFIG_PPC64 */ 31 #define ___get_user_instr(gu_op, dest, ptr) \ 32 ({ \ 33 __chk_user_ptr(ptr); \ 34 gu_op((dest).val, (u32 __user *)(ptr)); \ 35 }) 36 #endif /* CONFIG_PPC64 */ 37 38 #define get_user_instr(x, ptr) ___get_user_instr(get_user, x, ptr) 39 40 #define __get_user_instr(x, ptr) ___get_user_instr(__get_user, x, ptr) 41 42 /* 43 * Instruction data type for POWER 44 */ 45 46 struct ppc_inst { 47 u32 val; 48 #ifdef CONFIG_PPC64 49 u32 suffix; 50 #endif 51 } __packed; 52 53 static inline u32 ppc_inst_val(struct ppc_inst x) 54 { 55 return x.val; 56 } 57 58 static inline int ppc_inst_primary_opcode(struct ppc_inst x) 59 { 60 return ppc_inst_val(x) >> 26; 61 } 62 63 #define ppc_inst(x) ((struct ppc_inst){ .val = (x) }) 64 65 #ifdef CONFIG_PPC64 66 #define ppc_inst_prefix(x, y) ((struct ppc_inst){ .val = (x), .suffix = (y) }) 67 68 static inline u32 ppc_inst_suffix(struct ppc_inst x) 69 { 70 return x.suffix; 71 } 72 73 #else 74 #define ppc_inst_prefix(x, y) ppc_inst(x) 75 76 static inline u32 ppc_inst_suffix(struct ppc_inst x) 77 { 78 return 0; 79 } 80 81 #endif /* CONFIG_PPC64 */ 82 83 static inline struct ppc_inst ppc_inst_read(const u32 *ptr) 84 { 85 if (IS_ENABLED(CONFIG_PPC64) && (*ptr >> 26) == OP_PREFIX) 86 return ppc_inst_prefix(*ptr, *(ptr + 1)); 87 else 88 return ppc_inst(*ptr); 89 } 90 91 static inline bool ppc_inst_prefixed(struct ppc_inst x) 92 { 93 return IS_ENABLED(CONFIG_PPC64) && ppc_inst_primary_opcode(x) == OP_PREFIX; 94 } 95 96 static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x) 97 { 98 return ppc_inst_prefix(swab32(ppc_inst_val(x)), swab32(ppc_inst_suffix(x))); 99 } 100 101 static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y) 102 { 103 if (ppc_inst_val(x) != ppc_inst_val(y)) 104 return false; 105 if (!ppc_inst_prefixed(x)) 106 return true; 107 return ppc_inst_suffix(x) == ppc_inst_suffix(y); 108 } 109 110 static inline int ppc_inst_len(struct ppc_inst x) 111 { 112 return ppc_inst_prefixed(x) ? 8 : 4; 113 } 114 115 /* 116 * Return the address of the next instruction, if the instruction @value was 117 * located at @location. 118 */ 119 static inline u32 *ppc_inst_next(u32 *location, u32 *value) 120 { 121 struct ppc_inst tmp; 122 123 tmp = ppc_inst_read(value); 124 125 return (void *)location + ppc_inst_len(tmp); 126 } 127 128 static inline unsigned long ppc_inst_as_ulong(struct ppc_inst x) 129 { 130 if (IS_ENABLED(CONFIG_PPC32)) 131 return ppc_inst_val(x); 132 else if (IS_ENABLED(CONFIG_CPU_LITTLE_ENDIAN)) 133 return (u64)ppc_inst_suffix(x) << 32 | ppc_inst_val(x); 134 else 135 return (u64)ppc_inst_val(x) << 32 | ppc_inst_suffix(x); 136 } 137 138 #define PPC_INST_STR_LEN sizeof("00000000 00000000") 139 140 static inline char *__ppc_inst_as_str(char str[PPC_INST_STR_LEN], struct ppc_inst x) 141 { 142 if (ppc_inst_prefixed(x)) 143 sprintf(str, "%08x %08x", ppc_inst_val(x), ppc_inst_suffix(x)); 144 else 145 sprintf(str, "%08x", ppc_inst_val(x)); 146 147 return str; 148 } 149 150 #define ppc_inst_as_str(x) \ 151 ({ \ 152 char __str[PPC_INST_STR_LEN]; \ 153 __ppc_inst_as_str(__str, x); \ 154 __str; \ 155 }) 156 157 int copy_inst_from_kernel_nofault(struct ppc_inst *inst, u32 *src); 158 159 #endif /* _ASM_POWERPC_INST_H */ 160