blob: 19e18af2fac9d49586ec30bc5df1b3afb236ac8f [file] [log] [blame]
Jordan Niethe75346252020-05-06 13:40:26 +10001/* SPDX-License-Identifier: GPL-2.0-or-later */
2#ifndef _ASM_POWERPC_INST_H
3#define _ASM_POWERPC_INST_H
4
Jordan Niethe650b55b2020-05-15 12:12:55 +10005#include <asm/ppc-opcode.h>
6
Christophe Leroy35506a32021-03-10 17:46:44 +00007#ifdef CONFIG_PPC64
8
9#define ___get_user_instr(gu_op, dest, ptr) \
10({ \
11 long __gui_ret = 0; \
12 unsigned long __gui_ptr = (unsigned long)ptr; \
13 struct ppc_inst __gui_inst; \
14 unsigned int __prefix, __suffix; \
15 __gui_ret = gu_op(__prefix, (unsigned int __user *)__gui_ptr); \
16 if (__gui_ret == 0) { \
17 if ((__prefix >> 26) == OP_PREFIX) { \
18 __gui_ret = gu_op(__suffix, \
19 (unsigned int __user *)__gui_ptr + 1); \
20 __gui_inst = ppc_inst_prefix(__prefix, \
21 __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 gu_op((dest).val, (u32 __user *)(ptr))
33#endif /* CONFIG_PPC64 */
34
35#define get_user_instr(x, ptr) \
36 ___get_user_instr(get_user, x, ptr)
37
38#define __get_user_instr(x, ptr) \
39 ___get_user_instr(__get_user, x, ptr)
40
Jordan Niethe75346252020-05-06 13:40:26 +100041/*
42 * Instruction data type for POWER
43 */
44
Jordan Niethe94afd062020-05-06 13:40:31 +100045struct ppc_inst {
46 u32 val;
Jordan Niethe650b55b2020-05-15 12:12:55 +100047#ifdef CONFIG_PPC64
48 u32 suffix;
49#endif
Jordan Niethe94afd062020-05-06 13:40:31 +100050} __packed;
Jordan Niethe75346252020-05-06 13:40:26 +100051
Jordan Niethe94afd062020-05-06 13:40:31 +100052static inline u32 ppc_inst_val(struct ppc_inst x)
Jordan Niethe777e26f2020-05-06 13:40:27 +100053{
Jordan Niethe94afd062020-05-06 13:40:31 +100054 return x.val;
Jordan Niethe777e26f2020-05-06 13:40:27 +100055}
56
Jordan Niethe94afd062020-05-06 13:40:31 +100057static inline int ppc_inst_primary_opcode(struct ppc_inst x)
Jordan Niethe80948922020-05-06 13:40:28 +100058{
59 return ppc_inst_val(x) >> 26;
60}
61
Jordan Niethe650b55b2020-05-15 12:12:55 +100062#ifdef CONFIG_PPC64
63#define ppc_inst(x) ((struct ppc_inst){ .val = (x), .suffix = 0xff })
64
65#define ppc_inst_prefix(x, y) ((struct ppc_inst){ .val = (x), .suffix = (y) })
66
67static inline u32 ppc_inst_suffix(struct ppc_inst x)
68{
69 return x.suffix;
70}
71
72static inline bool ppc_inst_prefixed(struct ppc_inst x)
73{
74 return (ppc_inst_primary_opcode(x) == 1) && ppc_inst_suffix(x) != 0xff;
75}
76
77static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
78{
79 return ppc_inst_prefix(swab32(ppc_inst_val(x)),
80 swab32(ppc_inst_suffix(x)));
81}
82
83static inline struct ppc_inst ppc_inst_read(const struct ppc_inst *ptr)
84{
85 u32 val, suffix;
86
87 val = *(u32 *)ptr;
88 if ((val >> 26) == OP_PREFIX) {
89 suffix = *((u32 *)ptr + 1);
90 return ppc_inst_prefix(val, suffix);
91 } else {
92 return ppc_inst(val);
93 }
94}
95
96static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
97{
98 return *(u64 *)&x == *(u64 *)&y;
99}
100
101#else
102
103#define ppc_inst(x) ((struct ppc_inst){ .val = x })
104
105static inline bool ppc_inst_prefixed(struct ppc_inst x)
106{
107 return false;
108}
109
110static inline u32 ppc_inst_suffix(struct ppc_inst x)
111{
112 return 0;
113}
114
Jordan Niethe94afd062020-05-06 13:40:31 +1000115static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
Jordan Nietheaabd2232020-05-06 13:40:29 +1000116{
117 return ppc_inst(swab32(ppc_inst_val(x)));
118}
119
Jordan Niethef8faaff2020-05-06 13:40:32 +1000120static inline struct ppc_inst ppc_inst_read(const struct ppc_inst *ptr)
121{
122 return *ptr;
123}
124
Jordan Niethe94afd062020-05-06 13:40:31 +1000125static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
Jordan Niethe217862d2020-05-06 13:40:30 +1000126{
Jordan Niethe94afd062020-05-06 13:40:31 +1000127 return ppc_inst_val(x) == ppc_inst_val(y);
Jordan Niethe217862d2020-05-06 13:40:30 +1000128}
129
Jordan Niethe650b55b2020-05-15 12:12:55 +1000130#endif /* CONFIG_PPC64 */
131
132static inline int ppc_inst_len(struct ppc_inst x)
133{
134 return ppc_inst_prefixed(x) ? 8 : 4;
135}
136
Michael Ellermanc5ff46d2020-05-22 23:33:18 +1000137/*
138 * Return the address of the next instruction, if the instruction @value was
139 * located at @location.
140 */
141static inline struct ppc_inst *ppc_inst_next(void *location, struct ppc_inst *value)
142{
143 struct ppc_inst tmp;
144
145 tmp = ppc_inst_read(value);
146
147 return location + ppc_inst_len(tmp);
148}
149
Michael Ellerman16ef9762020-05-26 17:26:30 +1000150static inline u64 ppc_inst_as_u64(struct ppc_inst x)
151{
152#ifdef CONFIG_CPU_LITTLE_ENDIAN
153 return (u64)ppc_inst_suffix(x) << 32 | ppc_inst_val(x);
154#else
155 return (u64)ppc_inst_val(x) << 32 | ppc_inst_suffix(x);
156#endif
157}
158
Jordan Niethe50428fd2020-06-02 15:27:25 +1000159#define PPC_INST_STR_LEN sizeof("00000000 00000000")
160
161static inline char *__ppc_inst_as_str(char str[PPC_INST_STR_LEN], struct ppc_inst x)
162{
163 if (ppc_inst_prefixed(x))
164 sprintf(str, "%08x %08x", ppc_inst_val(x), ppc_inst_suffix(x));
165 else
166 sprintf(str, "%08x", ppc_inst_val(x));
167
168 return str;
169}
170
171#define ppc_inst_as_str(x) \
172({ \
173 char __str[PPC_INST_STR_LEN]; \
174 __ppc_inst_as_str(__str, x); \
175 __str; \
176})
177
Jordan Niethe7ba68b22020-05-06 13:40:33 +1000178int probe_user_read_inst(struct ppc_inst *inst,
179 struct ppc_inst __user *nip);
180
Jordan Niethe95b980a2020-05-06 13:40:34 +1000181int probe_kernel_read_inst(struct ppc_inst *inst,
182 struct ppc_inst *src);
183
Jordan Niethe75346252020-05-06 13:40:26 +1000184#endif /* _ASM_POWERPC_INST_H */