[PATCH v8 23/30] powerpc: Add prefixed instructions to instruction data type

Jordan Niethe jniethe5 at gmail.com
Fri May 15 17:52:19 AEST 2020


Hey mpe, fixes for the issues highlighted by Christophe, except KUAP
as discussed. Will make the optprobe change as a preceding patch.

diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h
--- a/arch/powerpc/include/asm/inst.h
+++ b/arch/powerpc/include/asm/inst.h
@@ -11,9 +11,9 @@

 struct ppc_inst {
     u32 val;
-#ifdef __powerpc64__
+#ifdef CONFIG_PPC64
     u32 suffix;
-#endif /* __powerpc64__ */
+#endif /* CONFIG_PPC64 */
 } __packed;

 static inline u32 ppc_inst_val(struct ppc_inst x)
@@ -26,7 +26,7 @@ static inline int ppc_inst_primary_opcode(struct ppc_inst x)
     return get_op(ppc_inst_val(x));
 }

-#ifdef __powerpc64__
+#ifdef CONFIG_PPC64
 #define ppc_inst(x) ((struct ppc_inst){ .val = (x), .suffix = 0xff })

 #define ppc_inst_prefix(x, y) ((struct ppc_inst){ .val = (x), .suffix = (y) })
@@ -52,7 +52,7 @@ static inline struct ppc_inst ppc_inst_read(const
struct ppc_inst *ptr)
     u32 val, suffix;

     val = *(u32 *)ptr;
