[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