powerpc/inst: Reduce casts in get_user_instr()
[linux-2.6-block.git] / arch / powerpc / include / asm / inst.h
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 = 0;                                             \
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,          \
22                                                      __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 #else /* !CONFIG_PPC64 */
32 #define ___get_user_instr(gu_op, dest, ptr)                             \
33 ({                                                                      \
34         __chk_user_ptr(ptr);                                            \
35         gu_op((dest).val, (u32 __user *)(ptr));                         \
36 })
37 #endif /* CONFIG_PPC64 */
38
39 #define get_user_instr(x, ptr) \
40         ___get_user_instr(get_user, x, ptr)
41
42 #define __get_user_instr(x, ptr) \
43         ___get_user_instr(__get_user, x, ptr)
44
45 /*
46  * Instruction data type for POWER
47  */
48
49 struct ppc_inst {
50         u32 val;
51 #ifdef CONFIG_PPC64
52         u32 suffix;
53 #endif
54 } __packed;
55
56 static inline u32 ppc_inst_val(struct ppc_inst x)
57 {
58         return x.val;
59 }
60
61 static inline int ppc_inst_primary_opcode(struct ppc_inst x)
62 {
63         return ppc_inst_val(x) >> 26;
64 }
65
66 #ifdef CONFIG_PPC64
67 #define ppc_inst(x) ((struct ppc_inst){ .val = (x), .suffix = 0xff })
68
69 #define ppc_inst_prefix(x, y) ((struct ppc_inst){ .val = (x), .suffix = (y) })
70
71 static inline u32 ppc_inst_suffix(struct ppc_inst x)
72 {
73         return x.suffix;
74 }
75
76 static inline bool ppc_inst_prefixed(struct ppc_inst x)
77 {
78         return (ppc_inst_primary_opcode(x) == 1) && ppc_inst_suffix(x) != 0xff;
79 }
80
81 static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
82 {
83         return ppc_inst_prefix(swab32(ppc_inst_val(x)),
84                                swab32(ppc_inst_suffix(x)));
85 }
86
87 static inline struct ppc_inst ppc_inst_read(const struct ppc_inst *ptr)
88 {
89         u32 val, suffix;
90
91         val = *(u32 *)ptr;
92         if ((val >> 26) == OP_PREFIX) {
93                 suffix = *((u32 *)ptr + 1);
94                 return ppc_inst_prefix(val, suffix);
95         } else {
96                 return ppc_inst(val);
97         }
98 }
99
100 static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
101 {
102         return *(u64 *)&x == *(u64 *)&y;
103 }
104
105 #else
106
107 #define ppc_inst(x) ((struct ppc_inst){ .val = x })
108
109 #define ppc_inst_prefix(x, y) ppc_inst(x)
110
111 static inline bool ppc_inst_prefixed(struct ppc_inst x)
112 {
113         return false;
114 }
115
116 static inline u32 ppc_inst_suffix(struct ppc_inst x)
117 {
118         return 0;
119 }
120
121 static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
122 {
123         return ppc_inst(swab32(ppc_inst_val(x)));
124 }
125
126 static inline struct ppc_inst ppc_inst_read(const struct ppc_inst *ptr)
127 {
128         return *ptr;
129 }
130
131 static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
132 {
133         return ppc_inst_val(x) == ppc_inst_val(y);
134 }
135
136 #endif /* CONFIG_PPC64 */
137
138 static inline int ppc_inst_len(struct ppc_inst x)
139 {
140         return ppc_inst_prefixed(x) ? 8 : 4;
141 }
142
143 /*
144  * Return the address of the next instruction, if the instruction @value was
145  * located at @location.
146  */
147 static inline struct ppc_inst *ppc_inst_next(void *location, struct ppc_inst *value)
148 {
149         struct ppc_inst tmp;
150
151         tmp = ppc_inst_read(value);
152
153         return location + ppc_inst_len(tmp);
154 }
155
156 static inline unsigned long ppc_inst_as_ulong(struct ppc_inst x)
157 {
158         if (IS_ENABLED(CONFIG_PPC32))
159                 return ppc_inst_val(x);
160         else if (IS_ENABLED(CONFIG_CPU_LITTLE_ENDIAN))
161                 return (u64)ppc_inst_suffix(x) << 32 | ppc_inst_val(x);
162         else
163                 return (u64)ppc_inst_val(x) << 32 | ppc_inst_suffix(x);
164 }
165
166 #define PPC_INST_STR_LEN sizeof("00000000 00000000")
167
168 static inline char *__ppc_inst_as_str(char str[PPC_INST_STR_LEN], struct ppc_inst x)
169 {
170         if (ppc_inst_prefixed(x))
171                 sprintf(str, "%08x %08x", ppc_inst_val(x), ppc_inst_suffix(x));
172         else
173                 sprintf(str, "%08x", ppc_inst_val(x));
174
175         return str;
176 }
177
178 #define ppc_inst_as_str(x)              \
179 ({                                      \
180         char __str[PPC_INST_STR_LEN];   \
181         __ppc_inst_as_str(__str, x);    \
182         __str;                          \
183 })
184
185 int copy_inst_from_kernel_nofault(struct ppc_inst *inst, struct ppc_inst *src);
186
187 #endif /* _ASM_POWERPC_INST_H */