-    if ((val >> 26) == 1) {
+    if ((get_op(val)) == OP_PREFIX) {
         suffix = *((u32 *)ptr + 1);
         return ppc_inst_prefix(val, suffix);
     } else {
@@ -94,7 +94,7 @@ static inline bool ppc_inst_equal(struct ppc_inst x,
struct ppc_inst y)
     return ppc_inst_val(x) == ppc_inst_val(y);
 }

-#endif /* __powerpc64__ */
+#endif /* CONFIG_PPC64 */

 static inline int ppc_inst_len(struct ppc_inst x)
 {
diff --git a/arch/powerpc/include/asm/uaccess.h
b/arch/powerpc/include/asm/uaccess.h
index e9027b3c641a..ac36a82321d4 100644
--- a/arch/powerpc/include/asm/uaccess.h
+++ b/arch/powerpc/include/asm/uaccess.h
@@ -105,7 +105,7 @@ static inline int __access_ok(unsigned long addr,
unsigned long size,
 #define __put_user_inatomic(x, ptr) \
     __put_user_nosleep((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))

-#ifdef __powerpc64__
+#ifdef CONFIG_PPC64
 #define __get_user_instr(x, ptr)            \
 ({                            \
     long __gui_ret = 0;                \
@@ -113,7 +113,7 @@ static inline int __access_ok(unsigned long addr,
unsigned long size,
     struct ppc_inst __gui_inst;            \
     unsigned int prefix, suffix;            \
     __gui_ret = __get_user(prefix, (unsigned int __user *)__gui_ptr);    \
-    if (!__gui_ret && (prefix >> 26) == OP_PREFIX) {    \
+    if (!__gui_ret && (get_op(prefix)) == OP_PREFIX) {    \
         __gui_ret = __get_user(suffix,        \
                        (unsigned int __user *)__gui_ptr + 1);    \
         __gui_inst = ppc_inst_prefix(prefix, suffix);    \
@@ -131,7 +131,7 @@ static inline int __access_ok(unsigned long addr,
unsigned long size,
     struct ppc_inst __gui_inst;            \
     unsigned int prefix, suffix;            \
     __gui_ret = __get_user_inatomic(prefix, (unsigned int __user
*)__gui_ptr);    \
-    if (!__gui_ret && (prefix >> 26) == OP_PREFIX) {    \
+    if (!__gui_ret && (get_op(prefix)) == OP_PREFIX) {    \
         __gui_ret = __get_user_inatomic(suffix,    \
                         (unsigned int __user *)__gui_ptr + 1);    \
         __gui_inst = ppc_inst_prefix(prefix, suffix);    \
diff --git a/arch/powerpc/kernel/optprobes.c b/arch/powerpc/kernel/optprobes.c
index a8e66603d12b..3ac105e7faae 100644
--- a/arch/powerpc/kernel/optprobes.c
+++ b/arch/powerpc/kernel/optprobes.c
@@ -283,10 +283,8 @@ int arch_prepare_optimized_kprobe(struct
optimized_kprobe *op, struct kprobe *p)
      * 3. load instruction to be emulated into relevant register, and
      */
     temp = ppc_inst_read((struct ppc_inst *)p->ainsn.insn);
-    patch_imm64_load_insns(ppc_inst_val(temp) |
-                   ((u64)ppc_inst_suffix(temp) << 32),
-                   4,
-                   buff + TMPL_INSN_IDX);
+    patch_imm64_load_insns(ppc_inst_val(temp) |
((u64)ppc_inst_suffix(temp) << 32),
+                   4, buff + TMPL_INSN_IDX);

     /*
      * 4. branch back from trampoline
diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index 58b67b62d5d3..bfd4e1dae0fb 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -26,8 +26,6 @@ static int __patch_instruction(struct ppc_inst
*exec_addr, struct ppc_inst instr

     if (!ppc_inst_prefixed(instr)) {
         __put_user_asm(ppc_inst_val(instr), patch_addr, err, "stw");
-        if (err)
-            return err;
     } else {
 #ifdef CONFIG_CPU_LITTLE_ENDIAN
         __put_user_asm((u64)ppc_inst_suffix(instr) << 32 |
@@ -36,12 +34,13 @@ static int __patch_instruction(struct ppc_inst
*exec_addr, struct ppc_inst instr
         __put_user_asm((u64)ppc_inst_val(instr) << 32 |
                    ppc_inst_suffix(instr), patch_addr, err, "std");
 #endif /* CONFIG_CPU_LITTLE_ENDIAN */
-        if (err)
-            return err;
     }
+    if (err)
+        return err;

     asm ("dcbst 0, %0; sync; icbi 0,%1; sync; isync" :: "r" (patch_addr),
                                 "r" (exec_addr));
+
     return 0;
 }

diff --git a/arch/powerpc/lib/inst.c b/arch/powerpc/lib/inst.c
index e5e589994097..3c3851ffdb36 100644
--- a/arch/powerpc/lib/inst.c
+++ b/arch/powerpc/lib/inst.c
@@ -7,7 +7,7 @@
 #include <linux/uaccess.h>
 #include <asm/inst.h>

-#ifdef __powerpc64__
+#ifdef CONFIG_PPC64
 int probe_user_read_inst(struct ppc_inst *inst,
              struct ppc_inst *nip)
 {
@@ -17,9 +17,8 @@ int probe_user_read_inst(struct ppc_inst *inst,
     err = probe_user_read(&val, nip, sizeof(val));
     if (err)
         return err;
-    if ((val >> 26) == OP_PREFIX) {
-        err = probe_user_read(&suffix, (void *)nip + 4,
-                      sizeof(unsigned int));
+    if (get_op(val) == OP_PREFIX) {
+        err = probe_user_read(&suffix, (void *)nip + 4, 4);
         *inst = ppc_inst_prefix(val, suffix);
     } else {
         *inst = ppc_inst(val);
@@ -36,9 +35,8 @@ int probe_kernel_read_inst(struct ppc_inst *inst,
     err = probe_kernel_read(&val, src, sizeof(val));
     if (err)
         return err;
-    if ((val >> 26) == OP_PREFIX) {
-        err = probe_kernel_read(&suffix, (void *)src + 4,
-                    sizeof(unsigned int));
+    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);
@@ -67,4 +65,4 @@ int probe_kernel_read_inst(struct ppc_inst *inst,
     *inst = ppc_inst(val);
     return err;
 }
-#endif /* __powerpc64__ */
+#endif /* CONFIG_PPC64 */
-- 
2.17.1


More information about the Linuxppc-dev mailing list