blob: 80b6d74146c6fe59a44743cf17d235ae000dcb2b [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>
Christophe Leroy9b307572021-11-29 18:49:40 +01006#include <asm/reg.h>
Christophe Leroy0d769142021-11-29 18:49:41 +01007#include <asm/disassemble.h>
8#include <asm/uaccess.h>
Jordan Niethe650b55b2020-05-15 12:12:55 +10009
Christophe Leroy35506a32021-03-10 17:46:44 +000010#define ___get_user_instr(gu_op, dest, ptr) \
11({ \
Christophe Leroy042e0862021-05-20 13:50:40 +000012 long __gui_ret; \
Christophe Leroy91348062021-05-20 13:50:39 +000013 u32 __user *__gui_ptr = (u32 __user *)ptr; \
Christophe Leroyc545b9f2021-11-29 18:49:38 +010014 ppc_inst_t __gui_inst; \
Christophe Leroy35506a32021-03-10 17:46:44 +000015 unsigned int __prefix, __suffix; \
Christophe Leroyb3a9e522021-05-20 13:50:38 +000016 \
17 __chk_user_ptr(ptr); \
Christophe Leroy91348062021-05-20 13:50:39 +000018 __gui_ret = gu_op(__prefix, __gui_ptr); \
Christophe Leroy35506a32021-03-10 17:46:44 +000019 if (__gui_ret == 0) { \
Christophe Leroy3261d992021-11-29 18:49:37 +010020 if (IS_ENABLED(CONFIG_PPC64) && (__prefix >> 26) == OP_PREFIX) { \
Christophe Leroy91348062021-05-20 13:50:39 +000021 __gui_ret = gu_op(__suffix, __gui_ptr + 1); \
Christophe Leroy042e0862021-05-20 13:50:40 +000022 __gui_inst = ppc_inst_prefix(__prefix, __suffix); \
Christophe Leroy35506a32021-03-10 17:46:44 +000023 } else { \
24 __gui_inst = ppc_inst(__prefix); \
25 } \
26 if (__gui_ret == 0) \
27 (dest) = __gui_inst; \
28 } \
29 __gui_ret; \
30})
Christophe Leroy35506a32021-03-10 17:46:44 +000031
Christophe Leroy042e0862021-05-20 13:50:40 +000032#define get_user_instr(x, ptr) ___get_user_instr(get_user, x, ptr)
Christophe Leroy35506a32021-03-10 17:46:44 +000033
Christophe Leroy042e0862021-05-20 13:50:40 +000034#define __get_user_instr(x, ptr) ___get_user_instr(__get_user, x, ptr)
Christophe Leroy35506a32021-03-10 17:46:44 +000035
Jordan Niethe75346252020-05-06 13:40:26 +100036/*
37 * Instruction data type for POWER
38 */
39
Christophe Leroy07b863a2021-11-29 18:49:39 +010040#if defined(CONFIG_PPC64) || defined(__CHECKER__)
Christophe Leroyc545b9f2021-11-29 18:49:38 +010041static inline u32 ppc_inst_val(ppc_inst_t x)
Jordan Niethe777e26f2020-05-06 13:40:27 +100042{
Jordan Niethe94afd062020-05-06 13:40:31 +100043 return x.val;
Jordan Niethe777e26f2020-05-06 13:40:27 +100044}
45
Christophe Leroy07b863a2021-11-29 18:49:39 +010046#define ppc_inst(x) ((ppc_inst_t){ .val = (x) })
47
48#else
Christophe Leroy07b863a2021-11-29 18:49:39 +010049static inline u32 ppc_inst_val(ppc_inst_t x)
50{
51 return x;
52}
53#define ppc_inst(x) (x)
54#endif
55
Christophe Leroyc545b9f2021-11-29 18:49:38 +010056static inline int ppc_inst_primary_opcode(ppc_inst_t x)
Jordan Niethe80948922020-05-06 13:40:28 +100057{
58 return ppc_inst_val(x) >> 26;
59}
60
Christophe Leroy077c4de2021-05-20 13:50:46 +000061#ifdef CONFIG_PPC64
Christophe Leroyc545b9f2021-11-29 18:49:38 +010062#define ppc_inst_prefix(x, y) ((ppc_inst_t){ .val = (x), .suffix = (y) })
Jordan Niethe650b55b2020-05-15 12:12:55 +100063
Christophe Leroyc545b9f2021-11-29 18:49:38 +010064static inline u32 ppc_inst_suffix(ppc_inst_t x)
Jordan Niethe650b55b2020-05-15 12:12:55 +100065{
66 return x.suffix;
67}
68
Jordan Niethe650b55b2020-05-15 12:12:55 +100069#else
Christophe Leroy3261d992021-11-29 18:49:37 +010070#define ppc_inst_prefix(x, y) ((void)y, ppc_inst(x))
Christophe Leroy64490782021-04-14 13:08:41 +000071
Christophe Leroyc545b9f2021-11-29 18:49:38 +010072static inline u32 ppc_inst_suffix(ppc_inst_t x)
Jordan Niethe650b55b2020-05-15 12:12:55 +100073{
74 return 0;
75}
76
Christophe Leroy077c4de2021-05-20 13:50:46 +000077#endif /* CONFIG_PPC64 */
Jordan Nietheaabd2232020-05-06 13:40:29 +100078
Christophe Leroyc545b9f2021-11-29 18:49:38 +010079static inline ppc_inst_t ppc_inst_read(const u32 *ptr)
Jordan Niethef8faaff2020-05-06 13:40:32 +100080{
Christophe Leroy077c4de2021-05-20 13:50:46 +000081 if (IS_ENABLED(CONFIG_PPC64) && (*ptr >> 26) == OP_PREFIX)
82 return ppc_inst_prefix(*ptr, *(ptr + 1));
83 else
84 return ppc_inst(*ptr);
Jordan Niethef8faaff2020-05-06 13:40:32 +100085}
86
Christophe Leroyc545b9f2021-11-29 18:49:38 +010087static inline bool ppc_inst_prefixed(ppc_inst_t x)
Christophe Leroy077c4de2021-05-20 13:50:46 +000088{
89 return IS_ENABLED(CONFIG_PPC64) && ppc_inst_primary_opcode(x) == OP_PREFIX;
90}
91
Christophe Leroyc545b9f2021-11-29 18:49:38 +010092static inline ppc_inst_t ppc_inst_swab(ppc_inst_t x)
Christophe Leroy077c4de2021-05-20 13:50:46 +000093{
94 return ppc_inst_prefix(swab32(ppc_inst_val(x)), swab32(ppc_inst_suffix(x)));
95}
Christophe Leroy036b5562021-05-20 13:50:41 +000096
Christophe Leroyc545b9f2021-11-29 18:49:38 +010097static inline bool ppc_inst_equal(ppc_inst_t x, ppc_inst_t y)
Jordan Niethe217862d2020-05-06 13:40:30 +100098{
Christophe Leroy036b5562021-05-20 13:50:41 +000099 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);
Jordan Niethe217862d2020-05-06 13:40:30 +1000104}
105
Christophe Leroyc545b9f2021-11-29 18:49:38 +0100106static inline int ppc_inst_len(ppc_inst_t x)
Jordan Niethe650b55b2020-05-15 12:12:55 +1000107{
108 return ppc_inst_prefixed(x) ? 8 : 4;
109}
110
Michael Ellermanc5ff46d2020-05-22 23:33:18 +1000111/*
112 * Return the address of the next instruction, if the instruction @value was
113 * located at @location.
114 */
Christophe Leroy69d4d6e2021-05-20 13:50:45 +0000115static inline u32 *ppc_inst_next(u32 *location, u32 *value)
Michael Ellermanc5ff46d2020-05-22 23:33:18 +1000116{
Christophe Leroyc545b9f2021-11-29 18:49:38 +0100117 ppc_inst_t tmp;
Michael Ellermanc5ff46d2020-05-22 23:33:18 +1000118
119 tmp = ppc_inst_read(value);
120
Christophe Leroy69d4d6e2021-05-20 13:50:45 +0000121 return (void *)location + ppc_inst_len(tmp);
Michael Ellermanc5ff46d2020-05-22 23:33:18 +1000122}
123
Christophe Leroyc545b9f2021-11-29 18:49:38 +0100124static inline unsigned long ppc_inst_as_ulong(ppc_inst_t x)
Michael Ellerman16ef9762020-05-26 17:26:30 +1000125{
Christophe Leroy693557e2021-04-20 14:02:06 +0000126 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);
Michael Ellerman16ef9762020-05-26 17:26:30 +1000132}
133
Christophe Leroy309a0a62021-12-02 13:00:27 +0100134static 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
Jordan Niethe50428fd2020-06-02 15:27:25 +1000142#define PPC_INST_STR_LEN sizeof("00000000 00000000")
143
Christophe Leroyc545b9f2021-11-29 18:49:38 +0100144static inline char *__ppc_inst_as_str(char str[PPC_INST_STR_LEN], ppc_inst_t x)
Jordan Niethe50428fd2020-06-02 15:27:25 +1000145{
146 if (ppc_inst_prefixed(x))
147 sprintf(str, "%08x %08x", ppc_inst_val(x), ppc_inst_suffix(x));
148 else
149 sprintf(str, "%08x", ppc_inst_val(x));
150
151 return str;
152}
153
154#define ppc_inst_as_str(x) \
155({ \
156 char __str[PPC_INST_STR_LEN]; \
157 __ppc_inst_as_str(__str, x); \
158 __str; \
159})
160
Christophe Leroy0d769142021-11-29 18:49:41 +0100161static inline int copy_inst_from_kernel_nofault(ppc_inst_t *inst, u32 *src)
162{
163 unsigned int val, suffix;
164
165 if (unlikely(!is_kernel_addr((unsigned long)src)))
166 return -ERANGE;
167
168/* See https://github.com/ClangBuiltLinux/linux/issues/1521 */
169#if defined(CONFIG_CC_IS_CLANG) && CONFIG_CLANG_VERSION < 140000
170 val = suffix = 0;
171#endif
172 __get_kernel_nofault(&val, src, u32, Efault);
173 if (IS_ENABLED(CONFIG_PPC64) && get_op(val) == OP_PREFIX) {
174 __get_kernel_nofault(&suffix, src + 1, u32, Efault);
175 *inst = ppc_inst_prefix(val, suffix);
176 } else {
177 *inst = ppc_inst(val);
178 }
179 return 0;
180Efault:
181 return -EFAULT;
182}
Jordan Niethe95b980a2020-05-06 13:40:34 +1000183
Jordan Niethe75346252020-05-06 13:40:26 +1000184#endif /* _ASM_POWERPC_INST_H */