Re: [PATCH v8 23/30] powerpc: Add prefixed instructions to instruction data type
From: Jordan Niethe <hidden>
Date: 2020-05-15 07:54:06
Subsystem:
linux for powerpc (32-bit and 64-bit), the rest · Maintainers:
Madhavan Srinivasan, Michael Ellerman, Linus Torvalds
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(conststruct 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.hb/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(structoptimized_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 trampolinediff --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