summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/lib/inst.c
diff options
context:
space:
mode:
authorJordan Niethe <jniethe5@gmail.com>2020-05-15 12:12:55 +1000
committerMichael Ellerman <mpe@ellerman.id.au>2020-05-19 00:10:39 +1000
commit650b55b707fdfa764e9f2b81314d3eb4216fb962 (patch)
tree33027daca271c94467f02d17945afc0517929171 /arch/powerpc/lib/inst.c
parent7a8818e0df5c6b53c89c7c928498668a2bbb3de0 (diff)
downloadlinux-650b55b707fdfa764e9f2b81314d3eb4216fb962.tar.bz2
powerpc: Add prefixed instructions to instruction data type
For powerpc64, redefine the ppc_inst type so both word and prefixed instructions can be represented. On powerpc32 the type will remain the same. Update places which had assumed instructions to be 4 bytes long. Signed-off-by: Jordan Niethe <jniethe5@gmail.com> Reviewed-by: Alistair Popple <alistair@popple.id.au> [mpe: Rework the get_user_inst() macros to be parameterised, and don't assign to the dest if an error occurred. Use CONFIG_PPC64 not __powerpc64__ in a few places. Address other comments from Christophe. Fix some sparse complaints.] Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/20200506034050.24806-24-jniethe5@gmail.com
Diffstat (limited to 'arch/powerpc/lib/inst.c')
-rw-r--r--arch/powerpc/lib/inst.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/arch/powerpc/lib/inst.c b/arch/powerpc/lib/inst.c
index bf3126ee399d..aedfd6e31e53 100644
--- a/arch/powerpc/lib/inst.c
+++ b/arch/powerpc/lib/inst.c
@@ -4,8 +4,47 @@
*/
#include <linux/uaccess.h>
+#include <asm/disassemble.h>
#include <asm/inst.h>
+#include <asm/ppc-opcode.h>
+#ifdef CONFIG_PPC64
+int probe_user_read_inst(struct ppc_inst *inst,
+ struct ppc_inst __user *nip)
+{
+ unsigned int val, suffix;
+ int err;
+
+ err = probe_user_read(&val, nip, sizeof(val));
+ if (err)
+ return err;
+ if (get_op(val) == OP_PREFIX) {
+ err = probe_user_read(&suffix, (void __user *)nip + 4, 4);
+ *inst = ppc_inst_prefix(val, suffix);
+ } else {
+ *inst = ppc_inst(val);
+ }
+ return err;
+}
+
+int probe_kernel_read_inst(struct ppc_inst *inst,
+ struct ppc_inst *src)
+{
+ unsigned int val, suffix;
+ int err;
+
+ err = probe_kernel_read(&val, src, sizeof(val));
+ if (err)
+ return err;
+ if (get_op(val) == OP_PREFIX) {
+ err = probe_kernel_read(&suffix, (void *)src + 4, 4);
+ *inst = ppc_inst_prefix(val, suffix);
+ } else {
+ *inst = ppc_inst(val);
+ }
+ return err;
+}
+#else /* !CONFIG_PPC64 */
int probe_user_read_inst(struct ppc_inst *inst,
struct ppc_inst __user *nip)
{
@@ -31,3 +70,4 @@ int probe_kernel_read_inst(struct ppc_inst *inst,
return err;
}
+#endif /* CONFIG_PPC64 */