* [PATCH v5 00/21] Initial Prefixed Instruction support
@ 2020-04-06 8:09 Jordan Niethe
2020-04-06 8:09 ` [PATCH v5 01/21] powerpc/xmon: Remove store_inst() for patch_instruction() Jordan Niethe
` (21 more replies)
0 siblings, 22 replies; 71+ messages in thread
From: Jordan Niethe @ 2020-04-06 8:09 UTC (permalink / raw)
To: linuxppc-dev; +Cc: alistair, npiggin, bala24, Jordan Niethe, dja
A future revision of the ISA will introduce prefixed instructions. A
prefixed instruction is composed of a 4-byte prefix followed by a
4-byte suffix.
All prefixes have the major opcode 1. A prefix will never be a valid
word instruction. A suffix may be an existing word instruction or a
new instruction.
This series enables prefixed instructions and extends the instruction
emulation to support them. Then the places where prefixed instructions
might need to be emulated are updated.
v5 is based on feedback from Nick Piggins, Michael Ellerman, Balamuruhan
Suriyakumar and Alistair Popple.
The major changes:
- The ppc instruction type is now a struct
- Series now just based on next
- ppc_inst_masked() dropped
- Space for xmon breakpoints allocated in an assembly file
- "Add prefixed instructions to instruction data type" patch seperated in
to smaller patches
- Calling convention for create_branch() is changed
- Some places which had not been updated to use the data type are now updated
v4 is based on feedback from Nick Piggins, Christophe Leroy and Daniel Axtens.
The major changes:
- Move xmon breakpoints from data section to text section
- Introduce a data type for instructions on powerpc
v3 is based on feedback from Christophe Leroy. The major changes:
- Completely replacing store_inst() with patch_instruction() in
xmon
- Improve implementation of mread_instr() to not use mread().
- Base the series on top of
https://patchwork.ozlabs.org/patch/1232619/ as this will effect
kprobes.
- Some renaming and simplification of conditionals.
v2 incorporates feedback from Daniel Axtens and and Balamuruhan
S. The major changes are:
- Squashing together all commits about SRR1 bits
- Squashing all commits for supporting prefixed load stores
- Changing abbreviated references to sufx/prfx -> suffix/prefix
- Introducing macros for returning the length of an instruction
- Removing sign extension flag from pstd/pld in sstep.c
- Dropping patch "powerpc/fault: Use analyse_instr() to check for
store with updates to sp" from the series, it did not really fit
with prefixed enablement in the first place and as reported by Greg
Kurz did not work correctly.
Alistair Popple (1):
powerpc: Enable Prefixed Instructions
Jordan Niethe (20):
powerpc/xmon: Remove store_inst() for patch_instruction()
powerpc/xmon: Move out-of-line instructions to text section
powerpc: Change calling convention for create_branch() et. al.
powerpc: Use a macro for creating instructions from u32s
powerpc: Use a function for getting the instruction op code
powerpc: Use an accessor for instructions
powerpc: Use a function for byte swapping instructions
powerpc: Introduce functions for instruction equality
powerpc: Use a datatype for instructions
powerpc: Use a function for reading instructions
powerpc: Define and use __get_user_instr{,inatomic}()
powerpc: Introduce a function for reporting instruction length
powerpc/xmon: Use a function for reading instructions
powerpc/xmon: Move insertion of breakpoint for xol'ing
powerpc: Make test_translate_branch() independent of instruction
length
powerpc: Define new SRR1 bits for a future ISA version
powerpc64: Add prefixed instructions to instruction data type
powerpc: Support prefixed instructions in alignment handler
powerpc sstep: Add support for prefixed load/stores
powerpc sstep: Add support for prefixed fixed-point arithmetic
arch/powerpc/include/asm/code-patching.h | 37 +-
arch/powerpc/include/asm/inst.h | 106 ++++++
arch/powerpc/include/asm/kprobes.h | 2 +-
arch/powerpc/include/asm/reg.h | 7 +-
arch/powerpc/include/asm/sstep.h | 15 +-
arch/powerpc/include/asm/uaccess.h | 28 ++
arch/powerpc/include/asm/uprobes.h | 7 +-
arch/powerpc/kernel/align.c | 13 +-
arch/powerpc/kernel/epapr_paravirt.c | 5 +-
arch/powerpc/kernel/hw_breakpoint.c | 5 +-
arch/powerpc/kernel/jump_label.c | 5 +-
arch/powerpc/kernel/kgdb.c | 9 +-
arch/powerpc/kernel/kprobes.c | 24 +-
arch/powerpc/kernel/mce_power.c | 5 +-
arch/powerpc/kernel/module_64.c | 3 +-
arch/powerpc/kernel/optprobes.c | 91 +++--
arch/powerpc/kernel/optprobes_head.S | 3 +
arch/powerpc/kernel/security.c | 9 +-
arch/powerpc/kernel/setup_32.c | 4 +-
arch/powerpc/kernel/trace/ftrace.c | 190 ++++++----
arch/powerpc/kernel/traps.c | 20 +-
arch/powerpc/kernel/uprobes.c | 3 +-
arch/powerpc/kernel/vecemu.c | 20 +-
arch/powerpc/kvm/book3s_hv_nested.c | 2 +-
arch/powerpc/kvm/book3s_hv_rm_mmu.c | 2 +-
arch/powerpc/kvm/emulate_loadstore.c | 2 +-
arch/powerpc/lib/code-patching.c | 289 +++++++-------
arch/powerpc/lib/feature-fixups.c | 69 ++--
arch/powerpc/lib/sstep.c | 455 ++++++++++++++++-------
arch/powerpc/lib/test_emulate_step.c | 56 +--
arch/powerpc/perf/core-book3s.c | 4 +-
arch/powerpc/xmon/Makefile | 2 +-
arch/powerpc/xmon/xmon.c | 94 +++--
arch/powerpc/xmon/xmon_bpts.S | 10 +
arch/powerpc/xmon/xmon_bpts.h | 8 +
35 files changed, 1042 insertions(+), 562 deletions(-)
create mode 100644 arch/powerpc/include/asm/inst.h
create mode 100644 arch/powerpc/xmon/xmon_bpts.S
create mode 100644 arch/powerpc/xmon/xmon_bpts.h
--
2.17.1
^ permalink raw reply [flat|nested] 71+ messages in thread
* [PATCH v5 01/21] powerpc/xmon: Remove store_inst() for patch_instruction()
2020-04-06 8:09 [PATCH v5 00/21] Initial Prefixed Instruction support Jordan Niethe
@ 2020-04-06 8:09 ` Jordan Niethe
2020-04-06 8:09 ` [PATCH v5 02/21] powerpc/xmon: Move out-of-line instructions to text section Jordan Niethe
` (20 subsequent siblings)
21 siblings, 0 replies; 71+ messages in thread
From: Jordan Niethe @ 2020-04-06 8:09 UTC (permalink / raw)
To: linuxppc-dev; +Cc: alistair, npiggin, bala24, Jordan Niethe, dja
For modifying instructions in xmon, patch_instruction() can serve the
same role that store_inst() is performing with the advantage of not
being specific to xmon. In some places patch_instruction() is already
being using followed by store_inst(). In these cases just remove the
store_inst(). Otherwise replace store_inst() with patch_instruction().
Reviewed-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v4: Read into a local variable
---
arch/powerpc/xmon/xmon.c | 18 +++++-------------
1 file changed, 5 insertions(+), 13 deletions(-)
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index e8c84d265602..02e3bd62cab4 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -325,11 +325,6 @@ static inline void sync(void)
asm volatile("sync; isync");
}
-static inline void store_inst(void *p)
-{
- asm volatile ("dcbst 0,%0; sync; icbi 0,%0; isync" : : "r" (p));
-}
-
static inline void cflush(void *p)
{
asm volatile ("dcbf 0,%0; icbi 0,%0" : : "r" (p));
@@ -881,8 +876,7 @@ static struct bpt *new_breakpoint(unsigned long a)
for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
if (!bp->enabled && atomic_read(&bp->ref_count) == 0) {
bp->address = a;
- bp->instr[1] = bpinstr;
- store_inst(&bp->instr[1]);
+ patch_instruction(&bp->instr[1], bpinstr);
return bp;
}
}
@@ -894,25 +888,26 @@ static struct bpt *new_breakpoint(unsigned long a)
static void insert_bpts(void)
{
int i;
+ unsigned int instr;
struct bpt *bp;
bp = bpts;
for (i = 0; i < NBPTS; ++i, ++bp) {
if ((bp->enabled & (BP_TRAP|BP_CIABR)) == 0)
continue;
- if (mread(bp->address, &bp->instr[0], 4) != 4) {
+ if (mread(bp->address, &instr, 4) != 4) {
printf("Couldn't read instruction at %lx, "
"disabling breakpoint there\n", bp->address);
bp->enabled = 0;
continue;
}
- if (IS_MTMSRD(bp->instr[0]) || IS_RFID(bp->instr[0])) {
+ if (IS_MTMSRD(instr) || IS_RFID(instr)) {
printf("Breakpoint at %lx is on an mtmsrd or rfid "
"instruction, disabling it\n", bp->address);
bp->enabled = 0;
continue;
}
- store_inst(&bp->instr[0]);
+ patch_instruction(bp->instr, instr);
if (bp->enabled & BP_CIABR)
continue;
if (patch_instruction((unsigned int *)bp->address,
@@ -922,7 +917,6 @@ static void insert_bpts(void)
bp->enabled &= ~BP_TRAP;
continue;
}
- store_inst((void *)bp->address);
}
}
@@ -957,8 +951,6 @@ static void remove_bpts(void)
(unsigned int *)bp->address, bp->instr[0]) != 0)
printf("Couldn't remove breakpoint at %lx\n",
bp->address);
- else
- store_inst((void *)bp->address);
}
}
--
2.17.1
^ permalink raw reply related [flat|nested] 71+ messages in thread
* [PATCH v5 02/21] powerpc/xmon: Move out-of-line instructions to text section
2020-04-06 8:09 [PATCH v5 00/21] Initial Prefixed Instruction support Jordan Niethe
2020-04-06 8:09 ` [PATCH v5 01/21] powerpc/xmon: Remove store_inst() for patch_instruction() Jordan Niethe
@ 2020-04-06 8:09 ` Jordan Niethe
2020-04-07 6:45 ` Balamuruhan S
2020-04-09 6:11 ` Christophe Leroy
2020-04-06 8:09 ` [PATCH v5 03/21] powerpc: Change calling convention for create_branch() et. al Jordan Niethe
` (19 subsequent siblings)
21 siblings, 2 replies; 71+ messages in thread
From: Jordan Niethe @ 2020-04-06 8:09 UTC (permalink / raw)
To: linuxppc-dev; +Cc: alistair, npiggin, bala24, Jordan Niethe, dja
To execute an instruction out of line after a breakpoint, the NIP is set
to the address of struct bpt::instr. Here a copy of the instruction that
was replaced with a breakpoint is kept, along with a trap so normal flow
can be resumed after XOLing. The struct bpt's are located within the
data section. This is problematic as the data section may be marked as
no execute.
Instead of each struct bpt holding the instructions to be XOL'd, make a
new array, bpt_table[], with enough space to hold instructions for the
number of supported breakpoints. Place this array in the text section.
Make struct bpt::instr a pointer to the instructions in bpt_table[]
associated with that breakpoint. This association is a simple mapping:
bpts[n] -> bpt_table[n * words per breakpoint]. Currently we only need
the copied instruction followed by a trap, so 2 words per breakpoint.
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v4: New to series
v5: - Do not use __section(), use a .space directive in .S file
- Simplify in_breakpoint_table() calculation
- Define BPT_SIZE
---
arch/powerpc/xmon/Makefile | 2 +-
arch/powerpc/xmon/xmon.c | 23 +++++++++++++----------
arch/powerpc/xmon/xmon_bpts.S | 8 ++++++++
arch/powerpc/xmon/xmon_bpts.h | 8 ++++++++
4 files changed, 30 insertions(+), 11 deletions(-)
create mode 100644 arch/powerpc/xmon/xmon_bpts.S
create mode 100644 arch/powerpc/xmon/xmon_bpts.h
diff --git a/arch/powerpc/xmon/Makefile b/arch/powerpc/xmon/Makefile
index c3842dbeb1b7..515a13ea6f28 100644
--- a/arch/powerpc/xmon/Makefile
+++ b/arch/powerpc/xmon/Makefile
@@ -21,7 +21,7 @@ endif
ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC)
-obj-y += xmon.o nonstdio.o spr_access.o
+obj-y += xmon.o nonstdio.o spr_access.o xmon_bpts.o
ifdef CONFIG_XMON_DISASSEMBLY
obj-y += ppc-dis.o ppc-opc.o
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 02e3bd62cab4..049375206510 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -62,6 +62,7 @@
#include "nonstdio.h"
#include "dis-asm.h"
+#include "xmon_bpts.h"
#ifdef CONFIG_SMP
static cpumask_t cpus_in_xmon = CPU_MASK_NONE;
@@ -97,7 +98,7 @@ static long *xmon_fault_jmp[NR_CPUS];
/* Breakpoint stuff */
struct bpt {
unsigned long address;
- unsigned int instr[2];
+ unsigned int *instr;
atomic_t ref_count;
int enabled;
unsigned long pad;
@@ -108,7 +109,6 @@ struct bpt {
#define BP_TRAP 2
#define BP_DABR 4
-#define NBPTS 256
static struct bpt bpts[NBPTS];
static struct bpt dabr;
static struct bpt *iabr;
@@ -116,6 +116,10 @@ static unsigned bpinstr = 0x7fe00008; /* trap */
#define BP_NUM(bp) ((bp) - bpts + 1)
+#define BPT_SIZE (sizeof(unsigned int) * 2)
+#define BPT_WORDS (BPT_SIZE / sizeof(unsigned int))
+extern unsigned int bpt_table[NBPTS * BPT_WORDS];
+
/* Prototypes */
static int cmds(struct pt_regs *);
static int mread(unsigned long, void *, int);
@@ -853,15 +857,13 @@ static struct bpt *in_breakpoint_table(unsigned long nip, unsigned long *offp)
{
unsigned long off;
- off = nip - (unsigned long) bpts;
- if (off >= sizeof(bpts))
+ off = nip - (unsigned long) bpt_table;
+ if (off >= sizeof(bpt_table))
return NULL;
- off %= sizeof(struct bpt);
- if (off != offsetof(struct bpt, instr[0])
- && off != offsetof(struct bpt, instr[1]))
+ *offp = off % BPT_SIZE;
+ if (*offp != 0 && *offp != 4)
return NULL;
- *offp = off - offsetof(struct bpt, instr[0]);
- return (struct bpt *) (nip - off);
+ return bpts + (off / BPT_SIZE);
}
static struct bpt *new_breakpoint(unsigned long a)
@@ -876,7 +878,8 @@ static struct bpt *new_breakpoint(unsigned long a)
for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
if (!bp->enabled && atomic_read(&bp->ref_count) == 0) {
bp->address = a;
- patch_instruction(&bp->instr[1], bpinstr);
+ bp->instr = bpt_table + ((bp - bpts) * BPT_WORDS);
+ patch_instruction(bp->instr + 1, bpinstr);
return bp;
}
}
diff --git a/arch/powerpc/xmon/xmon_bpts.S b/arch/powerpc/xmon/xmon_bpts.S
new file mode 100644
index 000000000000..ebb2dbc70ca8
--- /dev/null
+++ b/arch/powerpc/xmon/xmon_bpts.S
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#include <asm/ppc_asm.h>
+#include <asm/asm-compat.h>
+#include "xmon_bpts.h"
+
+.global bpt_table
+bpt_table:
+ .space NBPTS * 8
diff --git a/arch/powerpc/xmon/xmon_bpts.h b/arch/powerpc/xmon/xmon_bpts.h
new file mode 100644
index 000000000000..840e70be7945
--- /dev/null
+++ b/arch/powerpc/xmon/xmon_bpts.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef XMON_BPTS_H
+#define XMON_BPTS_H
+
+#define NBPTS 256
+
+#endif /* XMON_BPTS_H */
+
--
2.17.1
^ permalink raw reply related [flat|nested] 71+ messages in thread
* [PATCH v5 03/21] powerpc: Change calling convention for create_branch() et. al.
2020-04-06 8:09 [PATCH v5 00/21] Initial Prefixed Instruction support Jordan Niethe
2020-04-06 8:09 ` [PATCH v5 01/21] powerpc/xmon: Remove store_inst() for patch_instruction() Jordan Niethe
2020-04-06 8:09 ` [PATCH v5 02/21] powerpc/xmon: Move out-of-line instructions to text section Jordan Niethe
@ 2020-04-06 8:09 ` Jordan Niethe
2020-04-06 10:25 ` kbuild test robot
2020-04-07 6:10 ` Balamuruhan S
2020-04-06 8:09 ` [PATCH v5 04/21] powerpc: Use a macro for creating instructions from u32s Jordan Niethe
` (18 subsequent siblings)
21 siblings, 2 replies; 71+ messages in thread
From: Jordan Niethe @ 2020-04-06 8:09 UTC (permalink / raw)
To: linuxppc-dev; +Cc: alistair, npiggin, bala24, Jordan Niethe, dja
create_branch(), create_cond_branch() and translate_branch() return the
instruction that they create, or return 0 to signal an error. Seperate
these concerns in preparation for an instruction type that is not just
an unsigned int. Fill the created instruction to a pointer passed as
the first parameter to the function and use a non-zero return value to
signify an error.
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v5: New to series
---
arch/powerpc/include/asm/code-patching.h | 12 +-
arch/powerpc/kernel/optprobes.c | 24 ++--
arch/powerpc/kernel/setup_32.c | 2 +-
arch/powerpc/kernel/trace/ftrace.c | 24 ++--
arch/powerpc/lib/code-patching.c | 133 +++++++++++++----------
arch/powerpc/lib/feature-fixups.c | 5 +-
6 files changed, 117 insertions(+), 83 deletions(-)
diff --git a/arch/powerpc/include/asm/code-patching.h b/arch/powerpc/include/asm/code-patching.h
index 898b54262881..351dda7215b6 100644
--- a/arch/powerpc/include/asm/code-patching.h
+++ b/arch/powerpc/include/asm/code-patching.h
@@ -22,10 +22,10 @@
#define BRANCH_ABSOLUTE 0x2
bool is_offset_in_branch_range(long offset);
-unsigned int create_branch(const unsigned int *addr,
- unsigned long target, int flags);
-unsigned int create_cond_branch(const unsigned int *addr,
- unsigned long target, int flags);
+int create_branch(unsigned int *instr, const unsigned int *addr,
+ unsigned long target, int flags);
+int create_cond_branch(unsigned int *instr, const unsigned int *addr,
+ unsigned long target, int flags);
int patch_branch(unsigned int *addr, unsigned long target, int flags);
int patch_instruction(unsigned int *addr, unsigned int instr);
int raw_patch_instruction(unsigned int *addr, unsigned int instr);
@@ -60,8 +60,8 @@ int instr_is_relative_branch(unsigned int instr);
int instr_is_relative_link_branch(unsigned int instr);
int instr_is_branch_to_addr(const unsigned int *instr, unsigned long addr);
unsigned long branch_target(const unsigned int *instr);
-unsigned int translate_branch(const unsigned int *dest,
- const unsigned int *src);
+int translate_branch(unsigned int *instr, const unsigned int *dest,
+ const unsigned int *src);
extern bool is_conditional_branch(unsigned int instr);
#ifdef CONFIG_PPC_BOOK3E_64
void __patch_exception(int exc, unsigned long addr);
diff --git a/arch/powerpc/kernel/optprobes.c b/arch/powerpc/kernel/optprobes.c
index 024f7aad1952..445b3dad82dc 100644
--- a/arch/powerpc/kernel/optprobes.c
+++ b/arch/powerpc/kernel/optprobes.c
@@ -251,15 +251,17 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p)
goto error;
}
- branch_op_callback = create_branch((unsigned int *)buff + TMPL_CALL_HDLR_IDX,
- (unsigned long)op_callback_addr,
- BRANCH_SET_LINK);
+ rc = create_branch(&branch_op_callback,
+ (unsigned int *)buff + TMPL_CALL_HDLR_IDX,
+ (unsigned long)op_callback_addr,
+ BRANCH_SET_LINK);
- branch_emulate_step = create_branch((unsigned int *)buff + TMPL_EMULATE_IDX,
- (unsigned long)emulate_step_addr,
- BRANCH_SET_LINK);
+ rc |= create_branch(&branch_emulate_step,
+ (unsigned int *)buff + TMPL_EMULATE_IDX,
+ (unsigned long)emulate_step_addr,
+ BRANCH_SET_LINK);
- if (!branch_op_callback || !branch_emulate_step)
+ if (rc)
goto error;
patch_instruction(buff + TMPL_CALL_HDLR_IDX, branch_op_callback);
@@ -305,6 +307,7 @@ int arch_check_optimized_kprobe(struct optimized_kprobe *op)
void arch_optimize_kprobes(struct list_head *oplist)
{
+ unsigned int instr;
struct optimized_kprobe *op;
struct optimized_kprobe *tmp;
@@ -315,9 +318,10 @@ void arch_optimize_kprobes(struct list_head *oplist)
*/
memcpy(op->optinsn.copied_insn, op->kp.addr,
RELATIVEJUMP_SIZE);
- patch_instruction(op->kp.addr,
- create_branch((unsigned int *)op->kp.addr,
- (unsigned long)op->optinsn.insn, 0));
+ create_branch(&instr,
+ (unsigned int *)op->kp.addr,
+ (unsigned long)op->optinsn.insn, 0);
+ patch_instruction(op->kp.addr, instr);
list_del_init(&op->list);
}
}
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 5b49b26eb154..c1bdd462c5c0 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -88,7 +88,7 @@ notrace void __init machine_init(u64 dt_ptr)
patch_instruction_site(&patch__memcpy_nocache, PPC_INST_NOP);
- insn = create_cond_branch(addr, branch_target(addr), 0x820000);
+ create_cond_branch(&insn, addr, branch_target(addr), 0x820000);
patch_instruction(addr, insn); /* replace b by bne cr0 */
/* Do some early initialization based on the flat device tree */
diff --git a/arch/powerpc/kernel/trace/ftrace.c b/arch/powerpc/kernel/trace/ftrace.c
index 7ea0ca044b65..4dcb379133f8 100644
--- a/arch/powerpc/kernel/trace/ftrace.c
+++ b/arch/powerpc/kernel/trace/ftrace.c
@@ -48,7 +48,7 @@ ftrace_call_replace(unsigned long ip, unsigned long addr, int link)
addr = ppc_function_entry((void *)addr);
/* if (link) set op to 'bl' else 'b' */
- op = create_branch((unsigned int *)ip, addr, link ? 1 : 0);
+ create_branch(&op, (unsigned int *)ip, addr, link ? 1 : 0);
return op;
}
@@ -89,10 +89,11 @@ ftrace_modify_code(unsigned long ip, unsigned int old, unsigned int new)
*/
static int test_24bit_addr(unsigned long ip, unsigned long addr)
{
+ unsigned int op;
addr = ppc_function_entry((void *)addr);
/* use the create_branch to verify that this offset can be branched */
- return create_branch((unsigned int *)ip, addr, 0);
+ return create_branch(&op, (unsigned int *)ip, addr, 0) == 0;
}
static int is_bl_op(unsigned int op)
@@ -287,6 +288,7 @@ __ftrace_make_nop(struct module *mod,
static unsigned long find_ftrace_tramp(unsigned long ip)
{
int i;
+ unsigned int instr;
/*
* We have the compiler generated long_branch tramps at the end
@@ -295,7 +297,8 @@ static unsigned long find_ftrace_tramp(unsigned long ip)
for (i = NUM_FTRACE_TRAMPS - 1; i >= 0; i--)
if (!ftrace_tramps[i])
continue;
- else if (create_branch((void *)ip, ftrace_tramps[i], 0))
+ else if (create_branch(&instr, (void *)ip,
+ ftrace_tramps[i], 0) == 0)
return ftrace_tramps[i];
return 0;
@@ -324,6 +327,7 @@ static int setup_mcount_compiler_tramp(unsigned long tramp)
{
int i, op;
unsigned long ptr;
+ unsigned int instr;
static unsigned long ftrace_plt_tramps[NUM_FTRACE_TRAMPS];
/* Is this a known long jump tramp? */
@@ -366,7 +370,7 @@ static int setup_mcount_compiler_tramp(unsigned long tramp)
#else
ptr = ppc_global_function_entry((void *)ftrace_caller);
#endif
- if (!create_branch((void *)tramp, ptr, 0)) {
+ if (create_branch(&instr, (void *)tramp, ptr, 0)) {
pr_debug("%ps is not reachable from existing mcount tramp\n",
(void *)ptr);
return -1;
@@ -511,6 +515,7 @@ static int
__ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
{
unsigned int op[2];
+ unsigned int instr;
void *ip = (void *)rec->ip;
unsigned long entry, ptr, tramp;
struct module *mod = rec->arch.mod;
@@ -557,7 +562,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
}
/* Ensure branch is within 24 bits */
- if (!create_branch(ip, tramp, BRANCH_SET_LINK)) {
+ if (create_branch(&instr, ip, tramp, BRANCH_SET_LINK)) {
pr_err("Branch out of range\n");
return -EINVAL;
}
@@ -574,6 +579,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
static int
__ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
{
+ int err;
unsigned int op;
unsigned long ip = rec->ip;
@@ -594,9 +600,9 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
}
/* create the branch to the trampoline */
- op = create_branch((unsigned int *)ip,
- rec->arch.mod->arch.tramp, BRANCH_SET_LINK);
- if (!op) {
+ err = create_branch(&op, (unsigned int *)ip,
+ rec->arch.mod->arch.tramp, BRANCH_SET_LINK);
+ if (!err) {
pr_err("REL24 out of range!\n");
return -EINVAL;
}
@@ -776,7 +782,7 @@ __ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
}
/* Ensure branch is within 24 bits */
- if (!create_branch((unsigned int *)ip, tramp, BRANCH_SET_LINK)) {
+ if (create_branch(&op, (unsigned int *)ip, tramp, BRANCH_SET_LINK)) {
pr_err("Branch out of range\n");
return -EINVAL;
}
diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index 3345f039a876..4af564aeedf1 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -196,7 +196,10 @@ NOKPROBE_SYMBOL(patch_instruction);
int patch_branch(unsigned int *addr, unsigned long target, int flags)
{
- return patch_instruction(addr, create_branch(addr, target, flags));
+ unsigned int instr;
+
+ create_branch(&instr, addr, target, flags);
+ return patch_instruction(addr, instr);
}
bool is_offset_in_branch_range(long offset)
@@ -243,30 +246,30 @@ bool is_conditional_branch(unsigned int instr)
}
NOKPROBE_SYMBOL(is_conditional_branch);
-unsigned int create_branch(const unsigned int *addr,
- unsigned long target, int flags)
+int create_branch(unsigned int *instr,
+ const unsigned int *addr,
+ unsigned long target, int flags)
{
- unsigned int instruction;
long offset;
+ *instr = 0;
offset = target;
if (! (flags & BRANCH_ABSOLUTE))
offset = offset - (unsigned long)addr;
/* Check we can represent the target in the instruction format */
if (!is_offset_in_branch_range(offset))
- return 0;
+ return 1;
/* Mask out the flags and target, so they don't step on each other. */
- instruction = 0x48000000 | (flags & 0x3) | (offset & 0x03FFFFFC);
+ *instr = 0x48000000 | (flags & 0x3) | (offset & 0x03FFFFFC);
- return instruction;
+ return 0;
}
-unsigned int create_cond_branch(const unsigned int *addr,
- unsigned long target, int flags)
+int create_cond_branch(unsigned int *instr, const unsigned int *addr,
+ unsigned long target, int flags)
{
- unsigned int instruction;
long offset;
offset = target;
@@ -275,12 +278,12 @@ unsigned int create_cond_branch(const unsigned int *addr,
/* Check we can represent the target in the instruction format */
if (offset < -0x8000 || offset > 0x7FFF || offset & 0x3)
- return 0;
+ return 1;
/* Mask out the flags and target, so they don't step on each other. */
- instruction = 0x40000000 | (flags & 0x3FF0003) | (offset & 0xFFFC);
+ *instr = 0x40000000 | (flags & 0x3FF0003) | (offset & 0xFFFC);
- return instruction;
+ return 0;
}
static unsigned int branch_opcode(unsigned int instr)
@@ -361,18 +364,18 @@ int instr_is_branch_to_addr(const unsigned int *instr, unsigned long addr)
return 0;
}
-unsigned int translate_branch(const unsigned int *dest, const unsigned int *src)
+int translate_branch(unsigned int *instr, const unsigned int *dest, const unsigned int *src)
{
unsigned long target;
target = branch_target(src);
if (instr_is_branch_iform(*src))
- return create_branch(dest, target, *src);
+ return create_branch(instr, dest, target, *src);
else if (instr_is_branch_bform(*src))
- return create_cond_branch(dest, target, *src);
+ return create_cond_branch(instr, dest, target, *src);
- return 0;
+ return 1;
}
#ifdef CONFIG_PPC_BOOK3E_64
@@ -403,6 +406,7 @@ static void __init test_trampoline(void)
static void __init test_branch_iform(void)
{
+ int err;
unsigned int instr;
unsigned long addr;
@@ -443,35 +447,35 @@ static void __init test_branch_iform(void)
check(instr_is_branch_to_addr(&instr, addr - 0x2000000));
/* Branch to self, with link */
- instr = create_branch(&instr, addr, BRANCH_SET_LINK);
+ err = create_branch(&instr, &instr, addr, BRANCH_SET_LINK);
check(instr_is_branch_to_addr(&instr, addr));
/* Branch to self - 0x100, with link */
- instr = create_branch(&instr, addr - 0x100, BRANCH_SET_LINK);
+ err = create_branch(&instr, &instr, addr - 0x100, BRANCH_SET_LINK);
check(instr_is_branch_to_addr(&instr, addr - 0x100));
/* Branch to self + 0x100, no link */
- instr = create_branch(&instr, addr + 0x100, 0);
+ err = create_branch(&instr, &instr, addr + 0x100, 0);
check(instr_is_branch_to_addr(&instr, addr + 0x100));
/* Maximum relative negative offset, - 32 MB */
- instr = create_branch(&instr, addr - 0x2000000, BRANCH_SET_LINK);
+ err = create_branch(&instr, &instr, addr - 0x2000000, BRANCH_SET_LINK);
check(instr_is_branch_to_addr(&instr, addr - 0x2000000));
/* Out of range relative negative offset, - 32 MB + 4*/
- instr = create_branch(&instr, addr - 0x2000004, BRANCH_SET_LINK);
- check(instr == 0);
+ err = create_branch(&instr, &instr, addr - 0x2000004, BRANCH_SET_LINK);
+ check(err);
/* Out of range relative positive offset, + 32 MB */
- instr = create_branch(&instr, addr + 0x2000000, BRANCH_SET_LINK);
- check(instr == 0);
+ err = create_branch(&instr, &instr, addr + 0x2000000, BRANCH_SET_LINK);
+ check(err);
/* Unaligned target */
- instr = create_branch(&instr, addr + 3, BRANCH_SET_LINK);
- check(instr == 0);
+ err = create_branch(&instr, &instr, addr + 3, BRANCH_SET_LINK);
+ check(err);
/* Check flags are masked correctly */
- instr = create_branch(&instr, addr, 0xFFFFFFFC);
+ err = create_branch(&instr, &instr, addr, 0xFFFFFFFC);
check(instr_is_branch_to_addr(&instr, addr));
check(instr == 0x48000000);
}
@@ -480,16 +484,19 @@ static void __init test_create_function_call(void)
{
unsigned int *iptr;
unsigned long dest;
+ unsigned int instr;
/* Check we can create a function call */
iptr = (unsigned int *)ppc_function_entry(test_trampoline);
dest = ppc_function_entry(test_create_function_call);
- patch_instruction(iptr, create_branch(iptr, dest, BRANCH_SET_LINK));
+ create_branch(&instr, iptr, dest, BRANCH_SET_LINK);
+ patch_instruction(iptr, instr);
check(instr_is_branch_to_addr(iptr, dest));
}
static void __init test_branch_bform(void)
{
+ int err;
unsigned long addr;
unsigned int *iptr, instr, flags;
@@ -525,35 +532,35 @@ static void __init test_branch_bform(void)
flags = 0x3ff000 | BRANCH_SET_LINK;
/* Branch to self */
- instr = create_cond_branch(iptr, addr, flags);
+ err = create_cond_branch(&instr, iptr, addr, flags);
check(instr_is_branch_to_addr(&instr, addr));
/* Branch to self - 0x100 */
- instr = create_cond_branch(iptr, addr - 0x100, flags);
+ err = create_cond_branch(&instr, iptr, addr - 0x100, flags);
check(instr_is_branch_to_addr(&instr, addr - 0x100));
/* Branch to self + 0x100 */
- instr = create_cond_branch(iptr, addr + 0x100, flags);
+ err = create_cond_branch(&instr, iptr, addr + 0x100, flags);
check(instr_is_branch_to_addr(&instr, addr + 0x100));
/* Maximum relative negative offset, - 32 KB */
- instr = create_cond_branch(iptr, addr - 0x8000, flags);
+ err = create_cond_branch(&instr, iptr, addr - 0x8000, flags);
check(instr_is_branch_to_addr(&instr, addr - 0x8000));
/* Out of range relative negative offset, - 32 KB + 4*/
- instr = create_cond_branch(iptr, addr - 0x8004, flags);
- check(instr == 0);
+ err = create_cond_branch(&instr, iptr, addr - 0x8004, flags);
+ check(err);
/* Out of range relative positive offset, + 32 KB */
- instr = create_cond_branch(iptr, addr + 0x8000, flags);
- check(instr == 0);
+ err = create_cond_branch(&instr, iptr, addr + 0x8000, flags);
+ check(err);
/* Unaligned target */
- instr = create_cond_branch(iptr, addr + 3, flags);
- check(instr == 0);
+ err = create_cond_branch(&instr, iptr, addr + 3, flags);
+ check(err);
/* Check flags are masked correctly */
- instr = create_cond_branch(iptr, addr, 0xFFFFFFFC);
+ err = create_cond_branch(&instr, iptr, addr, 0xFFFFFFFC);
check(instr_is_branch_to_addr(&instr, addr));
check(instr == 0x43FF0000);
}
@@ -562,6 +569,7 @@ static void __init test_translate_branch(void)
{
unsigned long addr;
unsigned int *p, *q;
+ unsigned int instr;
void *buf;
buf = vmalloc(PAGE_ALIGN(0x2000000 + 1));
@@ -575,7 +583,8 @@ static void __init test_translate_branch(void)
patch_branch(p, addr, 0);
check(instr_is_branch_to_addr(p, addr));
q = p + 1;
- patch_instruction(q, translate_branch(q, p));
+ translate_branch(&instr, q, p);
+ patch_instruction(q, instr);
check(instr_is_branch_to_addr(q, addr));
/* Maximum negative case, move b . to addr + 32 MB */
@@ -583,7 +592,8 @@ static void __init test_translate_branch(void)
addr = (unsigned long)p;
patch_branch(p, addr, 0);
q = buf + 0x2000000;
- patch_instruction(q, translate_branch(q, p));
+ translate_branch(&instr, q, p);
+ patch_instruction(q, instr);
check(instr_is_branch_to_addr(p, addr));
check(instr_is_branch_to_addr(q, addr));
check(*q == 0x4a000000);
@@ -593,7 +603,8 @@ static void __init test_translate_branch(void)
addr = (unsigned long)p;
patch_branch(p, addr, 0);
q = buf + 4;
- patch_instruction(q, translate_branch(q, p));
+ translate_branch(&instr, q, p);
+ patch_instruction(q, instr);
check(instr_is_branch_to_addr(p, addr));
check(instr_is_branch_to_addr(q, addr));
check(*q == 0x49fffffc);
@@ -603,7 +614,8 @@ static void __init test_translate_branch(void)
addr = 0x1000000 + (unsigned long)buf;
patch_branch(p, addr, BRANCH_SET_LINK);
q = buf + 0x1400000;
- patch_instruction(q, translate_branch(q, p));
+ translate_branch(&instr, q, p);
+ patch_instruction(q, instr);
check(instr_is_branch_to_addr(p, addr));
check(instr_is_branch_to_addr(q, addr));
@@ -612,7 +624,8 @@ static void __init test_translate_branch(void)
addr = 0x2000000 + (unsigned long)buf;
patch_branch(p, addr, 0);
q = buf + 4;
- patch_instruction(q, translate_branch(q, p));
+ translate_branch(&instr, q, p);
+ patch_instruction(q, instr);
check(instr_is_branch_to_addr(p, addr));
check(instr_is_branch_to_addr(q, addr));
@@ -622,18 +635,22 @@ static void __init test_translate_branch(void)
/* Simple case, branch to self moved a little */
p = buf;
addr = (unsigned long)p;
- patch_instruction(p, create_cond_branch(p, addr, 0));
+ create_cond_branch(&instr, p, addr, 0);
+ patch_instruction(p, instr);
check(instr_is_branch_to_addr(p, addr));
q = p + 1;
- patch_instruction(q, translate_branch(q, p));
+ translate_branch(&instr, q, p);
+ patch_instruction(q, instr);
check(instr_is_branch_to_addr(q, addr));
/* Maximum negative case, move b . to addr + 32 KB */
p = buf;
addr = (unsigned long)p;
- patch_instruction(p, create_cond_branch(p, addr, 0xFFFFFFFC));
+ create_cond_branch(&instr, p, addr, 0xFFFFFFFC);
+ patch_instruction(p, instr);
q = buf + 0x8000;
- patch_instruction(q, translate_branch(q, p));
+ translate_branch(&instr, q, p);
+ patch_instruction(q, instr);
check(instr_is_branch_to_addr(p, addr));
check(instr_is_branch_to_addr(q, addr));
check(*q == 0x43ff8000);
@@ -641,9 +658,11 @@ static void __init test_translate_branch(void)
/* Maximum positive case, move x to x - 32 KB + 4 */
p = buf + 0x8000;
addr = (unsigned long)p;
- patch_instruction(p, create_cond_branch(p, addr, 0xFFFFFFFC));
+ create_cond_branch(&instr, p, addr, 0xFFFFFFFC);
+ patch_instruction(p, instr);
q = buf + 4;
- patch_instruction(q, translate_branch(q, p));
+ translate_branch(&instr, q, p);
+ patch_instruction(q, instr);
check(instr_is_branch_to_addr(p, addr));
check(instr_is_branch_to_addr(q, addr));
check(*q == 0x43ff7ffc);
@@ -651,18 +670,22 @@ static void __init test_translate_branch(void)
/* Jump to x + 12 KB moved to x + 20 KB */
p = buf;
addr = 0x3000 + (unsigned long)buf;
- patch_instruction(p, create_cond_branch(p, addr, BRANCH_SET_LINK));
+ create_cond_branch(&instr, p, addr, BRANCH_SET_LINK);
+ patch_instruction(p, instr);
q = buf + 0x5000;
- patch_instruction(q, translate_branch(q, p));
+ translate_branch(&instr, q, p);
+ patch_instruction(q, instr);
check(instr_is_branch_to_addr(p, addr));
check(instr_is_branch_to_addr(q, addr));
/* Jump to x + 8 KB moved to x - 8 KB + 4 */
p = buf + 0x2000;
addr = 0x4000 + (unsigned long)buf;
- patch_instruction(p, create_cond_branch(p, addr, 0));
+ create_cond_branch(&instr, p, addr, 0);
+ patch_instruction(p, instr);
q = buf + 4;
- patch_instruction(q, translate_branch(q, p));
+ translate_branch(&instr, q, p);
+ patch_instruction(q, instr);
check(instr_is_branch_to_addr(p, addr));
check(instr_is_branch_to_addr(q, addr));
diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c
index 4ba634b89ce5..b129d7b4e7dd 100644
--- a/arch/powerpc/lib/feature-fixups.c
+++ b/arch/powerpc/lib/feature-fixups.c
@@ -44,6 +44,7 @@ static unsigned int *calc_addr(struct fixup_entry *fcur, long offset)
static int patch_alt_instruction(unsigned int *src, unsigned int *dest,
unsigned int *alt_start, unsigned int *alt_end)
{
+ int err;
unsigned int instr;
instr = *src;
@@ -53,8 +54,8 @@ static int patch_alt_instruction(unsigned int *src, unsigned int *dest,
/* Branch within the section doesn't need translating */
if (target < alt_start || target > alt_end) {
- instr = translate_branch(dest, src);
- if (!instr)
+ err = translate_branch(&instr, dest, src);
+ if (err)
return 1;
}
}
--
2.17.1
^ permalink raw reply related [flat|nested] 71+ messages in thread
* [PATCH v5 04/21] powerpc: Use a macro for creating instructions from u32s
2020-04-06 8:09 [PATCH v5 00/21] Initial Prefixed Instruction support Jordan Niethe
` (2 preceding siblings ...)
2020-04-06 8:09 ` [PATCH v5 03/21] powerpc: Change calling convention for create_branch() et. al Jordan Niethe
@ 2020-04-06 8:09 ` Jordan Niethe
2020-04-07 6:40 ` Balamuruhan S
2020-04-06 8:09 ` [PATCH v5 05/21] powerpc: Use a function for getting the instruction op code Jordan Niethe
` (17 subsequent siblings)
21 siblings, 1 reply; 71+ messages in thread
From: Jordan Niethe @ 2020-04-06 8:09 UTC (permalink / raw)
To: linuxppc-dev; +Cc: alistair, npiggin, bala24, Jordan Niethe, dja
In preparation for instructions having a more complex data type start
using a macro, ppc_inst(), for making an instruction out of a u32. A
macro is used so that instructions can be used as initializer elements.
Currently this does nothing, but it will allow for creating a data type
that can represent prefixed instructions.
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v4: New to series
v5: - Rename PPC_INST() -> ppc_inst().
- Use on epapr_paravirt.c, kgdb.c
---
arch/powerpc/include/asm/code-patching.h | 3 +-
arch/powerpc/include/asm/inst.h | 11 +++++
arch/powerpc/kernel/align.c | 1 +
arch/powerpc/kernel/epapr_paravirt.c | 5 ++-
arch/powerpc/kernel/hw_breakpoint.c | 3 +-
arch/powerpc/kernel/jump_label.c | 3 +-
arch/powerpc/kernel/kgdb.c | 5 ++-
arch/powerpc/kernel/kprobes.c | 5 ++-
arch/powerpc/kernel/module_64.c | 3 +-
arch/powerpc/kernel/optprobes.c | 31 ++++++-------
arch/powerpc/kernel/security.c | 9 ++--
arch/powerpc/kernel/trace/ftrace.c | 25 ++++++-----
arch/powerpc/kernel/uprobes.c | 1 +
arch/powerpc/kvm/emulate_loadstore.c | 2 +-
arch/powerpc/lib/code-patching.c | 57 ++++++++++++------------
arch/powerpc/lib/feature-fixups.c | 39 ++++++++--------
arch/powerpc/lib/test_emulate_step.c | 39 ++++++++--------
arch/powerpc/xmon/xmon.c | 7 +--
18 files changed, 138 insertions(+), 111 deletions(-)
create mode 100644 arch/powerpc/include/asm/inst.h
diff --git a/arch/powerpc/include/asm/code-patching.h b/arch/powerpc/include/asm/code-patching.h
index 351dda7215b6..48e021957ee5 100644
--- a/arch/powerpc/include/asm/code-patching.h
+++ b/arch/powerpc/include/asm/code-patching.h
@@ -11,6 +11,7 @@
#include <linux/string.h>
#include <linux/kallsyms.h>
#include <asm/asm-compat.h>
+#include <asm/inst.h>
/* Flags for create_branch:
* "b" == create_branch(addr, target, 0);
@@ -48,7 +49,7 @@ static inline int patch_branch_site(s32 *site, unsigned long target, int flags)
static inline int modify_instruction(unsigned int *addr, unsigned int clr,
unsigned int set)
{
- return patch_instruction(addr, (*addr & ~clr) | set);
+ return patch_instruction(addr, ppc_inst((*addr & ~clr) | set));
}
static inline int modify_instruction_site(s32 *site, unsigned int clr, unsigned int set)
diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h
new file mode 100644
index 000000000000..5298ba33b6e5
--- /dev/null
+++ b/arch/powerpc/include/asm/inst.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#ifndef _ASM_INST_H
+#define _ASM_INST_H
+
+/*
+ * Instruction data type for POWER
+ */
+
+#define ppc_inst(x) (x)
+
+#endif /* _ASM_INST_H */
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
index 92045ed64976..86e9bf62f18c 100644
--- a/arch/powerpc/kernel/align.c
+++ b/arch/powerpc/kernel/align.c
@@ -24,6 +24,7 @@
#include <asm/disassemble.h>
#include <asm/cpu_has_feature.h>
#include <asm/sstep.h>
+#include <asm/inst.h>
struct aligninfo {
unsigned char len;
diff --git a/arch/powerpc/kernel/epapr_paravirt.c b/arch/powerpc/kernel/epapr_paravirt.c
index 9d32158ce36f..c53e863fb484 100644
--- a/arch/powerpc/kernel/epapr_paravirt.c
+++ b/arch/powerpc/kernel/epapr_paravirt.c
@@ -11,6 +11,7 @@
#include <asm/cacheflush.h>
#include <asm/code-patching.h>
#include <asm/machdep.h>
+#include <asm/inst.h>
#if !defined(CONFIG_64BIT) || defined(CONFIG_PPC_BOOK3E_64)
extern void epapr_ev_idle(void);
@@ -37,9 +38,9 @@ static int __init early_init_dt_scan_epapr(unsigned long node,
for (i = 0; i < (len / 4); i++) {
u32 inst = be32_to_cpu(insts[i]);
- patch_instruction(epapr_hypercall_start + i, inst);
+ patch_instruction(epapr_hypercall_start + i, ppc_inst(inst));
#if !defined(CONFIG_64BIT) || defined(CONFIG_PPC_BOOK3E_64)
- patch_instruction(epapr_ev_idle_start + i, inst);
+ patch_instruction(epapr_ev_idle_start + i, ppc_inst(inst));
#endif
}
diff --git a/arch/powerpc/kernel/hw_breakpoint.c b/arch/powerpc/kernel/hw_breakpoint.c
index 2462cd7c565c..79f51f182a83 100644
--- a/arch/powerpc/kernel/hw_breakpoint.c
+++ b/arch/powerpc/kernel/hw_breakpoint.c
@@ -24,6 +24,7 @@
#include <asm/debug.h>
#include <asm/debugfs.h>
#include <asm/hvcall.h>
+#include <asm/inst.h>
#include <linux/uaccess.h>
/*
@@ -243,7 +244,7 @@ dar_range_overlaps(unsigned long dar, int size, struct arch_hw_breakpoint *info)
static bool stepping_handler(struct pt_regs *regs, struct perf_event *bp,
struct arch_hw_breakpoint *info)
{
- unsigned int instr = 0;
+ unsigned int instr = ppc_inst(0);
int ret, type, size;
struct instruction_op op;
unsigned long addr = info->address;
diff --git a/arch/powerpc/kernel/jump_label.c b/arch/powerpc/kernel/jump_label.c
index ca37702bde97..daa4afce7ec8 100644
--- a/arch/powerpc/kernel/jump_label.c
+++ b/arch/powerpc/kernel/jump_label.c
@@ -6,6 +6,7 @@
#include <linux/kernel.h>
#include <linux/jump_label.h>
#include <asm/code-patching.h>
+#include <asm/inst.h>
void arch_jump_label_transform(struct jump_entry *entry,
enum jump_label_type type)
@@ -15,5 +16,5 @@ void arch_jump_label_transform(struct jump_entry *entry,
if (type == JUMP_LABEL_JMP)
patch_branch(addr, entry->target, 0);
else
- patch_instruction(addr, PPC_INST_NOP);
+ patch_instruction(addr, ppc_inst(PPC_INST_NOP));
}
diff --git a/arch/powerpc/kernel/kgdb.c b/arch/powerpc/kernel/kgdb.c
index 7dd55eb1259d..a6b38a19133f 100644
--- a/arch/powerpc/kernel/kgdb.c
+++ b/arch/powerpc/kernel/kgdb.c
@@ -26,6 +26,7 @@
#include <asm/debug.h>
#include <asm/code-patching.h>
#include <linux/slab.h>
+#include <asm/inst.h>
/*
* This table contains the mapping between PowerPC hardware trap types, and
@@ -424,7 +425,7 @@ int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
if (err)
return err;
- err = patch_instruction(addr, BREAK_INSTR);
+ err = patch_instruction(addr, ppc_inst(BREAK_INSTR));
if (err)
return -EFAULT;
@@ -439,7 +440,7 @@ int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
unsigned int instr = *(unsigned int *)bpt->saved_instr;
unsigned int *addr = (unsigned int *)bpt->bpt_addr;
- err = patch_instruction(addr, instr);
+ err = patch_instruction(addr, ppc_inst(instr));
if (err)
return -EFAULT;
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index 2d27ec4feee4..a1a3686f41c6 100644
--- a/arch/powerpc/kernel/kprobes.c
+++ b/arch/powerpc/kernel/kprobes.c
@@ -23,6 +23,7 @@
#include <asm/cacheflush.h>
#include <asm/sstep.h>
#include <asm/sections.h>
+#include <asm/inst.h>
#include <linux/uaccess.h>
DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
@@ -138,13 +139,13 @@ NOKPROBE_SYMBOL(arch_prepare_kprobe);
void arch_arm_kprobe(struct kprobe *p)
{
- patch_instruction(p->addr, BREAKPOINT_INSTRUCTION);
+ patch_instruction(p->addr, ppc_inst(BREAKPOINT_INSTRUCTION));
}
NOKPROBE_SYMBOL(arch_arm_kprobe);
void arch_disarm_kprobe(struct kprobe *p)
{
- patch_instruction(p->addr, p->opcode);
+ patch_instruction(p->addr, ppc_inst(p->opcode));
}
NOKPROBE_SYMBOL(arch_disarm_kprobe);
diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c
index 007606a48fd9..7fd6b29edcb2 100644
--- a/arch/powerpc/kernel/module_64.c
+++ b/arch/powerpc/kernel/module_64.c
@@ -20,6 +20,7 @@
#include <linux/sort.h>
#include <asm/setup.h>
#include <asm/sections.h>
+#include <asm/inst.h>
/* FIXME: We don't do .init separately. To do this, we'd need to have
a separate r2 value in the init and core section, and stub between
@@ -506,7 +507,7 @@ static int restore_r2(const char *name, u32 *instruction, struct module *me)
* "link" branches and they don't return, so they don't need the r2
* restore afterwards.
*/
- if (!instr_is_relative_link_branch(*prev_insn))
+ if (!instr_is_relative_link_branch(ppc_inst(*prev_insn)))
return 1;
if (*instruction != PPC_INST_NOP) {
diff --git a/arch/powerpc/kernel/optprobes.c b/arch/powerpc/kernel/optprobes.c
index 445b3dad82dc..3b33ebf18859 100644
--- a/arch/powerpc/kernel/optprobes.c
+++ b/arch/powerpc/kernel/optprobes.c
@@ -16,6 +16,7 @@
#include <asm/code-patching.h>
#include <asm/sstep.h>
#include <asm/ppc-opcode.h>
+#include <asm/inst.h>
#define TMPL_CALL_HDLR_IDX \
(optprobe_template_call_handler - optprobe_template_entry)
@@ -147,13 +148,13 @@ void arch_remove_optimized_kprobe(struct optimized_kprobe *op)
void patch_imm32_load_insns(unsigned int val, kprobe_opcode_t *addr)
{
/* addis r4,0,(insn)@h */
- patch_instruction(addr, PPC_INST_ADDIS | ___PPC_RT(4) |
- ((val >> 16) & 0xffff));
+ patch_instruction(addr, ppc_inst(PPC_INST_ADDIS | ___PPC_RT(4) |
+ ((val >> 16) & 0xffff)));
addr++;
/* ori r4,r4,(insn)@l */
- patch_instruction(addr, PPC_INST_ORI | ___PPC_RA(4) |
- ___PPC_RS(4) | (val & 0xffff));
+ patch_instruction(addr, ppc_inst(PPC_INST_ORI | ___PPC_RA(4) |
+ ___PPC_RS(4) | (val & 0xffff)));
}
/*
@@ -163,28 +164,28 @@ void patch_imm32_load_insns(unsigned int val, kprobe_opcode_t *addr)
void patch_imm64_load_insns(unsigned long val, kprobe_opcode_t *addr)
{
/* lis r3,(op)@highest */
- patch_instruction(addr, PPC_INST_ADDIS | ___PPC_RT(3) |
- ((val >> 48) & 0xffff));
+ patch_instruction(addr, ppc_inst(PPC_INST_ADDIS | ___PPC_RT(3) |
+ ((val >> 48) & 0xffff)));
addr++;
/* ori r3,r3,(op)@higher */
- patch_instruction(addr, PPC_INST_ORI | ___PPC_RA(3) |
- ___PPC_RS(3) | ((val >> 32) & 0xffff));
+ patch_instruction(addr, ppc_inst(PPC_INST_ORI | ___PPC_RA(3) |
+ ___PPC_RS(3) | ((val >> 32) & 0xffff)));
addr++;
/* rldicr r3,r3,32,31 */
- patch_instruction(addr, PPC_INST_RLDICR | ___PPC_RA(3) |
- ___PPC_RS(3) | __PPC_SH64(32) | __PPC_ME64(31));
+ patch_instruction(addr, ppc_inst(PPC_INST_RLDICR | ___PPC_RA(3) |
+ ___PPC_RS(3) | __PPC_SH64(32) | __PPC_ME64(31)));
addr++;
/* oris r3,r3,(op)@h */
- patch_instruction(addr, PPC_INST_ORIS | ___PPC_RA(3) |
- ___PPC_RS(3) | ((val >> 16) & 0xffff));
+ patch_instruction(addr, ppc_inst(PPC_INST_ORIS | ___PPC_RA(3) |
+ ___PPC_RS(3) | ((val >> 16) & 0xffff)));
addr++;
/* ori r3,r3,(op)@l */
- patch_instruction(addr, PPC_INST_ORI | ___PPC_RA(3) |
- ___PPC_RS(3) | (val & 0xffff));
+ patch_instruction(addr, ppc_inst(PPC_INST_ORI | ___PPC_RA(3) |
+ ___PPC_RS(3) | (val & 0xffff)));
}
int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p)
@@ -230,7 +231,7 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p)
size = (TMPL_END_IDX * sizeof(kprobe_opcode_t)) / sizeof(int);
pr_devel("Copying template to %p, size %lu\n", buff, size);
for (i = 0; i < size; i++) {
- rc = patch_instruction(buff + i, *(optprobe_template_entry + i));
+ rc = patch_instruction(buff + i, ppc_inst(*(optprobe_template_entry + i)));
if (rc < 0)
goto error;
}
diff --git a/arch/powerpc/kernel/security.c b/arch/powerpc/kernel/security.c
index bd70f5be1c27..81a288b1a603 100644
--- a/arch/powerpc/kernel/security.c
+++ b/arch/powerpc/kernel/security.c
@@ -14,6 +14,7 @@
#include <asm/debugfs.h>
#include <asm/security_features.h>
#include <asm/setup.h>
+#include <asm/inst.h>
u64 powerpc_security_features __read_mostly = SEC_FTR_DEFAULT;
@@ -403,9 +404,9 @@ static void toggle_count_cache_flush(bool enable)
enable = false;
if (!enable) {
- patch_instruction_site(&patch__call_flush_count_cache, PPC_INST_NOP);
+ patch_instruction_site(&patch__call_flush_count_cache, ppc_inst(PPC_INST_NOP));
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
- patch_instruction_site(&patch__call_kvm_flush_link_stack, PPC_INST_NOP);
+ patch_instruction_site(&patch__call_kvm_flush_link_stack, ppc_inst(PPC_INST_NOP));
#endif
pr_info("link-stack-flush: software flush disabled.\n");
link_stack_flush_enabled = false;
@@ -428,7 +429,7 @@ static void toggle_count_cache_flush(bool enable)
// If we just need to flush the link stack, patch an early return
if (!security_ftr_enabled(SEC_FTR_FLUSH_COUNT_CACHE)) {
- patch_instruction_site(&patch__flush_link_stack_return, PPC_INST_BLR);
+ patch_instruction_site(&patch__flush_link_stack_return, ppc_inst(PPC_INST_BLR));
no_count_cache_flush();
return;
}
@@ -439,7 +440,7 @@ static void toggle_count_cache_flush(bool enable)
return;
}
- patch_instruction_site(&patch__flush_count_cache_return, PPC_INST_BLR);
+ patch_instruction_site(&patch__flush_count_cache_return, ppc_inst(PPC_INST_BLR));
count_cache_flush_type = COUNT_CACHE_FLUSH_HW;
pr_info("count-cache-flush: hardware assisted flush sequence enabled\n");
}
diff --git a/arch/powerpc/kernel/trace/ftrace.c b/arch/powerpc/kernel/trace/ftrace.c
index 4dcb379133f8..47233e671c18 100644
--- a/arch/powerpc/kernel/trace/ftrace.c
+++ b/arch/powerpc/kernel/trace/ftrace.c
@@ -27,6 +27,7 @@
#include <asm/code-patching.h>
#include <asm/ftrace.h>
#include <asm/syscall.h>
+#include <asm/inst.h>
#ifdef CONFIG_DYNAMIC_FTRACE
@@ -161,7 +162,7 @@ __ftrace_make_nop(struct module *mod,
#ifdef CONFIG_MPROFILE_KERNEL
/* When using -mkernel_profile there is no load to jump over */
- pop = PPC_INST_NOP;
+ pop = ppc_inst(PPC_INST_NOP);
if (probe_kernel_read(&op, (void *)(ip - 4), 4)) {
pr_err("Fetching instruction at %lx failed.\n", ip - 4);
@@ -169,7 +170,7 @@ __ftrace_make_nop(struct module *mod,
}
/* We expect either a mflr r0, or a std r0, LRSAVE(r1) */
- if (op != PPC_INST_MFLR && op != PPC_INST_STD_LR) {
+ if (op != ppc_inst(PPC_INST_MFLR) && op != ppc_inst(PPC_INST_STD_LR)) {
pr_err("Unexpected instruction %08x around bl _mcount\n", op);
return -EINVAL;
}
@@ -188,7 +189,7 @@ __ftrace_make_nop(struct module *mod,
* Use a b +8 to jump over the load.
*/
- pop = PPC_INST_BRANCH | 8; /* b +8 */
+ pop = ppc_inst(PPC_INST_BRANCH | 8); /* b +8 */
/*
* Check what is in the next instruction. We can see ld r2,40(r1), but
@@ -199,7 +200,7 @@ __ftrace_make_nop(struct module *mod,
return -EFAULT;
}
- if (op != PPC_INST_LD_TOC) {
+ if (op != ppc_inst(PPC_INST_LD_TOC)) {
pr_err("Expected %08x found %08x\n", PPC_INST_LD_TOC, op);
return -EINVAL;
}
@@ -275,7 +276,7 @@ __ftrace_make_nop(struct module *mod,
return -EINVAL;
}
- op = PPC_INST_NOP;
+ op = ppc_inst(PPC_INST_NOP);
if (patch_instruction((unsigned int *)ip, op))
return -EPERM;
@@ -420,7 +421,7 @@ static int __ftrace_make_nop_kernel(struct dyn_ftrace *rec, unsigned long addr)
}
}
- if (patch_instruction((unsigned int *)ip, PPC_INST_NOP)) {
+ if (patch_instruction((unsigned int *)ip, ppc_inst(PPC_INST_NOP))) {
pr_err("Patching NOP failed.\n");
return -EPERM;
}
@@ -442,7 +443,7 @@ int ftrace_make_nop(struct module *mod,
if (test_24bit_addr(ip, addr)) {
/* within range */
old = ftrace_call_replace(ip, addr, 1);
- new = PPC_INST_NOP;
+ new = ppc_inst(PPC_INST_NOP);
return ftrace_modify_code(ip, old, new);
} else if (core_kernel_text(ip))
return __ftrace_make_nop_kernel(rec, addr);
@@ -496,7 +497,7 @@ expected_nop_sequence(void *ip, unsigned int op0, unsigned int op1)
* The load offset is different depending on the ABI. For simplicity
* just mask it out when doing the compare.
*/
- if ((op0 != 0x48000008) || ((op1 & 0xffff0000) != 0xe8410000))
+ if ((op0 != ppc_inst(0x48000008)) || ((op1 & 0xffff0000) != 0xe8410000))
return 0;
return 1;
}
@@ -505,7 +506,7 @@ static int
expected_nop_sequence(void *ip, unsigned int op0, unsigned int op1)
{
/* look for patched "NOP" on ppc64 with -mprofile-kernel */
- if (op0 != PPC_INST_NOP)
+ if (op0 != ppc_inst(PPC_INST_NOP))
return 0;
return 1;
}
@@ -588,7 +589,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
return -EFAULT;
/* It should be pointing to a nop */
- if (op != PPC_INST_NOP) {
+ if (op != ppc_inst(PPC_INST_NOP)) {
pr_err("Expected NOP but have %x\n", op);
return -EINVAL;
}
@@ -645,7 +646,7 @@ static int __ftrace_make_call_kernel(struct dyn_ftrace *rec, unsigned long addr)
return -EFAULT;
}
- if (op != PPC_INST_NOP) {
+ if (op != ppc_inst(PPC_INST_NOP)) {
pr_err("Unexpected call sequence at %p: %x\n", ip, op);
return -EINVAL;
}
@@ -676,7 +677,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
*/
if (test_24bit_addr(ip, addr)) {
/* within range */
- old = PPC_INST_NOP;
+ old = ppc_inst(PPC_INST_NOP);
new = ftrace_call_replace(ip, addr, 1);
return ftrace_modify_code(ip, old, new);
} else if (core_kernel_text(ip))
diff --git a/arch/powerpc/kernel/uprobes.c b/arch/powerpc/kernel/uprobes.c
index 1cfef0e5fec5..31c870287f2b 100644
--- a/arch/powerpc/kernel/uprobes.c
+++ b/arch/powerpc/kernel/uprobes.c
@@ -14,6 +14,7 @@
#include <linux/kdebug.h>
#include <asm/sstep.h>
+#include <asm/inst.h>
#define UPROBE_TRAP_NR UINT_MAX
diff --git a/arch/powerpc/kvm/emulate_loadstore.c b/arch/powerpc/kvm/emulate_loadstore.c
index 1139bc56e004..135d0e686622 100644
--- a/arch/powerpc/kvm/emulate_loadstore.c
+++ b/arch/powerpc/kvm/emulate_loadstore.c
@@ -95,7 +95,7 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu)
emulated = EMULATE_FAIL;
vcpu->arch.regs.msr = vcpu->arch.shared->msr;
- if (analyse_instr(&op, &vcpu->arch.regs, inst) == 0) {
+ if (analyse_instr(&op, &vcpu->arch.regs, ppc_inst(inst)) == 0) {
int type = op.type & INSTR_TYPE_MASK;
int size = GETSIZE(op.type);
diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index 4af564aeedf1..fdf0d6ea3575 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -17,6 +17,7 @@
#include <asm/page.h>
#include <asm/code-patching.h>
#include <asm/setup.h>
+#include <asm/inst.h>
static int __patch_instruction(unsigned int *exec_addr, unsigned int instr,
unsigned int *patch_addr)
@@ -413,37 +414,37 @@ static void __init test_branch_iform(void)
addr = (unsigned long)&instr;
/* The simplest case, branch to self, no flags */
- check(instr_is_branch_iform(0x48000000));
+ check(instr_is_branch_iform(ppc_inst(0x48000000)));
/* All bits of target set, and flags */
- check(instr_is_branch_iform(0x4bffffff));
+ check(instr_is_branch_iform(ppc_inst(0x4bffffff)));
/* High bit of opcode set, which is wrong */
- check(!instr_is_branch_iform(0xcbffffff));
+ check(!instr_is_branch_iform(ppc_inst(0xcbffffff)));
/* Middle bits of opcode set, which is wrong */
- check(!instr_is_branch_iform(0x7bffffff));
+ check(!instr_is_branch_iform(ppc_inst(0x7bffffff)));
/* Simplest case, branch to self with link */
- check(instr_is_branch_iform(0x48000001));
+ check(instr_is_branch_iform(ppc_inst(0x48000001)));
/* All bits of targets set */
- check(instr_is_branch_iform(0x4bfffffd));
+ check(instr_is_branch_iform(ppc_inst(0x4bfffffd)));
/* Some bits of targets set */
- check(instr_is_branch_iform(0x4bff00fd));
+ check(instr_is_branch_iform(ppc_inst(0x4bff00fd)));
/* Must be a valid branch to start with */
- check(!instr_is_branch_iform(0x7bfffffd));
+ check(!instr_is_branch_iform(ppc_inst(0x7bfffffd)));
/* Absolute branch to 0x100 */
- instr = 0x48000103;
+ instr = ppc_inst(0x48000103);
check(instr_is_branch_to_addr(&instr, 0x100));
/* Absolute branch to 0x420fc */
- instr = 0x480420ff;
+ instr = ppc_inst(0x480420ff);
check(instr_is_branch_to_addr(&instr, 0x420fc));
/* Maximum positive relative branch, + 20MB - 4B */
- instr = 0x49fffffc;
+ instr = ppc_inst(0x49fffffc);
check(instr_is_branch_to_addr(&instr, addr + 0x1FFFFFC));
/* Smallest negative relative branch, - 4B */
- instr = 0x4bfffffc;
+ instr = ppc_inst(0x4bfffffc);
check(instr_is_branch_to_addr(&instr, addr - 4));
/* Largest negative relative branch, - 32 MB */
- instr = 0x4a000000;
+ instr = ppc_inst(0x4a000000);
check(instr_is_branch_to_addr(&instr, addr - 0x2000000));
/* Branch to self, with link */
@@ -477,7 +478,7 @@ static void __init test_branch_iform(void)
/* Check flags are masked correctly */
err = create_branch(&instr, &instr, addr, 0xFFFFFFFC);
check(instr_is_branch_to_addr(&instr, addr));
- check(instr == 0x48000000);
+ check(instr == ppc_inst(0x48000000));
}
static void __init test_create_function_call(void)
@@ -504,28 +505,28 @@ static void __init test_branch_bform(void)
addr = (unsigned long)iptr;
/* The simplest case, branch to self, no flags */
- check(instr_is_branch_bform(0x40000000));
+ check(instr_is_branch_bform(ppc_inst(0x40000000)));
/* All bits of target set, and flags */
- check(instr_is_branch_bform(0x43ffffff));
+ check(instr_is_branch_bform(ppc_inst(0x43ffffff)));
/* High bit of opcode set, which is wrong */
- check(!instr_is_branch_bform(0xc3ffffff));
+ check(!instr_is_branch_bform(ppc_inst(0xc3ffffff)));
/* Middle bits of opcode set, which is wrong */
- check(!instr_is_branch_bform(0x7bffffff));
+ check(!instr_is_branch_bform(ppc_inst(0x7bffffff)));
/* Absolute conditional branch to 0x100 */
- instr = 0x43ff0103;
+ instr = ppc_inst(0x43ff0103);
check(instr_is_branch_to_addr(&instr, 0x100));
/* Absolute conditional branch to 0x20fc */
- instr = 0x43ff20ff;
+ instr = ppc_inst(0x43ff20ff);
check(instr_is_branch_to_addr(&instr, 0x20fc));
/* Maximum positive relative conditional branch, + 32 KB - 4B */
- instr = 0x43ff7ffc;
+ instr = ppc_inst(0x43ff7ffc);
check(instr_is_branch_to_addr(&instr, addr + 0x7FFC));
/* Smallest negative relative conditional branch, - 4B */
- instr = 0x43fffffc;
+ instr = ppc_inst(0x43fffffc);
check(instr_is_branch_to_addr(&instr, addr - 4));
/* Largest negative relative conditional branch, - 32 KB */
- instr = 0x43ff8000;
+ instr = ppc_inst(0x43ff8000);
check(instr_is_branch_to_addr(&instr, addr - 0x8000));
/* All condition code bits set & link */
@@ -562,7 +563,7 @@ static void __init test_branch_bform(void)
/* Check flags are masked correctly */
err = create_cond_branch(&instr, iptr, addr, 0xFFFFFFFC);
check(instr_is_branch_to_addr(&instr, addr));
- check(instr == 0x43FF0000);
+ check(instr == ppc_inst(0x43FF0000));
}
static void __init test_translate_branch(void)
@@ -596,7 +597,7 @@ static void __init test_translate_branch(void)
patch_instruction(q, instr);
check(instr_is_branch_to_addr(p, addr));
check(instr_is_branch_to_addr(q, addr));
- check(*q == 0x4a000000);
+ check(*q == ppc_inst(0x4a000000));
/* Maximum positive case, move x to x - 32 MB + 4 */
p = buf + 0x2000000;
@@ -607,7 +608,7 @@ static void __init test_translate_branch(void)
patch_instruction(q, instr);
check(instr_is_branch_to_addr(p, addr));
check(instr_is_branch_to_addr(q, addr));
- check(*q == 0x49fffffc);
+ check(*q == ppc_inst(0x49fffffc));
/* Jump to x + 16 MB moved to x + 20 MB */
p = buf;
@@ -653,7 +654,7 @@ static void __init test_translate_branch(void)
patch_instruction(q, instr);
check(instr_is_branch_to_addr(p, addr));
check(instr_is_branch_to_addr(q, addr));
- check(*q == 0x43ff8000);
+ check(*q == ppc_inst(0x43ff8000));
/* Maximum positive case, move x to x - 32 KB + 4 */
p = buf + 0x8000;
@@ -665,7 +666,7 @@ static void __init test_translate_branch(void)
patch_instruction(q, instr);
check(instr_is_branch_to_addr(p, addr));
check(instr_is_branch_to_addr(q, addr));
- check(*q == 0x43ff7ffc);
+ check(*q == ppc_inst(0x43ff7ffc));
/* Jump to x + 12 KB moved to x + 20 KB */
p = buf;
diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c
index b129d7b4e7dd..6e7479b8887a 100644
--- a/arch/powerpc/lib/feature-fixups.c
+++ b/arch/powerpc/lib/feature-fixups.c
@@ -21,6 +21,7 @@
#include <asm/setup.h>
#include <asm/security_features.h>
#include <asm/firmware.h>
+#include <asm/inst.h>
struct fixup_entry {
unsigned long mask;
@@ -89,7 +90,7 @@ static int patch_feature_section(unsigned long value, struct fixup_entry *fcur)
}
for (; dest < end; dest++)
- raw_patch_instruction(dest, PPC_INST_NOP);
+ raw_patch_instruction(dest, ppc_inst(PPC_INST_NOP));
return 0;
}
@@ -146,15 +147,15 @@ static void do_stf_entry_barrier_fixups(enum stf_barrier_type types)
pr_devel("patching dest %lx\n", (unsigned long)dest);
- patch_instruction(dest, instrs[0]);
+ patch_instruction(dest, ppc_inst(instrs[0]));
if (types & STF_BARRIER_FALLBACK)
patch_branch(dest + 1, (unsigned long)&stf_barrier_fallback,
BRANCH_SET_LINK);
else
- patch_instruction(dest + 1, instrs[1]);
+ patch_instruction(dest + 1, ppc_inst(instrs[1]));
- patch_instruction(dest + 2, instrs[2]);
+ patch_instruction(dest + 2, ppc_inst(instrs[2]));
}
printk(KERN_DEBUG "stf-barrier: patched %d entry locations (%s barrier)\n", i,
@@ -207,12 +208,12 @@ static void do_stf_exit_barrier_fixups(enum stf_barrier_type types)
pr_devel("patching dest %lx\n", (unsigned long)dest);
- patch_instruction(dest, instrs[0]);
- patch_instruction(dest + 1, instrs[1]);
- patch_instruction(dest + 2, instrs[2]);
- patch_instruction(dest + 3, instrs[3]);
- patch_instruction(dest + 4, instrs[4]);
- patch_instruction(dest + 5, instrs[5]);
+ patch_instruction(dest, ppc_inst(instrs[0]));
+ patch_instruction(dest + 1, ppc_inst(instrs[1]));
+ patch_instruction(dest + 2, ppc_inst(instrs[2]));
+ patch_instruction(dest + 3, ppc_inst(instrs[3]));
+ patch_instruction(dest + 4, ppc_inst(instrs[4]));
+ patch_instruction(dest + 5, ppc_inst(instrs[5]));
}
printk(KERN_DEBUG "stf-barrier: patched %d exit locations (%s barrier)\n", i,
(types == STF_BARRIER_NONE) ? "no" :
@@ -260,9 +261,9 @@ void do_rfi_flush_fixups(enum l1d_flush_type types)
pr_devel("patching dest %lx\n", (unsigned long)dest);
- patch_instruction(dest, instrs[0]);
- patch_instruction(dest + 1, instrs[1]);
- patch_instruction(dest + 2, instrs[2]);
+ patch_instruction(dest, ppc_inst(instrs[0]));
+ patch_instruction(dest + 1, ppc_inst(instrs[1]));
+ patch_instruction(dest + 2, ppc_inst(instrs[2]));
}
printk(KERN_DEBUG "rfi-flush: patched %d locations (%s flush)\n", i,
@@ -295,7 +296,7 @@ void do_barrier_nospec_fixups_range(bool enable, void *fixup_start, void *fixup_
dest = (void *)start + *start;
pr_devel("patching dest %lx\n", (unsigned long)dest);
- patch_instruction(dest, instr);
+ patch_instruction(dest, ppc_inst(instr));
}
printk(KERN_DEBUG "barrier-nospec: patched %d locations\n", i);
@@ -338,8 +339,8 @@ void do_barrier_nospec_fixups_range(bool enable, void *fixup_start, void *fixup_
dest = (void *)start + *start;
pr_devel("patching dest %lx\n", (unsigned long)dest);
- patch_instruction(dest, instr[0]);
- patch_instruction(dest + 1, instr[1]);
+ patch_instruction(dest, ppc_inst(instr[0]));
+ patch_instruction(dest + 1, ppc_inst(instr[1]));
}
printk(KERN_DEBUG "barrier-nospec: patched %d locations\n", i);
@@ -353,7 +354,7 @@ static void patch_btb_flush_section(long *curr)
end = (void *)curr + *(curr + 1);
for (; start < end; start++) {
pr_devel("patching dest %lx\n", (unsigned long)start);
- patch_instruction(start, PPC_INST_NOP);
+ patch_instruction(start, ppc_inst(PPC_INST_NOP));
}
}
@@ -382,7 +383,7 @@ void do_lwsync_fixups(unsigned long value, void *fixup_start, void *fixup_end)
for (; start < end; start++) {
dest = (void *)start + *start;
- raw_patch_instruction(dest, PPC_INST_LWSYNC);
+ raw_patch_instruction(dest, ppc_inst(PPC_INST_LWSYNC));
}
}
@@ -400,7 +401,7 @@ static void do_final_fixups(void)
length = (__end_interrupts - _stext) / sizeof(int);
while (length--) {
- raw_patch_instruction(dest, *src);
+ raw_patch_instruction(dest, ppc_inst(*src));
src++;
dest++;
}
diff --git a/arch/powerpc/lib/test_emulate_step.c b/arch/powerpc/lib/test_emulate_step.c
index 42347067739c..88b17226a493 100644
--- a/arch/powerpc/lib/test_emulate_step.c
+++ b/arch/powerpc/lib/test_emulate_step.c
@@ -11,6 +11,7 @@
#include <asm/sstep.h>
#include <asm/ppc-opcode.h>
#include <asm/code-patching.h>
+#include <asm/inst.h>
#define IMM_L(i) ((uintptr_t)(i) & 0xffff)
@@ -18,40 +19,40 @@
* Defined with TEST_ prefix so it does not conflict with other
* definitions.
*/
-#define TEST_LD(r, base, i) (PPC_INST_LD | ___PPC_RT(r) | \
+#define TEST_LD(r, base, i) ppc_inst(PPC_INST_LD | ___PPC_RT(r) | \
___PPC_RA(base) | IMM_L(i))
-#define TEST_LWZ(r, base, i) (PPC_INST_LWZ | ___PPC_RT(r) | \
+#define TEST_LWZ(r, base, i) ppc_inst(PPC_INST_LWZ | ___PPC_RT(r) | \
___PPC_RA(base) | IMM_L(i))
-#define TEST_LWZX(t, a, b) (PPC_INST_LWZX | ___PPC_RT(t) | \
+#define TEST_LWZX(t, a, b) ppc_inst(PPC_INST_LWZX | ___PPC_RT(t) | \
___PPC_RA(a) | ___PPC_RB(b))
-#define TEST_STD(r, base, i) (PPC_INST_STD | ___PPC_RS(r) | \
+#define TEST_STD(r, base, i) ppc_inst(PPC_INST_STD | ___PPC_RS(r) | \
___PPC_RA(base) | ((i) & 0xfffc))
-#define TEST_LDARX(t, a, b, eh) (PPC_INST_LDARX | ___PPC_RT(t) | \
+#define TEST_LDARX(t, a, b, eh) ppc_inst(PPC_INST_LDARX | ___PPC_RT(t) | \
___PPC_RA(a) | ___PPC_RB(b) | \
__PPC_EH(eh))
-#define TEST_STDCX(s, a, b) (PPC_INST_STDCX | ___PPC_RS(s) | \
+#define TEST_STDCX(s, a, b) ppc_inst(PPC_INST_STDCX | ___PPC_RS(s) | \
___PPC_RA(a) | ___PPC_RB(b))
-#define TEST_LFSX(t, a, b) (PPC_INST_LFSX | ___PPC_RT(t) | \
+#define TEST_LFSX(t, a, b) ppc_inst(PPC_INST_LFSX | ___PPC_RT(t) | \
___PPC_RA(a) | ___PPC_RB(b))
-#define TEST_STFSX(s, a, b) (PPC_INST_STFSX | ___PPC_RS(s) | \
+#define TEST_STFSX(s, a, b) ppc_inst(PPC_INST_STFSX | ___PPC_RS(s) | \
___PPC_RA(a) | ___PPC_RB(b))
-#define TEST_LFDX(t, a, b) (PPC_INST_LFDX | ___PPC_RT(t) | \
+#define TEST_LFDX(t, a, b) ppc_inst(PPC_INST_LFDX | ___PPC_RT(t) | \
___PPC_RA(a) | ___PPC_RB(b))
-#define TEST_STFDX(s, a, b) (PPC_INST_STFDX | ___PPC_RS(s) | \
+#define TEST_STFDX(s, a, b) ppc_inst(PPC_INST_STFDX | ___PPC_RS(s) | \
___PPC_RA(a) | ___PPC_RB(b))
-#define TEST_LVX(t, a, b) (PPC_INST_LVX | ___PPC_RT(t) | \
+#define TEST_LVX(t, a, b) ppc_inst(PPC_INST_LVX | ___PPC_RT(t) | \
___PPC_RA(a) | ___PPC_RB(b))
-#define TEST_STVX(s, a, b) (PPC_INST_STVX | ___PPC_RS(s) | \
+#define TEST_STVX(s, a, b) ppc_inst(PPC_INST_STVX | ___PPC_RS(s) | \
___PPC_RA(a) | ___PPC_RB(b))
-#define TEST_LXVD2X(s, a, b) (PPC_INST_LXVD2X | VSX_XX1((s), R##a, R##b))
-#define TEST_STXVD2X(s, a, b) (PPC_INST_STXVD2X | VSX_XX1((s), R##a, R##b))
-#define TEST_ADD(t, a, b) (PPC_INST_ADD | ___PPC_RT(t) | \
+#define TEST_LXVD2X(s, a, b) ppc_inst(PPC_INST_LXVD2X | VSX_XX1((s), R##a, R##b))
+#define TEST_STXVD2X(s, a, b) ppc_inst(PPC_INST_STXVD2X | VSX_XX1((s), R##a, R##b))
+#define TEST_ADD(t, a, b) ppc_inst(PPC_INST_ADD | ___PPC_RT(t) | \
___PPC_RA(a) | ___PPC_RB(b))
-#define TEST_ADD_DOT(t, a, b) (PPC_INST_ADD | ___PPC_RT(t) | \
+#define TEST_ADD_DOT(t, a, b) ppc_inst(PPC_INST_ADD | ___PPC_RT(t) | \
___PPC_RA(a) | ___PPC_RB(b) | 0x1)
-#define TEST_ADDC(t, a, b) (PPC_INST_ADDC | ___PPC_RT(t) | \
+#define TEST_ADDC(t, a, b) ppc_inst(PPC_INST_ADDC | ___PPC_RT(t) | \
___PPC_RA(a) | ___PPC_RB(b))
-#define TEST_ADDC_DOT(t, a, b) (PPC_INST_ADDC | ___PPC_RT(t) | \
+#define TEST_ADDC_DOT(t, a, b) ppc_inst(PPC_INST_ADDC | ___PPC_RT(t) | \
___PPC_RA(a) | ___PPC_RB(b) | 0x1)
#define MAX_SUBTESTS 16
@@ -471,7 +472,7 @@ static struct compute_test compute_tests[] = {
.subtests = {
{
.descr = "R0 = LONG_MAX",
- .instr = PPC_INST_NOP,
+ .instr = ppc_inst(PPC_INST_NOP),
.regs = {
.gpr[0] = LONG_MAX,
}
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 049375206510..68ecb39dd9cc 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -54,6 +54,7 @@
#include <asm/firmware.h>
#include <asm/code-patching.h>
#include <asm/sections.h>
+#include <asm/inst.h>
#ifdef CONFIG_PPC64
#include <asm/hvcall.h>
@@ -949,7 +950,7 @@ static void remove_bpts(void)
if ((bp->enabled & (BP_TRAP|BP_CIABR)) != BP_TRAP)
continue;
if (mread(bp->address, &instr, 4) == 4
- && instr == bpinstr
+ && instr == ppc_inst(bpinstr)
&& patch_instruction(
(unsigned int *)bp->address, bp->instr[0]) != 0)
printf("Couldn't remove breakpoint at %lx\n",
@@ -2845,7 +2846,7 @@ generic_inst_dump(unsigned long adr, long count, int praddr,
{
int nr, dotted;
unsigned long first_adr;
- unsigned int inst, last_inst = 0;
+ unsigned int inst, last_inst = ppc_inst(0);
unsigned char val[4];
dotted = 0;
@@ -2858,7 +2859,7 @@ generic_inst_dump(unsigned long adr, long count, int praddr,
}
break;
}
- inst = GETWORD(val);
+ inst = ppc_inst(GETWORD(val));
if (adr > first_adr && inst == last_inst) {
if (!dotted) {
printf(" ...\n");
--
2.17.1
^ permalink raw reply related [flat|nested] 71+ messages in thread
* [PATCH v5 05/21] powerpc: Use a function for getting the instruction op code
2020-04-06 8:09 [PATCH v5 00/21] Initial Prefixed Instruction support Jordan Niethe
` (3 preceding siblings ...)
2020-04-06 8:09 ` [PATCH v5 04/21] powerpc: Use a macro for creating instructions from u32s Jordan Niethe
@ 2020-04-06 8:09 ` Jordan Niethe
2020-04-06 8:22 ` Christophe Leroy
` (2 more replies)
2020-04-06 8:09 ` [PATCH v5 06/21] powerpc: Use an accessor for instructions Jordan Niethe
` (16 subsequent siblings)
21 siblings, 3 replies; 71+ messages in thread
From: Jordan Niethe @ 2020-04-06 8:09 UTC (permalink / raw)
To: linuxppc-dev; +Cc: alistair, npiggin, bala24, Jordan Niethe, dja
In preparation for using a data type for instructions that can not be
directly used with the '>>' operator use a function for getting the op
code of an instruction.
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v4: New to series
---
arch/powerpc/include/asm/inst.h | 5 +++++
arch/powerpc/kernel/align.c | 2 +-
arch/powerpc/lib/code-patching.c | 4 ++--
3 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h
index 5298ba33b6e5..93959016fe4b 100644
--- a/arch/powerpc/include/asm/inst.h
+++ b/arch/powerpc/include/asm/inst.h
@@ -8,4 +8,9 @@
#define ppc_inst(x) (x)
+static inline int ppc_inst_opcode(u32 x)
+{
+ return x >> 26;
+}
+
#endif /* _ASM_INST_H */
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
index 86e9bf62f18c..691013aa9f3c 100644
--- a/arch/powerpc/kernel/align.c
+++ b/arch/powerpc/kernel/align.c
@@ -314,7 +314,7 @@ int fix_alignment(struct pt_regs *regs)
}
#ifdef CONFIG_SPE
- if ((instr >> 26) == 0x4) {
+ if (ppc_inst_opcode(instr) == 0x4) {
int reg = (instr >> 21) & 0x1f;
PPC_WARN_ALIGNMENT(spe, regs);
return emulate_spe(regs, reg, instr);
diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index fdf0d6ea3575..099a515202aa 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -231,7 +231,7 @@ bool is_offset_in_branch_range(long offset)
*/
bool is_conditional_branch(unsigned int instr)
{
- unsigned int opcode = instr >> 26;
+ unsigned int opcode = ppc_inst_opcode(instr);
if (opcode == 16) /* bc, bca, bcl, bcla */
return true;
@@ -289,7 +289,7 @@ int create_cond_branch(unsigned int *instr, const unsigned int *addr,
static unsigned int branch_opcode(unsigned int instr)
{
- return (instr >> 26) & 0x3F;
+ return ppc_inst_opcode(instr) & 0x3F;
}
static int instr_is_branch_iform(unsigned int instr)
--
2.17.1
^ permalink raw reply related [flat|nested] 71+ messages in thread
* [PATCH v5 06/21] powerpc: Use an accessor for instructions
2020-04-06 8:09 [PATCH v5 00/21] Initial Prefixed Instruction support Jordan Niethe
` (4 preceding siblings ...)
2020-04-06 8:09 ` [PATCH v5 05/21] powerpc: Use a function for getting the instruction op code Jordan Niethe
@ 2020-04-06 8:09 ` Jordan Niethe
2020-04-06 8:09 ` [PATCH v5 07/21] powerpc: Use a function for byte swapping instructions Jordan Niethe
` (15 subsequent siblings)
21 siblings, 0 replies; 71+ messages in thread
From: Jordan Niethe @ 2020-04-06 8:09 UTC (permalink / raw)
To: linuxppc-dev; +Cc: alistair, npiggin, bala24, Jordan Niethe, dja
In preparation for introducing a more complicated instruction type to
accomodate prefixed instructions use an accessor for getting an
instruction as a u32. Currently this does nothing.
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v4: New to series
v5: Remove references to 'word' instructions
---
arch/powerpc/include/asm/inst.h | 5 +
arch/powerpc/include/asm/sstep.h | 6 +-
arch/powerpc/kernel/align.c | 4 +-
arch/powerpc/kernel/kprobes.c | 2 +-
arch/powerpc/kernel/trace/ftrace.c | 22 +--
arch/powerpc/kernel/vecemu.c | 17 +-
arch/powerpc/lib/code-patching.c | 18 +-
arch/powerpc/lib/sstep.c | 270 ++++++++++++++-------------
arch/powerpc/lib/test_emulate_step.c | 6 +-
arch/powerpc/xmon/xmon.c | 4 +-
10 files changed, 182 insertions(+), 172 deletions(-)
diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h
index 93959016fe4b..15f570bef936 100644
--- a/arch/powerpc/include/asm/inst.h
+++ b/arch/powerpc/include/asm/inst.h
@@ -8,6 +8,11 @@
#define ppc_inst(x) (x)
+static inline u32 ppc_inst_val(u32 x)
+{
+ return x;
+}
+
static inline int ppc_inst_opcode(u32 x)
{
return x >> 26;
diff --git a/arch/powerpc/include/asm/sstep.h b/arch/powerpc/include/asm/sstep.h
index 769f055509c9..26d729562fe2 100644
--- a/arch/powerpc/include/asm/sstep.h
+++ b/arch/powerpc/include/asm/sstep.h
@@ -15,9 +15,9 @@ struct pt_regs;
* Note that IS_MTMSRD returns true for both an mtmsr (32-bit)
* and an mtmsrd (64-bit).
*/
-#define IS_MTMSRD(instr) (((instr) & 0xfc0007be) == 0x7c000124)
-#define IS_RFID(instr) (((instr) & 0xfc0007fe) == 0x4c000024)
-#define IS_RFI(instr) (((instr) & 0xfc0007fe) == 0x4c000064)
+#define IS_MTMSRD(instr) ((ppc_inst_val(instr) & 0xfc0007be) == 0x7c000124)
+#define IS_RFID(instr) ((ppc_inst_val(instr) & 0xfc0007fe) == 0x4c000024)
+#define IS_RFI(instr) ((ppc_inst_val(instr) & 0xfc0007fe) == 0x4c000064)
enum instruction_type {
COMPUTE, /* arith/logical/CR op, etc. */
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
index 691013aa9f3c..a83d32c6513d 100644
--- a/arch/powerpc/kernel/align.c
+++ b/arch/powerpc/kernel/align.c
@@ -315,7 +315,7 @@ int fix_alignment(struct pt_regs *regs)
#ifdef CONFIG_SPE
if (ppc_inst_opcode(instr) == 0x4) {
- int reg = (instr >> 21) & 0x1f;
+ int reg = (ppc_inst_val(instr) >> 21) & 0x1f;
PPC_WARN_ALIGNMENT(spe, regs);
return emulate_spe(regs, reg, instr);
}
@@ -332,7 +332,7 @@ int fix_alignment(struct pt_regs *regs)
* when pasting to a co-processor. Furthermore, paste_last is the
* synchronisation point for preceding copy/paste sequences.
*/
- if ((instr & 0xfc0006fe) == (PPC_INST_COPY & 0xfc0006fe))
+ if ((ppc_inst_val(instr) & 0xfc0006fe) == (PPC_INST_COPY & 0xfc0006fe))
return -EIO;
r = analyse_instr(&op, regs, instr);
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index a1a3686f41c6..8420b1944164 100644
--- a/arch/powerpc/kernel/kprobes.c
+++ b/arch/powerpc/kernel/kprobes.c
@@ -234,7 +234,7 @@ static int try_to_emulate(struct kprobe *p, struct pt_regs *regs)
* So, we should never get here... but, its still
* good to catch them, just in case...
*/
- printk("Can't step on instruction %x\n", insn);
+ printk("Can't step on instruction %x\n", ppc_inst_val(insn));
BUG();
} else {
/*
diff --git a/arch/powerpc/kernel/trace/ftrace.c b/arch/powerpc/kernel/trace/ftrace.c
index 47233e671c18..62ff429bddc4 100644
--- a/arch/powerpc/kernel/trace/ftrace.c
+++ b/arch/powerpc/kernel/trace/ftrace.c
@@ -74,7 +74,7 @@ ftrace_modify_code(unsigned long ip, unsigned int old, unsigned int new)
/* Make sure it is what we expect it to be */
if (replaced != old) {
pr_err("%p: replaced (%#x) != old (%#x)",
- (void *)ip, replaced, old);
+ (void *)ip, ppc_inst_val(replaced), ppc_inst_val(old));
return -EINVAL;
}
@@ -99,19 +99,19 @@ static int test_24bit_addr(unsigned long ip, unsigned long addr)
static int is_bl_op(unsigned int op)
{
- return (op & 0xfc000003) == 0x48000001;
+ return (ppc_inst_val(op) & 0xfc000003) == 0x48000001;
}
static int is_b_op(unsigned int op)
{
- return (op & 0xfc000003) == 0x48000000;
+ return (ppc_inst_val(op) & 0xfc000003) == 0x48000000;
}
static unsigned long find_bl_target(unsigned long ip, unsigned int op)
{
int offset;
- offset = (op & 0x03fffffc);
+ offset = (ppc_inst_val(op) & 0x03fffffc);
/* make it signed */
if (offset & 0x02000000)
offset |= 0xfe000000;
@@ -137,7 +137,7 @@ __ftrace_make_nop(struct module *mod,
/* Make sure that that this is still a 24bit jump */
if (!is_bl_op(op)) {
- pr_err("Not expected bl: opcode is %x\n", op);
+ pr_err("Not expected bl: opcode is %x\n", ppc_inst_val(op));
return -EINVAL;
}
@@ -171,7 +171,7 @@ __ftrace_make_nop(struct module *mod,
/* We expect either a mflr r0, or a std r0, LRSAVE(r1) */
if (op != ppc_inst(PPC_INST_MFLR) && op != ppc_inst(PPC_INST_STD_LR)) {
- pr_err("Unexpected instruction %08x around bl _mcount\n", op);
+ pr_err("Unexpected instruction %08x around bl _mcount\n", ppc_inst_val(op));
return -EINVAL;
}
#else
@@ -201,7 +201,7 @@ __ftrace_make_nop(struct module *mod,
}
if (op != ppc_inst(PPC_INST_LD_TOC)) {
- pr_err("Expected %08x found %08x\n", PPC_INST_LD_TOC, op);
+ pr_err("Expected %08x found %08x\n", PPC_INST_LD_TOC, ppc_inst_val(op));
return -EINVAL;
}
#endif /* CONFIG_MPROFILE_KERNEL */
@@ -403,7 +403,7 @@ static int __ftrace_make_nop_kernel(struct dyn_ftrace *rec, unsigned long addr)
/* Make sure that that this is still a 24bit jump */
if (!is_bl_op(op)) {
- pr_err("Not expected bl: opcode is %x\n", op);
+ pr_err("Not expected bl: opcode is %x\n", ppc_inst_val(op));
return -EINVAL;
}
@@ -497,7 +497,7 @@ expected_nop_sequence(void *ip, unsigned int op0, unsigned int op1)
* The load offset is different depending on the ABI. For simplicity
* just mask it out when doing the compare.
*/
- if ((op0 != ppc_inst(0x48000008)) || ((op1 & 0xffff0000) != 0xe8410000))
+ if ((op0 != ppc_inst(0x48000008)) || (ppc_inst_val(op1) & 0xffff0000) != 0xe8410000)
return 0;
return 1;
}
@@ -647,7 +647,7 @@ static int __ftrace_make_call_kernel(struct dyn_ftrace *rec, unsigned long addr)
}
if (op != ppc_inst(PPC_INST_NOP)) {
- pr_err("Unexpected call sequence at %p: %x\n", ip, op);
+ pr_err("Unexpected call sequence at %p: %x\n", ip, ppc_inst_val(op));
return -EINVAL;
}
@@ -726,7 +726,7 @@ __ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
/* Make sure that that this is still a 24bit jump */
if (!is_bl_op(op)) {
- pr_err("Not expected bl: opcode is %x\n", op);
+ pr_err("Not expected bl: opcode is %x\n", ppc_inst_val(op));
return -EINVAL;
}
diff --git a/arch/powerpc/kernel/vecemu.c b/arch/powerpc/kernel/vecemu.c
index 4acd3fb2b38e..c8d21e812d8c 100644
--- a/arch/powerpc/kernel/vecemu.c
+++ b/arch/powerpc/kernel/vecemu.c
@@ -10,6 +10,7 @@
#include <asm/processor.h>
#include <asm/switch_to.h>
#include <linux/uaccess.h>
+#include <asm/inst.h>
/* Functions in vector.S */
extern void vaddfp(vector128 *dst, vector128 *a, vector128 *b);
@@ -260,21 +261,23 @@ static unsigned int rfin(unsigned int x)
int emulate_altivec(struct pt_regs *regs)
{
- unsigned int instr, i;
+ unsigned int instr, i, word;
unsigned int va, vb, vc, vd;
vector128 *vrs;
if (get_user(instr, (unsigned int __user *) regs->nip))
return -EFAULT;
- if ((instr >> 26) != 4)
+
+ word = ppc_inst_val(instr);
+ if ((word >> 26) != 4)
return -EINVAL; /* not an altivec instruction */
- vd = (instr >> 21) & 0x1f;
- va = (instr >> 16) & 0x1f;
- vb = (instr >> 11) & 0x1f;
- vc = (instr >> 6) & 0x1f;
+ vd = (word >> 21) & 0x1f;
+ va = (word >> 16) & 0x1f;
+ vb = (word >> 11) & 0x1f;
+ vc = (word >> 6) & 0x1f;
vrs = current->thread.vr_state.vr;
- switch (instr & 0x3f) {
+ switch (word & 0x3f) {
case 10:
switch (vc) {
case 0: /* vaddfp */
diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index 099a515202aa..3f88d2a4400c 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -236,7 +236,7 @@ bool is_conditional_branch(unsigned int instr)
if (opcode == 16) /* bc, bca, bcl, bcla */
return true;
if (opcode == 19) {
- switch ((instr >> 1) & 0x3ff) {
+ switch ((ppc_inst_val(instr) >> 1) & 0x3ff) {
case 16: /* bclr, bclrl */
case 528: /* bcctr, bcctrl */
case 560: /* bctar, bctarl */
@@ -304,7 +304,7 @@ static int instr_is_branch_bform(unsigned int instr)
int instr_is_relative_branch(unsigned int instr)
{
- if (instr & BRANCH_ABSOLUTE)
+ if (ppc_inst_val(instr) & BRANCH_ABSOLUTE)
return 0;
return instr_is_branch_iform(instr) || instr_is_branch_bform(instr);
@@ -312,20 +312,20 @@ int instr_is_relative_branch(unsigned int instr)
int instr_is_relative_link_branch(unsigned int instr)
{
- return instr_is_relative_branch(instr) && (instr & BRANCH_SET_LINK);
+ return instr_is_relative_branch(instr) && (ppc_inst_val(instr) & BRANCH_SET_LINK);
}
static unsigned long branch_iform_target(const unsigned int *instr)
{
signed long imm;
- imm = *instr & 0x3FFFFFC;
+ imm = ppc_inst_val(*instr) & 0x3FFFFFC;
/* If the top bit of the immediate value is set this is negative */
if (imm & 0x2000000)
imm -= 0x4000000;
- if ((*instr & BRANCH_ABSOLUTE) == 0)
+ if ((ppc_inst_val(*instr) & BRANCH_ABSOLUTE) == 0)
imm += (unsigned long)instr;
return (unsigned long)imm;
@@ -335,13 +335,13 @@ static unsigned long branch_bform_target(const unsigned int *instr)
{
signed long imm;
- imm = *instr & 0xFFFC;
+ imm = ppc_inst_val(*instr) & 0xFFFC;
/* If the top bit of the immediate value is set this is negative */
if (imm & 0x8000)
imm -= 0x10000;
- if ((*instr & BRANCH_ABSOLUTE) == 0)
+ if ((ppc_inst_val(*instr) & BRANCH_ABSOLUTE) == 0)
imm += (unsigned long)instr;
return (unsigned long)imm;
@@ -372,9 +372,9 @@ int translate_branch(unsigned int *instr, const unsigned int *dest, const unsign
target = branch_target(src);
if (instr_is_branch_iform(*src))
- return create_branch(instr, dest, target, *src);
+ return create_branch(instr, dest, target, ppc_inst_val(*src));
else if (instr_is_branch_bform(*src))
- return create_cond_branch(instr, dest, target, *src);
+ return create_cond_branch(instr, dest, target, ppc_inst_val(*src));
return 1;
}
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index c077acb983a1..26e37176692e 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -1169,26 +1169,28 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
unsigned long int imm;
unsigned long int val, val2;
unsigned int mb, me, sh;
+ unsigned int word;
long ival;
+ word = ppc_inst_val(instr);
op->type = COMPUTE;
- opcode = instr >> 26;
+ opcode = word >> 26;
switch (opcode) {
case 16: /* bc */
op->type = BRANCH;
- imm = (signed short)(instr & 0xfffc);
- if ((instr & 2) == 0)
+ imm = (signed short)(word & 0xfffc);
+ if ((word & 2) == 0)
imm += regs->nip;
op->val = truncate_if_32bit(regs->msr, imm);
- if (instr & 1)
+ if (word & 1)
op->type |= SETLK;
- if (branch_taken(instr, regs, op))
+ if (branch_taken(word, regs, op))
op->type |= BRTAKEN;
return 1;
#ifdef CONFIG_PPC64
case 17: /* sc */
- if ((instr & 0xfe2) == 2)
+ if ((word & 0xfe2) == 2)
op->type = SYSCALL;
else
op->type = UNKNOWN;
@@ -1196,21 +1198,21 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
#endif
case 18: /* b */
op->type = BRANCH | BRTAKEN;
- imm = instr & 0x03fffffc;
+ imm = word & 0x03fffffc;
if (imm & 0x02000000)
imm -= 0x04000000;
- if ((instr & 2) == 0)
+ if ((word & 2) == 0)
imm += regs->nip;
op->val = truncate_if_32bit(regs->msr, imm);
- if (instr & 1)
+ if (word & 1)
op->type |= SETLK;
return 1;
case 19:
- switch ((instr >> 1) & 0x3ff) {
+ switch ((word >> 1) & 0x3ff) {
case 0: /* mcrf */
op->type = COMPUTE + SETCC;
- rd = 7 - ((instr >> 23) & 0x7);
- ra = 7 - ((instr >> 18) & 0x7);
+ rd = 7 - ((word >> 23) & 0x7);
+ ra = 7 - ((word >> 18) & 0x7);
rd *= 4;
ra *= 4;
val = (regs->ccr >> ra) & 0xf;
@@ -1220,11 +1222,11 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
case 16: /* bclr */
case 528: /* bcctr */
op->type = BRANCH;
- imm = (instr & 0x400)? regs->ctr: regs->link;
+ imm = (word & 0x400)? regs->ctr: regs->link;
op->val = truncate_if_32bit(regs->msr, imm);
- if (instr & 1)
+ if (word & 1)
op->type |= SETLK;
- if (branch_taken(instr, regs, op))
+ if (branch_taken(word, regs, op))
op->type |= BRTAKEN;
return 1;
@@ -1247,23 +1249,23 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
case 417: /* crorc */
case 449: /* cror */
op->type = COMPUTE + SETCC;
- ra = (instr >> 16) & 0x1f;
- rb = (instr >> 11) & 0x1f;
- rd = (instr >> 21) & 0x1f;
+ ra = (word >> 16) & 0x1f;
+ rb = (word >> 11) & 0x1f;
+ rd = (word >> 21) & 0x1f;
ra = (regs->ccr >> (31 - ra)) & 1;
rb = (regs->ccr >> (31 - rb)) & 1;
- val = (instr >> (6 + ra * 2 + rb)) & 1;
+ val = (word >> (6 + ra * 2 + rb)) & 1;
op->ccval = (regs->ccr & ~(1UL << (31 - rd))) |
(val << (31 - rd));
return 1;
}
break;
case 31:
- switch ((instr >> 1) & 0x3ff) {
+ switch ((word >> 1) & 0x3ff) {
case 598: /* sync */
op->type = BARRIER + BARRIER_SYNC;
#ifdef __powerpc64__
- switch ((instr >> 21) & 3) {
+ switch ((word >> 21) & 3) {
case 1: /* lwsync */
op->type = BARRIER + BARRIER_LWSYNC;
break;
@@ -1285,20 +1287,20 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
if (!FULL_REGS(regs))
return -1;
- rd = (instr >> 21) & 0x1f;
- ra = (instr >> 16) & 0x1f;
- rb = (instr >> 11) & 0x1f;
- rc = (instr >> 6) & 0x1f;
+ rd = (word >> 21) & 0x1f;
+ ra = (word >> 16) & 0x1f;
+ rb = (word >> 11) & 0x1f;
+ rc = (word >> 6) & 0x1f;
switch (opcode) {
#ifdef __powerpc64__
case 2: /* tdi */
- if (rd & trap_compare(regs->gpr[ra], (short) instr))
+ if (rd & trap_compare(regs->gpr[ra], (short) word))
goto trap;
return 1;
#endif
case 3: /* twi */
- if (rd & trap_compare((int)regs->gpr[ra], (short) instr))
+ if (rd & trap_compare((int)regs->gpr[ra], (short) word))
goto trap;
return 1;
@@ -1307,7 +1309,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
if (!cpu_has_feature(CPU_FTR_ARCH_300))
return -1;
- switch (instr & 0x3f) {
+ switch (word & 0x3f) {
case 48: /* maddhd */
asm volatile(PPC_MADDHD(%0, %1, %2, %3) :
"=r" (op->val) : "r" (regs->gpr[ra]),
@@ -1335,16 +1337,16 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
#endif
case 7: /* mulli */
- op->val = regs->gpr[ra] * (short) instr;
+ op->val = regs->gpr[ra] * (short) word;
goto compute_done;
case 8: /* subfic */
- imm = (short) instr;
+ imm = (short) word;
add_with_carry(regs, op, rd, ~regs->gpr[ra], imm, 1);
return 1;
case 10: /* cmpli */
- imm = (unsigned short) instr;
+ imm = (unsigned short) word;
val = regs->gpr[ra];
#ifdef __powerpc64__
if ((rd & 1) == 0)
@@ -1354,7 +1356,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
return 1;
case 11: /* cmpi */
- imm = (short) instr;
+ imm = (short) word;
val = regs->gpr[ra];
#ifdef __powerpc64__
if ((rd & 1) == 0)
@@ -1364,35 +1366,35 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
return 1;
case 12: /* addic */
- imm = (short) instr;
+ imm = (short) word;
add_with_carry(regs, op, rd, regs->gpr[ra], imm, 0);
return 1;
case 13: /* addic. */
- imm = (short) instr;
+ imm = (short) word;
add_with_carry(regs, op, rd, regs->gpr[ra], imm, 0);
set_cr0(regs, op);
return 1;
case 14: /* addi */
- imm = (short) instr;
+ imm = (short) word;
if (ra)
imm += regs->gpr[ra];
op->val = imm;
goto compute_done;
case 15: /* addis */
- imm = ((short) instr) << 16;
+ imm = ((short) word) << 16;
if (ra)
imm += regs->gpr[ra];
op->val = imm;
goto compute_done;
case 19:
- if (((instr >> 1) & 0x1f) == 2) {
+ if (((word >> 1) & 0x1f) == 2) {
/* addpcis */
- imm = (short) (instr & 0xffc1); /* d0 + d2 fields */
- imm |= (instr >> 15) & 0x3e; /* d1 field */
+ imm = (short) (word & 0xffc1); /* d0 + d2 fields */
+ imm |= (word >> 15) & 0x3e; /* d1 field */
op->val = regs->nip + (imm << 16) + 4;
goto compute_done;
}
@@ -1400,65 +1402,65 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
return 0;
case 20: /* rlwimi */
- mb = (instr >> 6) & 0x1f;
- me = (instr >> 1) & 0x1f;
+ mb = (word >> 6) & 0x1f;
+ me = (word >> 1) & 0x1f;
val = DATA32(regs->gpr[rd]);
imm = MASK32(mb, me);
op->val = (regs->gpr[ra] & ~imm) | (ROTATE(val, rb) & imm);
goto logical_done;
case 21: /* rlwinm */
- mb = (instr >> 6) & 0x1f;
- me = (instr >> 1) & 0x1f;
+ mb = (word >> 6) & 0x1f;
+ me = (word >> 1) & 0x1f;
val = DATA32(regs->gpr[rd]);
op->val = ROTATE(val, rb) & MASK32(mb, me);
goto logical_done;
case 23: /* rlwnm */
- mb = (instr >> 6) & 0x1f;
- me = (instr >> 1) & 0x1f;
+ mb = (word >> 6) & 0x1f;
+ me = (word >> 1) & 0x1f;
rb = regs->gpr[rb] & 0x1f;
val = DATA32(regs->gpr[rd]);
op->val = ROTATE(val, rb) & MASK32(mb, me);
goto logical_done;
case 24: /* ori */
- op->val = regs->gpr[rd] | (unsigned short) instr;
+ op->val = regs->gpr[rd] | (unsigned short) word;
goto logical_done_nocc;
case 25: /* oris */
- imm = (unsigned short) instr;
+ imm = (unsigned short) word;
op->val = regs->gpr[rd] | (imm << 16);
goto logical_done_nocc;
case 26: /* xori */
- op->val = regs->gpr[rd] ^ (unsigned short) instr;
+ op->val = regs->gpr[rd] ^ (unsigned short) word;
goto logical_done_nocc;
case 27: /* xoris */
- imm = (unsigned short) instr;
+ imm = (unsigned short) word;
op->val = regs->gpr[rd] ^ (imm << 16);
goto logical_done_nocc;
case 28: /* andi. */
- op->val = regs->gpr[rd] & (unsigned short) instr;
+ op->val = regs->gpr[rd] & (unsigned short) word;
set_cr0(regs, op);
goto logical_done_nocc;
case 29: /* andis. */
- imm = (unsigned short) instr;
+ imm = (unsigned short) word;
op->val = regs->gpr[rd] & (imm << 16);
set_cr0(regs, op);
goto logical_done_nocc;
#ifdef __powerpc64__
case 30: /* rld* */
- mb = ((instr >> 6) & 0x1f) | (instr & 0x20);
+ mb = ((word >> 6) & 0x1f) | (word & 0x20);
val = regs->gpr[rd];
- if ((instr & 0x10) == 0) {
- sh = rb | ((instr & 2) << 4);
+ if ((word & 0x10) == 0) {
+ sh = rb | ((word & 2) << 4);
val = ROTATE(val, sh);
- switch ((instr >> 2) & 3) {
+ switch ((word >> 2) & 3) {
case 0: /* rldicl */
val &= MASK64_L(mb);
break;
@@ -1478,7 +1480,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
} else {
sh = regs->gpr[rb] & 0x3f;
val = ROTATE(val, sh);
- switch ((instr >> 1) & 7) {
+ switch ((word >> 1) & 7) {
case 0: /* rldcl */
op->val = val & MASK64_L(mb);
goto logical_done;
@@ -1493,8 +1495,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
case 31:
/* isel occupies 32 minor opcodes */
- if (((instr >> 1) & 0x1f) == 15) {
- mb = (instr >> 6) & 0x1f; /* bc field */
+ if (((word >> 1) & 0x1f) == 15) {
+ mb = (word >> 6) & 0x1f; /* bc field */
val = (regs->ccr >> (31 - mb)) & 1;
val2 = (ra) ? regs->gpr[ra] : 0;
@@ -1502,7 +1504,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
goto compute_done;
}
- switch ((instr >> 1) & 0x3ff) {
+ switch ((word >> 1) & 0x3ff) {
case 4: /* tw */
if (rd == 0x1f ||
(rd & trap_compare((int)regs->gpr[ra],
@@ -1536,17 +1538,17 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
op->reg = rd;
/* only MSR_EE and MSR_RI get changed if bit 15 set */
/* mtmsrd doesn't change MSR_HV, MSR_ME or MSR_LE */
- imm = (instr & 0x10000)? 0x8002: 0xefffffffffffeffeUL;
+ imm = (word & 0x10000)? 0x8002: 0xefffffffffffeffeUL;
op->val = imm;
return 0;
#endif
case 19: /* mfcr */
imm = 0xffffffffUL;
- if ((instr >> 20) & 1) {
+ if ((word >> 20) & 1) {
imm = 0xf0000000UL;
for (sh = 0; sh < 8; ++sh) {
- if (instr & (0x80000 >> sh))
+ if (word & (0x80000 >> sh))
break;
imm >>= 4;
}
@@ -1560,7 +1562,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
val = regs->gpr[rd];
op->ccval = regs->ccr;
for (sh = 0; sh < 8; ++sh) {
- if (instr & (0x80000 >> sh))
+ if (word & (0x80000 >> sh))
op->ccval = (op->ccval & ~imm) |
(val & imm);
imm >>= 4;
@@ -1568,7 +1570,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
return 1;
case 339: /* mfspr */
- spr = ((instr >> 16) & 0x1f) | ((instr >> 6) & 0x3e0);
+ spr = ((word >> 16) & 0x1f) | ((word >> 6) & 0x3e0);
op->type = MFSPR;
op->reg = rd;
op->spr = spr;
@@ -1578,7 +1580,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
return 0;
case 467: /* mtspr */
- spr = ((instr >> 16) & 0x1f) | ((instr >> 6) & 0x3e0);
+ spr = ((word >> 16) & 0x1f) | ((word >> 6) & 0x3e0);
op->type = MTSPR;
op->val = regs->gpr[rd];
op->spr = spr;
@@ -1948,7 +1950,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
case 826: /* sradi with sh_5 = 0 */
case 827: /* sradi with sh_5 = 1 */
op->type = COMPUTE + SETREG + SETXER;
- sh = rb | ((instr & 2) << 4);
+ sh = rb | ((word & 2) << 4);
ival = (signed long int) regs->gpr[rd];
op->val = ival >> sh;
op->xerval = regs->xer;
@@ -1964,7 +1966,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
if (!cpu_has_feature(CPU_FTR_ARCH_300))
return -1;
op->type = COMPUTE + SETREG;
- sh = rb | ((instr & 2) << 4);
+ sh = rb | ((word & 2) << 4);
val = (signed int) regs->gpr[rd];
if (sh)
op->val = ROTATE(val, sh) & MASK64(0, 63 - sh);
@@ -1979,34 +1981,34 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
*/
case 54: /* dcbst */
op->type = MKOP(CACHEOP, DCBST, 0);
- op->ea = xform_ea(instr, regs);
+ op->ea = xform_ea(word, regs);
return 0;
case 86: /* dcbf */
op->type = MKOP(CACHEOP, DCBF, 0);
- op->ea = xform_ea(instr, regs);
+ op->ea = xform_ea(word, regs);
return 0;
case 246: /* dcbtst */
op->type = MKOP(CACHEOP, DCBTST, 0);
- op->ea = xform_ea(instr, regs);
+ op->ea = xform_ea(word, regs);
op->reg = rd;
return 0;
case 278: /* dcbt */
op->type = MKOP(CACHEOP, DCBTST, 0);
- op->ea = xform_ea(instr, regs);
+ op->ea = xform_ea(word, regs);
op->reg = rd;
return 0;
case 982: /* icbi */
op->type = MKOP(CACHEOP, ICBI, 0);
- op->ea = xform_ea(instr, regs);
+ op->ea = xform_ea(word, regs);
return 0;
case 1014: /* dcbz */
op->type = MKOP(CACHEOP, DCBZ, 0);
- op->ea = xform_ea(instr, regs);
+ op->ea = xform_ea(word, regs);
return 0;
}
break;
@@ -2019,14 +2021,14 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
op->update_reg = ra;
op->reg = rd;
op->val = regs->gpr[rd];
- u = (instr >> 20) & UPDATE;
+ u = (word >> 20) & UPDATE;
op->vsx_flags = 0;
switch (opcode) {
case 31:
- u = instr & UPDATE;
- op->ea = xform_ea(instr, regs);
- switch ((instr >> 1) & 0x3ff) {
+ u = word & UPDATE;
+ op->ea = xform_ea(word, regs);
+ switch ((word >> 1) & 0x3ff) {
case 20: /* lwarx */
op->type = MKOP(LARX, 0, 4);
break;
@@ -2271,25 +2273,25 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
#ifdef CONFIG_VSX
case 12: /* lxsiwzx */
- op->reg = rd | ((instr & 1) << 5);
+ op->reg = rd | ((word & 1) << 5);
op->type = MKOP(LOAD_VSX, 0, 4);
op->element_size = 8;
break;
case 76: /* lxsiwax */
- op->reg = rd | ((instr & 1) << 5);
+ op->reg = rd | ((word & 1) << 5);
op->type = MKOP(LOAD_VSX, SIGNEXT, 4);
op->element_size = 8;
break;
case 140: /* stxsiwx */
- op->reg = rd | ((instr & 1) << 5);
+ op->reg = rd | ((word & 1) << 5);
op->type = MKOP(STORE_VSX, 0, 4);
op->element_size = 8;
break;
case 268: /* lxvx */
- op->reg = rd | ((instr & 1) << 5);
+ op->reg = rd | ((word & 1) << 5);
op->type = MKOP(LOAD_VSX, 0, 16);
op->element_size = 16;
op->vsx_flags = VSX_CHECK_VEC;
@@ -2298,33 +2300,33 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
case 269: /* lxvl */
case 301: { /* lxvll */
int nb;
- op->reg = rd | ((instr & 1) << 5);
+ op->reg = rd | ((word & 1) << 5);
op->ea = ra ? regs->gpr[ra] : 0;
nb = regs->gpr[rb] & 0xff;
if (nb > 16)
nb = 16;
op->type = MKOP(LOAD_VSX, 0, nb);
op->element_size = 16;
- op->vsx_flags = ((instr & 0x20) ? VSX_LDLEFT : 0) |
+ op->vsx_flags = ((word & 0x20) ? VSX_LDLEFT : 0) |
VSX_CHECK_VEC;
break;
}
case 332: /* lxvdsx */
- op->reg = rd | ((instr & 1) << 5);
+ op->reg = rd | ((word & 1) << 5);
op->type = MKOP(LOAD_VSX, 0, 8);
op->element_size = 8;
op->vsx_flags = VSX_SPLAT;
break;
case 364: /* lxvwsx */
- op->reg = rd | ((instr & 1) << 5);
+ op->reg = rd | ((word & 1) << 5);
op->type = MKOP(LOAD_VSX, 0, 4);
op->element_size = 4;
op->vsx_flags = VSX_SPLAT | VSX_CHECK_VEC;
break;
case 396: /* stxvx */
- op->reg = rd | ((instr & 1) << 5);
+ op->reg = rd | ((word & 1) << 5);
op->type = MKOP(STORE_VSX, 0, 16);
op->element_size = 16;
op->vsx_flags = VSX_CHECK_VEC;
@@ -2333,118 +2335,118 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
case 397: /* stxvl */
case 429: { /* stxvll */
int nb;
- op->reg = rd | ((instr & 1) << 5);
+ op->reg = rd | ((word & 1) << 5);
op->ea = ra ? regs->gpr[ra] : 0;
nb = regs->gpr[rb] & 0xff;
if (nb > 16)
nb = 16;
op->type = MKOP(STORE_VSX, 0, nb);
op->element_size = 16;
- op->vsx_flags = ((instr & 0x20) ? VSX_LDLEFT : 0) |
+ op->vsx_flags = ((word & 0x20) ? VSX_LDLEFT : 0) |
VSX_CHECK_VEC;
break;
}
case 524: /* lxsspx */
- op->reg = rd | ((instr & 1) << 5);
+ op->reg = rd | ((word & 1) << 5);
op->type = MKOP(LOAD_VSX, 0, 4);
op->element_size = 8;
op->vsx_flags = VSX_FPCONV;
break;
case 588: /* lxsdx */
- op->reg = rd | ((instr & 1) << 5);
+ op->reg = rd | ((word & 1) << 5);
op->type = MKOP(LOAD_VSX, 0, 8);
op->element_size = 8;
break;
case 652: /* stxsspx */
- op->reg = rd | ((instr & 1) << 5);
+ op->reg = rd | ((word & 1) << 5);
op->type = MKOP(STORE_VSX, 0, 4);
op->element_size = 8;
op->vsx_flags = VSX_FPCONV;
break;
case 716: /* stxsdx */
- op->reg = rd | ((instr & 1) << 5);
+ op->reg = rd | ((word & 1) << 5);
op->type = MKOP(STORE_VSX, 0, 8);
op->element_size = 8;
break;
case 780: /* lxvw4x */
- op->reg = rd | ((instr & 1) << 5);
+ op->reg = rd | ((word & 1) << 5);
op->type = MKOP(LOAD_VSX, 0, 16);
op->element_size = 4;
break;
case 781: /* lxsibzx */
- op->reg = rd | ((instr & 1) << 5);
+ op->reg = rd | ((word & 1) << 5);
op->type = MKOP(LOAD_VSX, 0, 1);
op->element_size = 8;
op->vsx_flags = VSX_CHECK_VEC;
break;
case 812: /* lxvh8x */
- op->reg = rd | ((instr & 1) << 5);
+ op->reg = rd | ((word & 1) << 5);
op->type = MKOP(LOAD_VSX, 0, 16);
op->element_size = 2;
op->vsx_flags = VSX_CHECK_VEC;
break;
case 813: /* lxsihzx */
- op->reg = rd | ((instr & 1) << 5);
+ op->reg = rd | ((word & 1) << 5);
op->type = MKOP(LOAD_VSX, 0, 2);
op->element_size = 8;
op->vsx_flags = VSX_CHECK_VEC;
break;
case 844: /* lxvd2x */
- op->reg = rd | ((instr & 1) << 5);
+ op->reg = rd | ((word & 1) << 5);
op->type = MKOP(LOAD_VSX, 0, 16);
op->element_size = 8;
break;
case 876: /* lxvb16x */
- op->reg = rd | ((instr & 1) << 5);
+ op->reg = rd | ((word & 1) << 5);
op->type = MKOP(LOAD_VSX, 0, 16);
op->element_size = 1;
op->vsx_flags = VSX_CHECK_VEC;
break;
case 908: /* stxvw4x */
- op->reg = rd | ((instr & 1) << 5);
+ op->reg = rd | ((word & 1) << 5);
op->type = MKOP(STORE_VSX, 0, 16);
op->element_size = 4;
break;
case 909: /* stxsibx */
- op->reg = rd | ((instr & 1) << 5);
+ op->reg = rd | ((word & 1) << 5);
op->type = MKOP(STORE_VSX, 0, 1);
op->element_size = 8;
op->vsx_flags = VSX_CHECK_VEC;
break;
case 940: /* stxvh8x */
- op->reg = rd | ((instr & 1) << 5);
+ op->reg = rd | ((word & 1) << 5);
op->type = MKOP(STORE_VSX, 0, 16);
op->element_size = 2;
op->vsx_flags = VSX_CHECK_VEC;
break;
case 941: /* stxsihx */
- op->reg = rd | ((instr & 1) << 5);
+ op->reg = rd | ((word & 1) << 5);
op->type = MKOP(STORE_VSX, 0, 2);
op->element_size = 8;
op->vsx_flags = VSX_CHECK_VEC;
break;
case 972: /* stxvd2x */
- op->reg = rd | ((instr & 1) << 5);
+ op->reg = rd | ((word & 1) << 5);
op->type = MKOP(STORE_VSX, 0, 16);
op->element_size = 8;
break;
case 1004: /* stxvb16x */
- op->reg = rd | ((instr & 1) << 5);
+ op->reg = rd | ((word & 1) << 5);
op->type = MKOP(STORE_VSX, 0, 16);
op->element_size = 1;
op->vsx_flags = VSX_CHECK_VEC;
@@ -2457,80 +2459,80 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
case 32: /* lwz */
case 33: /* lwzu */
op->type = MKOP(LOAD, u, 4);
- op->ea = dform_ea(instr, regs);
+ op->ea = dform_ea(word, regs);
break;
case 34: /* lbz */
case 35: /* lbzu */
op->type = MKOP(LOAD, u, 1);
- op->ea = dform_ea(instr, regs);
+ op->ea = dform_ea(word, regs);
break;
case 36: /* stw */
case 37: /* stwu */
op->type = MKOP(STORE, u, 4);
- op->ea = dform_ea(instr, regs);
+ op->ea = dform_ea(word, regs);
break;
case 38: /* stb */
case 39: /* stbu */
op->type = MKOP(STORE, u, 1);
- op->ea = dform_ea(instr, regs);
+ op->ea = dform_ea(word, regs);
break;
case 40: /* lhz */
case 41: /* lhzu */
op->type = MKOP(LOAD, u, 2);
- op->ea = dform_ea(instr, regs);
+ op->ea = dform_ea(word, regs);
break;
case 42: /* lha */
case 43: /* lhau */
op->type = MKOP(LOAD, SIGNEXT | u, 2);
- op->ea = dform_ea(instr, regs);
+ op->ea = dform_ea(word, regs);
break;
case 44: /* sth */
case 45: /* sthu */
op->type = MKOP(STORE, u, 2);
- op->ea = dform_ea(instr, regs);
+ op->ea = dform_ea(word, regs);
break;
case 46: /* lmw */
if (ra >= rd)
break; /* invalid form, ra in range to load */
op->type = MKOP(LOAD_MULTI, 0, 4 * (32 - rd));
- op->ea = dform_ea(instr, regs);
+ op->ea = dform_ea(word, regs);
break;
case 47: /* stmw */
op->type = MKOP(STORE_MULTI, 0, 4 * (32 - rd));
- op->ea = dform_ea(instr, regs);
+ op->ea = dform_ea(word, regs);
break;
#ifdef CONFIG_PPC_FPU
case 48: /* lfs */
case 49: /* lfsu */
op->type = MKOP(LOAD_FP, u | FPCONV, 4);
- op->ea = dform_ea(instr, regs);
+ op->ea = dform_ea(word, regs);
break;
case 50: /* lfd */
case 51: /* lfdu */
op->type = MKOP(LOAD_FP, u, 8);
- op->ea = dform_ea(instr, regs);
+ op->ea = dform_ea(word, regs);
break;
case 52: /* stfs */
case 53: /* stfsu */
op->type = MKOP(STORE_FP, u | FPCONV, 4);
- op->ea = dform_ea(instr, regs);
+ op->ea = dform_ea(word, regs);
break;
case 54: /* stfd */
case 55: /* stfdu */
op->type = MKOP(STORE_FP, u, 8);
- op->ea = dform_ea(instr, regs);
+ op->ea = dform_ea(word, regs);
break;
#endif
@@ -2538,14 +2540,14 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
case 56: /* lq */
if (!((rd & 1) || (rd == ra)))
op->type = MKOP(LOAD, 0, 16);
- op->ea = dqform_ea(instr, regs);
+ op->ea = dqform_ea(word, regs);
break;
#endif
#ifdef CONFIG_VSX
case 57: /* lfdp, lxsd, lxssp */
- op->ea = dsform_ea(instr, regs);
- switch (instr & 3) {
+ op->ea = dsform_ea(word, regs);
+ switch (word & 3) {
case 0: /* lfdp */
if (rd & 1)
break; /* reg must be even */
@@ -2569,8 +2571,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
#ifdef __powerpc64__
case 58: /* ld[u], lwa */
- op->ea = dsform_ea(instr, regs);
- switch (instr & 3) {
+ op->ea = dsform_ea(word, regs);
+ switch (word & 3) {
case 0: /* ld */
op->type = MKOP(LOAD, 0, 8);
break;
@@ -2586,16 +2588,16 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
#ifdef CONFIG_VSX
case 61: /* stfdp, lxv, stxsd, stxssp, stxv */
- switch (instr & 7) {
+ switch (word & 7) {
case 0: /* stfdp with LSB of DS field = 0 */
case 4: /* stfdp with LSB of DS field = 1 */
- op->ea = dsform_ea(instr, regs);
+ op->ea = dsform_ea(word, regs);
op->type = MKOP(STORE_FP, 0, 16);
break;
case 1: /* lxv */
- op->ea = dqform_ea(instr, regs);
- if (instr & 8)
+ op->ea = dqform_ea(word, regs);
+ if (word & 8)
op->reg = rd + 32;
op->type = MKOP(LOAD_VSX, 0, 16);
op->element_size = 16;
@@ -2604,7 +2606,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
case 2: /* stxsd with LSB of DS field = 0 */
case 6: /* stxsd with LSB of DS field = 1 */
- op->ea = dsform_ea(instr, regs);
+ op->ea = dsform_ea(word, regs);
op->reg = rd + 32;
op->type = MKOP(STORE_VSX, 0, 8);
op->element_size = 8;
@@ -2613,7 +2615,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
case 3: /* stxssp with LSB of DS field = 0 */
case 7: /* stxssp with LSB of DS field = 1 */
- op->ea = dsform_ea(instr, regs);
+ op->ea = dsform_ea(word, regs);
op->reg = rd + 32;
op->type = MKOP(STORE_VSX, 0, 4);
op->element_size = 8;
@@ -2621,8 +2623,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
break;
case 5: /* stxv */
- op->ea = dqform_ea(instr, regs);
- if (instr & 8)
+ op->ea = dqform_ea(word, regs);
+ if (word & 8)
op->reg = rd + 32;
op->type = MKOP(STORE_VSX, 0, 16);
op->element_size = 16;
@@ -2634,8 +2636,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
#ifdef __powerpc64__
case 62: /* std[u] */
- op->ea = dsform_ea(instr, regs);
- switch (instr & 3) {
+ op->ea = dsform_ea(word, regs);
+ switch (word & 3) {
case 0: /* std */
op->type = MKOP(STORE, 0, 8);
break;
@@ -2663,7 +2665,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
return 0;
logical_done:
- if (instr & 1)
+ if (word & 1)
set_cr0(regs, op);
logical_done_nocc:
op->reg = ra;
@@ -2671,7 +2673,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
return 1;
arith_done:
- if (instr & 1)
+ if (word & 1)
set_cr0(regs, op);
compute_done:
op->reg = rd;
diff --git a/arch/powerpc/lib/test_emulate_step.c b/arch/powerpc/lib/test_emulate_step.c
index 88b17226a493..60f7eb24d742 100644
--- a/arch/powerpc/lib/test_emulate_step.c
+++ b/arch/powerpc/lib/test_emulate_step.c
@@ -846,12 +846,12 @@ static int __init emulate_compute_instr(struct pt_regs *regs,
{
struct instruction_op op;
- if (!regs || !instr)
+ if (!regs || !ppc_inst_val(instr))
return -EINVAL;
if (analyse_instr(&op, regs, instr) != 1 ||
GETTYPE(op.type) != COMPUTE) {
- pr_info("emulation failed, instruction = 0x%08x\n", instr);
+ pr_info("emulation failed, instruction = 0x%08x\n", ppc_inst_val(instr));
return -EFAULT;
}
@@ -871,7 +871,7 @@ static int __init execute_compute_instr(struct pt_regs *regs,
/* Patch the NOP with the actual instruction */
patch_instruction_site(&patch__exec_instr, instr);
if (exec_instr(regs)) {
- pr_info("execution failed, instruction = 0x%08x\n", instr);
+ pr_info("execution failed, instruction = 0x%08x\n", ppc_inst_val(instr));
return -EFAULT;
}
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 68ecb39dd9cc..3c1fb46bfacf 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -2870,9 +2870,9 @@ generic_inst_dump(unsigned long adr, long count, int praddr,
dotted = 0;
last_inst = inst;
if (praddr)
- printf(REG" %.8x", adr, inst);
+ printf(REG" %.8x", adr, ppc_inst_val(inst));
printf("\t");
- dump_func(inst, adr);
+ dump_func(ppc_inst_val(inst), adr);
printf("\n");
}
return adr - first_adr;
--
2.17.1
^ permalink raw reply related [flat|nested] 71+ messages in thread
* [PATCH v5 07/21] powerpc: Use a function for byte swapping instructions
2020-04-06 8:09 [PATCH v5 00/21] Initial Prefixed Instruction support Jordan Niethe
` (5 preceding siblings ...)
2020-04-06 8:09 ` [PATCH v5 06/21] powerpc: Use an accessor for instructions Jordan Niethe
@ 2020-04-06 8:09 ` Jordan Niethe
2020-04-07 7:42 ` Balamuruhan S
2020-04-06 8:09 ` [PATCH v5 08/21] powerpc: Introduce functions for instruction equality Jordan Niethe
` (14 subsequent siblings)
21 siblings, 1 reply; 71+ messages in thread
From: Jordan Niethe @ 2020-04-06 8:09 UTC (permalink / raw)
To: linuxppc-dev; +Cc: alistair, npiggin, bala24, Jordan Niethe, dja
Use a function for byte swapping instructions in preparation of a more
complicated instruction type.
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
arch/powerpc/include/asm/inst.h | 5 +++++
arch/powerpc/kernel/align.c | 2 +-
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h
index 15f570bef936..78eb1481f1f6 100644
--- a/arch/powerpc/include/asm/inst.h
+++ b/arch/powerpc/include/asm/inst.h
@@ -18,4 +18,9 @@ static inline int ppc_inst_opcode(u32 x)
return x >> 26;
}
+static inline u32 ppc_inst_swab(u32 x)
+{
+ return ppc_inst(swab32(ppc_inst_val(x)));
+}
+
#endif /* _ASM_INST_H */
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
index a83d32c6513d..46870cf6a6dc 100644
--- a/arch/powerpc/kernel/align.c
+++ b/arch/powerpc/kernel/align.c
@@ -310,7 +310,7 @@ int fix_alignment(struct pt_regs *regs)
/* We don't handle PPC little-endian any more... */
if (cpu_has_feature(CPU_FTR_PPC_LE))
return -EIO;
- instr = swab32(instr);
+ instr = ppc_inst_swab(instr);
}
#ifdef CONFIG_SPE
--
2.17.1
^ permalink raw reply related [flat|nested] 71+ messages in thread
* [PATCH v5 08/21] powerpc: Introduce functions for instruction equality
2020-04-06 8:09 [PATCH v5 00/21] Initial Prefixed Instruction support Jordan Niethe
` (6 preceding siblings ...)
2020-04-06 8:09 ` [PATCH v5 07/21] powerpc: Use a function for byte swapping instructions Jordan Niethe
@ 2020-04-06 8:09 ` Jordan Niethe
2020-04-07 7:37 ` Balamuruhan S
2020-04-06 8:09 ` [PATCH v5 09/21] powerpc: Use a datatype for instructions Jordan Niethe
` (13 subsequent siblings)
21 siblings, 1 reply; 71+ messages in thread
From: Jordan Niethe @ 2020-04-06 8:09 UTC (permalink / raw)
To: linuxppc-dev; +Cc: alistair, npiggin, bala24, Jordan Niethe, dja
In preparation for an instruction data type that can not be directly
used with the '==' operator use functions for checking equality.
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v5: Remove ppc_inst_null()
---
arch/powerpc/include/asm/inst.h | 5 +++++
arch/powerpc/kernel/trace/ftrace.c | 15 ++++++++-------
arch/powerpc/lib/code-patching.c | 12 ++++++------
arch/powerpc/lib/test_emulate_step.c | 2 +-
arch/powerpc/xmon/xmon.c | 4 ++--
5 files changed, 22 insertions(+), 16 deletions(-)
diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h
index 78eb1481f1f6..54ee46b0a7c9 100644
--- a/arch/powerpc/include/asm/inst.h
+++ b/arch/powerpc/include/asm/inst.h
@@ -23,4 +23,9 @@ static inline u32 ppc_inst_swab(u32 x)
return ppc_inst(swab32(ppc_inst_val(x)));
}
+static inline bool ppc_inst_equal(u32 x, u32 y)
+{
+ return x == y;
+}
+
#endif /* _ASM_INST_H */
diff --git a/arch/powerpc/kernel/trace/ftrace.c b/arch/powerpc/kernel/trace/ftrace.c
index 62ff429bddc4..784b5746cc55 100644
--- a/arch/powerpc/kernel/trace/ftrace.c
+++ b/arch/powerpc/kernel/trace/ftrace.c
@@ -72,7 +72,7 @@ ftrace_modify_code(unsigned long ip, unsigned int old, unsigned int new)
return -EFAULT;
/* Make sure it is what we expect it to be */
- if (replaced != old) {
+ if (!ppc_inst_equal(replaced, old)) {
pr_err("%p: replaced (%#x) != old (%#x)",
(void *)ip, ppc_inst_val(replaced), ppc_inst_val(old));
return -EINVAL;
@@ -170,7 +170,8 @@ __ftrace_make_nop(struct module *mod,
}
/* We expect either a mflr r0, or a std r0, LRSAVE(r1) */
- if (op != ppc_inst(PPC_INST_MFLR) && op != ppc_inst(PPC_INST_STD_LR)) {
+ if (!ppc_inst_equal(op, ppc_inst(PPC_INST_MFLR)) &&
+ !ppc_inst_equal(op, ppc_inst(PPC_INST_STD_LR))) {
pr_err("Unexpected instruction %08x around bl _mcount\n", ppc_inst_val(op));
return -EINVAL;
}
@@ -200,7 +201,7 @@ __ftrace_make_nop(struct module *mod,
return -EFAULT;
}
- if (op != ppc_inst(PPC_INST_LD_TOC)) {
+ if (!ppc_inst_equal(op, ppc_inst(PPC_INST_LD_TOC))) {
pr_err("Expected %08x found %08x\n", PPC_INST_LD_TOC, ppc_inst_val(op));
return -EINVAL;
}
@@ -497,7 +498,7 @@ expected_nop_sequence(void *ip, unsigned int op0, unsigned int op1)
* The load offset is different depending on the ABI. For simplicity
* just mask it out when doing the compare.
*/
- if ((op0 != ppc_inst(0x48000008)) || (ppc_inst_val(op1) & 0xffff0000) != 0xe8410000)
+ if ((!ppc_inst_equal(op0), ppc_inst(0x48000008)) || (ppc_inst_val(op1) & 0xffff0000) != 0xe8410000)
return 0;
return 1;
}
@@ -506,7 +507,7 @@ static int
expected_nop_sequence(void *ip, unsigned int op0, unsigned int op1)
{
/* look for patched "NOP" on ppc64 with -mprofile-kernel */
- if (op0 != ppc_inst(PPC_INST_NOP))
+ if (!ppc_inst_equal(op0, ppc_inst(PPC_INST_NOP)))
return 0;
return 1;
}
@@ -589,7 +590,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
return -EFAULT;
/* It should be pointing to a nop */
- if (op != ppc_inst(PPC_INST_NOP)) {
+ if (!ppc_inst_equal(op, ppc_inst(PPC_INST_NOP))) {
pr_err("Expected NOP but have %x\n", op);
return -EINVAL;
}
@@ -646,7 +647,7 @@ static int __ftrace_make_call_kernel(struct dyn_ftrace *rec, unsigned long addr)
return -EFAULT;
}
- if (op != ppc_inst(PPC_INST_NOP)) {
+ if (!ppc_inst_equal(op, ppc_inst(PPC_INST_NOP))) {
pr_err("Unexpected call sequence at %p: %x\n", ip, ppc_inst_val(op));
return -EINVAL;
}
diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index 3f88d2a4400c..33654c6334a9 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -478,7 +478,7 @@ static void __init test_branch_iform(void)
/* Check flags are masked correctly */
err = create_branch(&instr, &instr, addr, 0xFFFFFFFC);
check(instr_is_branch_to_addr(&instr, addr));
- check(instr == ppc_inst(0x48000000));
+ check(ppc_inst_equal(instr, ppc_inst(0x48000000)));
}
static void __init test_create_function_call(void)
@@ -563,7 +563,7 @@ static void __init test_branch_bform(void)
/* Check flags are masked correctly */
err = create_cond_branch(&instr, iptr, addr, 0xFFFFFFFC);
check(instr_is_branch_to_addr(&instr, addr));
- check(instr == ppc_inst(0x43FF0000));
+ check(ppc_inst_equal(instr, ppc_inst(0x43FF0000)));
}
static void __init test_translate_branch(void)
@@ -597,7 +597,7 @@ static void __init test_translate_branch(void)
patch_instruction(q, instr);
check(instr_is_branch_to_addr(p, addr));
check(instr_is_branch_to_addr(q, addr));
- check(*q == ppc_inst(0x4a000000));
+ check(ppc_inst_equal(*q, ppc_inst(0x4a000000)));
/* Maximum positive case, move x to x - 32 MB + 4 */
p = buf + 0x2000000;
@@ -608,7 +608,7 @@ static void __init test_translate_branch(void)
patch_instruction(q, instr);
check(instr_is_branch_to_addr(p, addr));
check(instr_is_branch_to_addr(q, addr));
- check(*q == ppc_inst(0x49fffffc));
+ check(ppc_inst_equal(*q, ppc_inst(0x49fffffc)));
/* Jump to x + 16 MB moved to x + 20 MB */
p = buf;
@@ -654,7 +654,7 @@ static void __init test_translate_branch(void)
patch_instruction(q, instr);
check(instr_is_branch_to_addr(p, addr));
check(instr_is_branch_to_addr(q, addr));
- check(*q == ppc_inst(0x43ff8000));
+ check(ppc_inst_equal(*q, ppc_inst(0x43ff8000)));
/* Maximum positive case, move x to x - 32 KB + 4 */
p = buf + 0x8000;
@@ -666,7 +666,7 @@ static void __init test_translate_branch(void)
patch_instruction(q, instr);
check(instr_is_branch_to_addr(p, addr));
check(instr_is_branch_to_addr(q, addr));
- check(*q == ppc_inst(0x43ff7ffc));
+ check(ppc_inst_equal(*q, ppc_inst(0x43ff7ffc)));
/* Jump to x + 12 KB moved to x + 20 KB */
p = buf;
diff --git a/arch/powerpc/lib/test_emulate_step.c b/arch/powerpc/lib/test_emulate_step.c
index 60f7eb24d742..16387a9bfda0 100644
--- a/arch/powerpc/lib/test_emulate_step.c
+++ b/arch/powerpc/lib/test_emulate_step.c
@@ -865,7 +865,7 @@ static int __init execute_compute_instr(struct pt_regs *regs,
extern int exec_instr(struct pt_regs *regs);
extern s32 patch__exec_instr;
- if (!regs || !instr)
+ if (!regs || !ppc_inst_val(instr))
return -EINVAL;
/* Patch the NOP with the actual instruction */
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 3c1fb46bfacf..f6c87d3d53ea 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -950,7 +950,7 @@ static void remove_bpts(void)
if ((bp->enabled & (BP_TRAP|BP_CIABR)) != BP_TRAP)
continue;
if (mread(bp->address, &instr, 4) == 4
- && instr == ppc_inst(bpinstr)
+ && ppc_inst_equal(instr, ppc_inst(bpinstr))
&& patch_instruction(
(unsigned int *)bp->address, bp->instr[0]) != 0)
printf("Couldn't remove breakpoint at %lx\n",
@@ -2860,7 +2860,7 @@ generic_inst_dump(unsigned long adr, long count, int praddr,
break;
}
inst = ppc_inst(GETWORD(val));
- if (adr > first_adr && inst == last_inst) {
+ if (adr > first_adr && ppc_inst_equal(inst, last_inst)) {
if (!dotted) {
printf(" ...\n");
dotted = 1;
--
2.17.1
^ permalink raw reply related [flat|nested] 71+ messages in thread
* [PATCH v5 09/21] powerpc: Use a datatype for instructions
2020-04-06 8:09 [PATCH v5 00/21] Initial Prefixed Instruction support Jordan Niethe
` (7 preceding siblings ...)
2020-04-06 8:09 ` [PATCH v5 08/21] powerpc: Introduce functions for instruction equality Jordan Niethe
@ 2020-04-06 8:09 ` Jordan Niethe
2020-04-06 10:34 ` kbuild test robot
` (2 more replies)
2020-04-06 8:09 ` [PATCH v5 10/21] powerpc: Use a function for reading instructions Jordan Niethe
` (12 subsequent siblings)
21 siblings, 3 replies; 71+ messages in thread
From: Jordan Niethe @ 2020-04-06 8:09 UTC (permalink / raw)
To: linuxppc-dev; +Cc: alistair, npiggin, bala24, Jordan Niethe, dja
Currently unsigned ints are used to represent instructions on powerpc.
This has worked well as instructions have always been 4 byte words.
However, a future ISA version will introduce some changes to
instructions that mean this scheme will no longer work as well. This
change is Prefixed Instructions. A prefixed instruction is made up of a
word prefix followed by a word suffix to make an 8 byte double word
instruction. No matter the endianess of the system the prefix always
comes first. Prefixed instructions are only planned for powerpc64.
Introduce a ppc_inst type to represent both prefixed and word
instructions on powerpc64 while keeping it possible to exclusively have
word instructions on powerpc32, A latter patch will expand the type to
include prefixed instructions but for now just typedef it to a u32.
Later patches will introduce helper functions and macros for
manipulating the instructions so that powerpc64 and powerpc32 might
maintain separate type definitions.
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v4: New to series
v5: Add to epapr_paravirt.c, kgdb.c
---
arch/powerpc/include/asm/code-patching.h | 32 ++++-----
arch/powerpc/include/asm/inst.h | 20 +++---
arch/powerpc/include/asm/sstep.h | 5 +-
arch/powerpc/include/asm/uprobes.h | 5 +-
arch/powerpc/kernel/align.c | 4 +-
arch/powerpc/kernel/epapr_paravirt.c | 4 +-
arch/powerpc/kernel/hw_breakpoint.c | 4 +-
arch/powerpc/kernel/jump_label.c | 2 +-
arch/powerpc/kernel/kgdb.c | 4 +-
arch/powerpc/kernel/kprobes.c | 8 +--
arch/powerpc/kernel/mce_power.c | 5 +-
arch/powerpc/kernel/optprobes.c | 40 ++++++------
arch/powerpc/kernel/setup_32.c | 2 +-
arch/powerpc/kernel/trace/ftrace.c | 83 ++++++++++++------------
arch/powerpc/kernel/vecemu.c | 5 +-
arch/powerpc/lib/code-patching.c | 69 ++++++++++----------
arch/powerpc/lib/feature-fixups.c | 48 +++++++-------
arch/powerpc/lib/sstep.c | 4 +-
arch/powerpc/lib/test_emulate_step.c | 9 +--
arch/powerpc/perf/core-book3s.c | 4 +-
arch/powerpc/xmon/xmon.c | 24 +++----
21 files changed, 196 insertions(+), 185 deletions(-)
diff --git a/arch/powerpc/include/asm/code-patching.h b/arch/powerpc/include/asm/code-patching.h
index 48e021957ee5..eacc9102c251 100644
--- a/arch/powerpc/include/asm/code-patching.h
+++ b/arch/powerpc/include/asm/code-patching.h
@@ -23,33 +23,33 @@
#define BRANCH_ABSOLUTE 0x2
bool is_offset_in_branch_range(long offset);
-int create_branch(unsigned int *instr, const unsigned int *addr,
+int create_branch(struct ppc_inst *instr, const struct ppc_inst *addr,
unsigned long target, int flags);
-int create_cond_branch(unsigned int *instr, const unsigned int *addr,
+int create_cond_branch(struct ppc_inst *instr, const struct ppc_inst *addr,
unsigned long target, int flags);
-int patch_branch(unsigned int *addr, unsigned long target, int flags);
-int patch_instruction(unsigned int *addr, unsigned int instr);
-int raw_patch_instruction(unsigned int *addr, unsigned int instr);
+int patch_branch(struct ppc_inst *addr, unsigned long target, int flags);
+int patch_instruction(struct ppc_inst *addr, struct ppc_inst instr);
+int raw_patch_instruction(struct ppc_inst *addr, struct ppc_inst instr);
static inline unsigned long patch_site_addr(s32 *site)
{
return (unsigned long)site + *site;
}
-static inline int patch_instruction_site(s32 *site, unsigned int instr)
+static inline int patch_instruction_site(s32 *site, struct ppc_inst instr)
{
- return patch_instruction((unsigned int *)patch_site_addr(site), instr);
+ return patch_instruction((struct ppc_inst *)patch_site_addr(site), instr);
}
static inline int patch_branch_site(s32 *site, unsigned long target, int flags)
{
- return patch_branch((unsigned int *)patch_site_addr(site), target, flags);
+ return patch_branch((struct ppc_inst *)patch_site_addr(site), target, flags);
}
static inline int modify_instruction(unsigned int *addr, unsigned int clr,
unsigned int set)
{
- return patch_instruction(addr, ppc_inst((*addr & ~clr) | set));
+ return patch_instruction((struct ppc_inst *)addr, ppc_inst((*addr & ~clr) | set));
}
static inline int modify_instruction_site(s32 *site, unsigned int clr, unsigned int set)
@@ -57,13 +57,13 @@ static inline int modify_instruction_site(s32 *site, unsigned int clr, unsigned
return modify_instruction((unsigned int *)patch_site_addr(site), clr, set);
}
-int instr_is_relative_branch(unsigned int instr);
-int instr_is_relative_link_branch(unsigned int instr);
-int instr_is_branch_to_addr(const unsigned int *instr, unsigned long addr);
-unsigned long branch_target(const unsigned int *instr);
-int translate_branch(unsigned int *instr, const unsigned int *dest,
- const unsigned int *src);
-extern bool is_conditional_branch(unsigned int instr);
+int instr_is_relative_branch(struct ppc_inst instr);
+int instr_is_relative_link_branch(struct ppc_inst instr);
+int instr_is_branch_to_addr(const struct ppc_inst *instr, unsigned long addr);
+unsigned long branch_target(const struct ppc_inst *instr);
+int translate_branch(struct ppc_inst *instr, const struct ppc_inst *dest,
+ const struct ppc_inst *src);
+extern bool is_conditional_branch(struct ppc_inst instr);
#ifdef CONFIG_PPC_BOOK3E_64
void __patch_exception(int exc, unsigned long addr);
#define patch_exception(exc, name) do { \
diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h
index 54ee46b0a7c9..a71decf5f871 100644
--- a/arch/powerpc/include/asm/inst.h
+++ b/arch/powerpc/include/asm/inst.h
@@ -6,26 +6,30 @@
* Instruction data type for POWER
*/
-#define ppc_inst(x) (x)
+struct ppc_inst {
+ u32 val;
+} __packed;
-static inline u32 ppc_inst_val(u32 x)
+#define ppc_inst(x) ((struct ppc_inst){ .val = x })
+
+static inline u32 ppc_inst_val(struct ppc_inst x)
{
- return x;
+ return x.val;
}
-static inline int ppc_inst_opcode(u32 x)
+static inline int ppc_inst_opcode(struct ppc_inst x)
{
- return x >> 26;
+ return x.val >> 26;
}
-static inline u32 ppc_inst_swab(u32 x)
+static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
{
return ppc_inst(swab32(ppc_inst_val(x)));
}
-static inline bool ppc_inst_equal(u32 x, u32 y)
+static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
{
- return x == y;
+ return !memcmp(&x, &y, sizeof(struct ppc_inst));
}
#endif /* _ASM_INST_H */
diff --git a/arch/powerpc/include/asm/sstep.h b/arch/powerpc/include/asm/sstep.h
index 26d729562fe2..c3ce903ac488 100644
--- a/arch/powerpc/include/asm/sstep.h
+++ b/arch/powerpc/include/asm/sstep.h
@@ -2,6 +2,7 @@
/*
* Copyright (C) 2004 Paul Mackerras <paulus@au.ibm.com>, IBM
*/
+#include <asm/inst.h>
struct pt_regs;
@@ -132,7 +133,7 @@ union vsx_reg {
* otherwise.
*/
extern int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
- unsigned int instr);
+ struct ppc_inst instr);
/*
* Emulate an instruction that can be executed just by updating
@@ -149,7 +150,7 @@ void emulate_update_regs(struct pt_regs *reg, struct instruction_op *op);
* 0 if it could not be emulated, or -1 for an instruction that
* should not be emulated (rfid, mtmsrd clearing MSR_RI, etc.).
*/
-extern int emulate_step(struct pt_regs *regs, unsigned int instr);
+extern int emulate_step(struct pt_regs *regs, struct ppc_inst instr);
/*
* Emulate a load or store instruction by reading/writing the
diff --git a/arch/powerpc/include/asm/uprobes.h b/arch/powerpc/include/asm/uprobes.h
index 2bbdf27d09b5..7e3b329ba2d3 100644
--- a/arch/powerpc/include/asm/uprobes.h
+++ b/arch/powerpc/include/asm/uprobes.h
@@ -11,6 +11,7 @@
#include <linux/notifier.h>
#include <asm/probes.h>
+#include <asm/inst.h>
typedef ppc_opcode_t uprobe_opcode_t;
@@ -23,8 +24,8 @@ typedef ppc_opcode_t uprobe_opcode_t;
struct arch_uprobe {
union {
- u32 insn;
- u32 ixol;
+ struct ppc_inst insn;
+ struct ppc_inst ixol;
};
};
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
index 46870cf6a6dc..66a6d1de7799 100644
--- a/arch/powerpc/kernel/align.c
+++ b/arch/powerpc/kernel/align.c
@@ -294,7 +294,7 @@ static int emulate_spe(struct pt_regs *regs, unsigned int reg,
int fix_alignment(struct pt_regs *regs)
{
- unsigned int instr;
+ struct ppc_inst instr;
struct instruction_op op;
int r, type;
@@ -304,7 +304,7 @@ int fix_alignment(struct pt_regs *regs)
*/
CHECK_FULL_REGS(regs);
- if (unlikely(__get_user(instr, (unsigned int __user *)regs->nip)))
+ if (unlikely(__get_user(instr.val, (unsigned int __user *)regs->nip)))
return -EFAULT;
if ((regs->msr & MSR_LE) != (MSR_KERNEL & MSR_LE)) {
/* We don't handle PPC little-endian any more... */
diff --git a/arch/powerpc/kernel/epapr_paravirt.c b/arch/powerpc/kernel/epapr_paravirt.c
index c53e863fb484..c42aa3926632 100644
--- a/arch/powerpc/kernel/epapr_paravirt.c
+++ b/arch/powerpc/kernel/epapr_paravirt.c
@@ -38,9 +38,9 @@ static int __init early_init_dt_scan_epapr(unsigned long node,
for (i = 0; i < (len / 4); i++) {
u32 inst = be32_to_cpu(insts[i]);
- patch_instruction(epapr_hypercall_start + i, ppc_inst(inst));
+ patch_instruction((struct ppc_inst *)(epapr_hypercall_start + i), ppc_inst(inst));
#if !defined(CONFIG_64BIT) || defined(CONFIG_PPC_BOOK3E_64)
- patch_instruction(epapr_ev_idle_start + i, ppc_inst(inst));
+ patch_instruction((struct ppc_inst *)(epapr_ev_idle_start + i), ppc_inst(inst));
#endif
}
diff --git a/arch/powerpc/kernel/hw_breakpoint.c b/arch/powerpc/kernel/hw_breakpoint.c
index 79f51f182a83..542f65ccf68b 100644
--- a/arch/powerpc/kernel/hw_breakpoint.c
+++ b/arch/powerpc/kernel/hw_breakpoint.c
@@ -244,12 +244,12 @@ dar_range_overlaps(unsigned long dar, int size, struct arch_hw_breakpoint *info)
static bool stepping_handler(struct pt_regs *regs, struct perf_event *bp,
struct arch_hw_breakpoint *info)
{
- unsigned int instr = ppc_inst(0);
+ struct ppc_inst instr = ppc_inst(0);
int ret, type, size;
struct instruction_op op;
unsigned long addr = info->address;
- if (__get_user_inatomic(instr, (unsigned int *)regs->nip))
+ if (__get_user_inatomic(instr.val, (unsigned int *)regs->nip))
goto fail;
ret = analyse_instr(&op, regs, instr);
diff --git a/arch/powerpc/kernel/jump_label.c b/arch/powerpc/kernel/jump_label.c
index daa4afce7ec8..144858027fa3 100644
--- a/arch/powerpc/kernel/jump_label.c
+++ b/arch/powerpc/kernel/jump_label.c
@@ -11,7 +11,7 @@
void arch_jump_label_transform(struct jump_entry *entry,
enum jump_label_type type)
{
- u32 *addr = (u32 *)(unsigned long)entry->code;
+ struct ppc_inst *addr = (struct ppc_inst *)(unsigned long)entry->code;
if (type == JUMP_LABEL_JMP)
patch_branch(addr, entry->target, 0);
diff --git a/arch/powerpc/kernel/kgdb.c b/arch/powerpc/kernel/kgdb.c
index a6b38a19133f..652b2852bea3 100644
--- a/arch/powerpc/kernel/kgdb.c
+++ b/arch/powerpc/kernel/kgdb.c
@@ -419,7 +419,7 @@ int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
{
int err;
unsigned int instr;
- unsigned int *addr = (unsigned int *)bpt->bpt_addr;
+ struct ppc_inst *addr = (struct ppc_inst *)bpt->bpt_addr;
err = probe_kernel_address(addr, instr);
if (err)
@@ -438,7 +438,7 @@ int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
{
int err;
unsigned int instr = *(unsigned int *)bpt->saved_instr;
- unsigned int *addr = (unsigned int *)bpt->bpt_addr;
+ struct ppc_inst *addr = (struct ppc_inst *)bpt->bpt_addr;
err = patch_instruction(addr, ppc_inst(instr));
if (err)
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index 8420b1944164..9ed996cb0589 100644
--- a/arch/powerpc/kernel/kprobes.c
+++ b/arch/powerpc/kernel/kprobes.c
@@ -106,7 +106,7 @@ kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset)
int arch_prepare_kprobe(struct kprobe *p)
{
int ret = 0;
- kprobe_opcode_t insn = *p->addr;
+ struct ppc_inst insn = *(struct ppc_inst *)p->addr;
if ((unsigned long)p->addr & 0x03) {
printk("Attempt to register kprobe at an unaligned address\n");
@@ -139,13 +139,13 @@ NOKPROBE_SYMBOL(arch_prepare_kprobe);
void arch_arm_kprobe(struct kprobe *p)
{
- patch_instruction(p->addr, ppc_inst(BREAKPOINT_INSTRUCTION));
+ patch_instruction((struct ppc_inst *)p->addr, ppc_inst(BREAKPOINT_INSTRUCTION));
}
NOKPROBE_SYMBOL(arch_arm_kprobe);
void arch_disarm_kprobe(struct kprobe *p)
{
- patch_instruction(p->addr, ppc_inst(p->opcode));
+ patch_instruction((struct ppc_inst *)p->addr, ppc_inst(p->opcode));
}
NOKPROBE_SYMBOL(arch_disarm_kprobe);
@@ -217,7 +217,7 @@ NOKPROBE_SYMBOL(arch_prepare_kretprobe);
static int try_to_emulate(struct kprobe *p, struct pt_regs *regs)
{
int ret;
- unsigned int insn = *p->ainsn.insn;
+ struct ppc_inst insn = *(struct ppc_inst *)p->ainsn.insn;
/* regs->nip is also adjusted if emulate_step returns 1 */
ret = emulate_step(regs, insn);
diff --git a/arch/powerpc/kernel/mce_power.c b/arch/powerpc/kernel/mce_power.c
index 1cbf7f1a4e3d..7118b46a6543 100644
--- a/arch/powerpc/kernel/mce_power.c
+++ b/arch/powerpc/kernel/mce_power.c
@@ -20,6 +20,7 @@
#include <asm/sstep.h>
#include <asm/exception-64s.h>
#include <asm/extable.h>
+#include <asm/inst.h>
/*
* Convert an address related to an mm to a PFN. NOTE: we are in real
@@ -365,7 +366,7 @@ static int mce_find_instr_ea_and_phys(struct pt_regs *regs, uint64_t *addr,
* in real-mode is tricky and can lead to recursive
* faults
*/
- int instr;
+ struct ppc_inst instr;
unsigned long pfn, instr_addr;
struct instruction_op op;
struct pt_regs tmp = *regs;
@@ -373,7 +374,7 @@ static int mce_find_instr_ea_and_phys(struct pt_regs *regs, uint64_t *addr,
pfn = addr_to_pfn(regs, regs->nip);
if (pfn != ULONG_MAX) {
instr_addr = (pfn << PAGE_SHIFT) + (regs->nip & ~PAGE_MASK);
- instr = *(unsigned int *)(instr_addr);
+ instr = *(struct ppc_inst *)(instr_addr);
if (!analyse_instr(&op, &tmp, instr)) {
pfn = addr_to_pfn(regs, op.ea);
*addr = op.ea;
diff --git a/arch/powerpc/kernel/optprobes.c b/arch/powerpc/kernel/optprobes.c
index 3b33ebf18859..b61bbcee84f4 100644
--- a/arch/powerpc/kernel/optprobes.c
+++ b/arch/powerpc/kernel/optprobes.c
@@ -100,8 +100,8 @@ static unsigned long can_optimize(struct kprobe *p)
* Ensure that the instruction is not a conditional branch,
* and that can be emulated.
*/
- if (!is_conditional_branch(*p->ainsn.insn) &&
- analyse_instr(&op, ®s, *p->ainsn.insn) == 1) {
+ if (!is_conditional_branch(*(struct ppc_inst *)p->ainsn.insn) &&
+ analyse_instr(&op, ®s, *(struct ppc_inst *)p->ainsn.insn) == 1) {
emulate_update_regs(®s, &op);
nip = regs.nip;
}
@@ -148,12 +148,12 @@ void arch_remove_optimized_kprobe(struct optimized_kprobe *op)
void patch_imm32_load_insns(unsigned int val, kprobe_opcode_t *addr)
{
/* addis r4,0,(insn)@h */
- patch_instruction(addr, ppc_inst(PPC_INST_ADDIS | ___PPC_RT(4) |
+ patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ADDIS | ___PPC_RT(4) |
((val >> 16) & 0xffff)));
addr++;
/* ori r4,r4,(insn)@l */
- patch_instruction(addr, ppc_inst(PPC_INST_ORI | ___PPC_RA(4) |
+ patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI | ___PPC_RA(4) |
___PPC_RS(4) | (val & 0xffff)));
}
@@ -164,34 +164,34 @@ void patch_imm32_load_insns(unsigned int val, kprobe_opcode_t *addr)
void patch_imm64_load_insns(unsigned long val, kprobe_opcode_t *addr)
{
/* lis r3,(op)@highest */
- patch_instruction(addr, ppc_inst(PPC_INST_ADDIS | ___PPC_RT(3) |
+ patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ADDIS | ___PPC_RT(3) |
((val >> 48) & 0xffff)));
addr++;
/* ori r3,r3,(op)@higher */
- patch_instruction(addr, ppc_inst(PPC_INST_ORI | ___PPC_RA(3) |
+ patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI | ___PPC_RA(3) |
___PPC_RS(3) | ((val >> 32) & 0xffff)));
addr++;
/* rldicr r3,r3,32,31 */
- patch_instruction(addr, ppc_inst(PPC_INST_RLDICR | ___PPC_RA(3) |
+ patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_RLDICR | ___PPC_RA(3) |
___PPC_RS(3) | __PPC_SH64(32) | __PPC_ME64(31)));
addr++;
/* oris r3,r3,(op)@h */
- patch_instruction(addr, ppc_inst(PPC_INST_ORIS | ___PPC_RA(3) |
+ patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORIS | ___PPC_RA(3) |
___PPC_RS(3) | ((val >> 16) & 0xffff)));
addr++;
/* ori r3,r3,(op)@l */
- patch_instruction(addr, ppc_inst(PPC_INST_ORI | ___PPC_RA(3) |
+ patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI | ___PPC_RA(3) |
___PPC_RS(3) | (val & 0xffff)));
}
int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p)
{
- kprobe_opcode_t *buff, branch_op_callback, branch_emulate_step;
- kprobe_opcode_t *op_callback_addr, *emulate_step_addr;
+ struct ppc_inst branch_op_callback, branch_emulate_step;
+ kprobe_opcode_t *op_callback_addr, *emulate_step_addr, *buff;
long b_offset;
unsigned long nip, size;
int rc, i;
@@ -231,7 +231,7 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p)
size = (TMPL_END_IDX * sizeof(kprobe_opcode_t)) / sizeof(int);
pr_devel("Copying template to %p, size %lu\n", buff, size);
for (i = 0; i < size; i++) {
- rc = patch_instruction(buff + i, ppc_inst(*(optprobe_template_entry + i)));
+ rc = patch_instruction((struct ppc_inst *)(buff + i), ppc_inst(*(optprobe_template_entry + i)));
if (rc < 0)
goto error;
}
@@ -253,20 +253,20 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p)
}
rc = create_branch(&branch_op_callback,
- (unsigned int *)buff + TMPL_CALL_HDLR_IDX,
+ (struct ppc_inst *)(buff + TMPL_CALL_HDLR_IDX),
(unsigned long)op_callback_addr,
BRANCH_SET_LINK);
rc |= create_branch(&branch_emulate_step,
- (unsigned int *)buff + TMPL_EMULATE_IDX,
+ (struct ppc_inst *)(buff + TMPL_EMULATE_IDX),
(unsigned long)emulate_step_addr,
BRANCH_SET_LINK);
if (rc)
goto error;
- patch_instruction(buff + TMPL_CALL_HDLR_IDX, branch_op_callback);
- patch_instruction(buff + TMPL_EMULATE_IDX, branch_emulate_step);
+ patch_instruction((struct ppc_inst *)(buff + TMPL_CALL_HDLR_IDX), branch_op_callback);
+ patch_instruction((struct ppc_inst *)(buff + TMPL_EMULATE_IDX), branch_emulate_step);
/*
* 3. load instruction to be emulated into relevant register, and
@@ -276,7 +276,7 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p)
/*
* 4. branch back from trampoline
*/
- patch_branch(buff + TMPL_RET_IDX, (unsigned long)nip, 0);
+ patch_branch((void *)(buff + TMPL_RET_IDX), (unsigned long)nip, 0);
flush_icache_range((unsigned long)buff,
(unsigned long)(&buff[TMPL_END_IDX]));
@@ -308,7 +308,7 @@ int arch_check_optimized_kprobe(struct optimized_kprobe *op)
void arch_optimize_kprobes(struct list_head *oplist)
{
- unsigned int instr;
+ struct ppc_inst instr;
struct optimized_kprobe *op;
struct optimized_kprobe *tmp;
@@ -320,9 +320,9 @@ void arch_optimize_kprobes(struct list_head *oplist)
memcpy(op->optinsn.copied_insn, op->kp.addr,
RELATIVEJUMP_SIZE);
create_branch(&instr,
- (unsigned int *)op->kp.addr,
+ (struct ppc_inst *)op->kp.addr,
(unsigned long)op->optinsn.insn, 0);
- patch_instruction(op->kp.addr, instr);
+ patch_instruction((struct ppc_inst *)op->kp.addr, instr);
list_del_init(&op->list);
}
}
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index c1bdd462c5c0..989809e58234 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -76,7 +76,7 @@ EXPORT_SYMBOL(DMA_MODE_WRITE);
notrace void __init machine_init(u64 dt_ptr)
{
unsigned int *addr = (unsigned int *)patch_site_addr(&patch__memset_nocache);
- unsigned long insn;
+ struct ppc_inst insn;
/* Configure static keys first, now that we're relocated. */
setup_feature_keys();
diff --git a/arch/powerpc/kernel/trace/ftrace.c b/arch/powerpc/kernel/trace/ftrace.c
index 784b5746cc55..442c62fb68ff 100644
--- a/arch/powerpc/kernel/trace/ftrace.c
+++ b/arch/powerpc/kernel/trace/ftrace.c
@@ -41,23 +41,23 @@
#define NUM_FTRACE_TRAMPS 8
static unsigned long ftrace_tramps[NUM_FTRACE_TRAMPS];
-static unsigned int
+static struct ppc_inst
ftrace_call_replace(unsigned long ip, unsigned long addr, int link)
{
- unsigned int op;
+ struct ppc_inst op;
addr = ppc_function_entry((void *)addr);
/* if (link) set op to 'bl' else 'b' */
- create_branch(&op, (unsigned int *)ip, addr, link ? 1 : 0);
+ create_branch(&op, (struct ppc_inst *)ip, addr, link ? 1 : 0);
return op;
}
static int
-ftrace_modify_code(unsigned long ip, unsigned int old, unsigned int new)
+ftrace_modify_code(unsigned long ip, struct ppc_inst old, struct ppc_inst new)
{
- unsigned int replaced;
+ struct ppc_inst replaced;
/*
* Note:
@@ -79,7 +79,7 @@ ftrace_modify_code(unsigned long ip, unsigned int old, unsigned int new)
}
/* replace the text with the new text */
- if (patch_instruction((unsigned int *)ip, new))
+ if (patch_instruction((struct ppc_inst *)ip, new))
return -EPERM;
return 0;
@@ -90,24 +90,24 @@ ftrace_modify_code(unsigned long ip, unsigned int old, unsigned int new)
*/
static int test_24bit_addr(unsigned long ip, unsigned long addr)
{
- unsigned int op;
+ struct ppc_inst op;
addr = ppc_function_entry((void *)addr);
/* use the create_branch to verify that this offset can be branched */
- return create_branch(&op, (unsigned int *)ip, addr, 0) == 0;
+ return create_branch(&op, (struct ppc_inst *)ip, addr, 0) == 0;
}
-static int is_bl_op(unsigned int op)
+static int is_bl_op(struct ppc_inst op)
{
return (ppc_inst_val(op) & 0xfc000003) == 0x48000001;
}
-static int is_b_op(unsigned int op)
+static int is_b_op(struct ppc_inst op)
{
return (ppc_inst_val(op) & 0xfc000003) == 0x48000000;
}
-static unsigned long find_bl_target(unsigned long ip, unsigned int op)
+static unsigned long find_bl_target(unsigned long ip, struct ppc_inst op)
{
int offset;
@@ -127,7 +127,7 @@ __ftrace_make_nop(struct module *mod,
{
unsigned long entry, ptr, tramp;
unsigned long ip = rec->ip;
- unsigned int op, pop;
+ struct ppc_inst op, pop;
/* read where this goes */
if (probe_kernel_read(&op, (void *)ip, sizeof(int))) {
@@ -207,7 +207,7 @@ __ftrace_make_nop(struct module *mod,
}
#endif /* CONFIG_MPROFILE_KERNEL */
- if (patch_instruction((unsigned int *)ip, pop)) {
+ if (patch_instruction((struct ppc_inst *)ip, pop)) {
pr_err("Patching NOP failed.\n");
return -EPERM;
}
@@ -220,7 +220,7 @@ static int
__ftrace_make_nop(struct module *mod,
struct dyn_ftrace *rec, unsigned long addr)
{
- unsigned int op;
+ struct ppc_inst op;
unsigned int jmp[4];
unsigned long ip = rec->ip;
unsigned long tramp;
@@ -279,7 +279,7 @@ __ftrace_make_nop(struct module *mod,
op = ppc_inst(PPC_INST_NOP);
- if (patch_instruction((unsigned int *)ip, op))
+ if (patch_instruction((struct ppc_inst *)ip, op))
return -EPERM;
return 0;
@@ -290,7 +290,7 @@ __ftrace_make_nop(struct module *mod,
static unsigned long find_ftrace_tramp(unsigned long ip)
{
int i;
- unsigned int instr;
+ struct ppc_inst instr;
/*
* We have the compiler generated long_branch tramps at the end
@@ -327,9 +327,10 @@ static int add_ftrace_tramp(unsigned long tramp)
*/
static int setup_mcount_compiler_tramp(unsigned long tramp)
{
- int i, op;
+ int i;
+ struct ppc_inst op;
unsigned long ptr;
- unsigned int instr;
+ struct ppc_inst instr;
static unsigned long ftrace_plt_tramps[NUM_FTRACE_TRAMPS];
/* Is this a known long jump tramp? */
@@ -378,7 +379,7 @@ static int setup_mcount_compiler_tramp(unsigned long tramp)
return -1;
}
- if (patch_branch((unsigned int *)tramp, ptr, 0)) {
+ if (patch_branch((struct ppc_inst *)tramp, ptr, 0)) {
pr_debug("REL24 out of range!\n");
return -1;
}
@@ -394,7 +395,7 @@ static int setup_mcount_compiler_tramp(unsigned long tramp)
static int __ftrace_make_nop_kernel(struct dyn_ftrace *rec, unsigned long addr)
{
unsigned long tramp, ip = rec->ip;
- unsigned int op;
+ struct ppc_inst op;
/* Read where this goes */
if (probe_kernel_read(&op, (void *)ip, sizeof(int))) {
@@ -422,7 +423,7 @@ static int __ftrace_make_nop_kernel(struct dyn_ftrace *rec, unsigned long addr)
}
}
- if (patch_instruction((unsigned int *)ip, ppc_inst(PPC_INST_NOP))) {
+ if (patch_instruction((struct ppc_inst *)ip, ppc_inst(PPC_INST_NOP))) {
pr_err("Patching NOP failed.\n");
return -EPERM;
}
@@ -434,7 +435,7 @@ int ftrace_make_nop(struct module *mod,
struct dyn_ftrace *rec, unsigned long addr)
{
unsigned long ip = rec->ip;
- unsigned int old, new;
+ struct ppc_inst old, new;
/*
* If the calling address is more that 24 bits away,
@@ -487,7 +488,7 @@ int ftrace_make_nop(struct module *mod,
*/
#ifndef CONFIG_MPROFILE_KERNEL
static int
-expected_nop_sequence(void *ip, unsigned int op0, unsigned int op1)
+expected_nop_sequence(void *ip, struct ppc_inst op0, struct ppc_inst op1)
{
/*
* We expect to see:
@@ -504,7 +505,7 @@ expected_nop_sequence(void *ip, unsigned int op0, unsigned int op1)
}
#else
static int
-expected_nop_sequence(void *ip, unsigned int op0, unsigned int op1)
+expected_nop_sequence(void *ip, struct ppc_inst op0, struct ppc_inst op1)
{
/* look for patched "NOP" on ppc64 with -mprofile-kernel */
if (!ppc_inst_equal(op0, ppc_inst(PPC_INST_NOP)))
@@ -516,8 +517,8 @@ expected_nop_sequence(void *ip, unsigned int op0, unsigned int op1)
static int
__ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
{
- unsigned int op[2];
- unsigned int instr;
+ struct ppc_inst op[2];
+ struct ppc_inst instr;
void *ip = (void *)rec->ip;
unsigned long entry, ptr, tramp;
struct module *mod = rec->arch.mod;
@@ -528,7 +529,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
if (!expected_nop_sequence(ip, op[0], op[1])) {
pr_err("Unexpected call sequence at %p: %x %x\n",
- ip, op[0], op[1]);
+ ip, ppc_inst_val(op[0]), ppc_inst_val(op[1]));
return -EINVAL;
}
@@ -582,7 +583,7 @@ static int
__ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
{
int err;
- unsigned int op;
+ struct ppc_inst op;
unsigned long ip = rec->ip;
/* read where this goes */
@@ -602,7 +603,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
}
/* create the branch to the trampoline */
- err = create_branch(&op, (unsigned int *)ip,
+ err = create_branch(&op, (struct ppc_inst *)ip,
rec->arch.mod->arch.tramp, BRANCH_SET_LINK);
if (!err) {
pr_err("REL24 out of range!\n");
@@ -621,7 +622,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
static int __ftrace_make_call_kernel(struct dyn_ftrace *rec, unsigned long addr)
{
- unsigned int op;
+ struct ppc_inst op;
void *ip = (void *)rec->ip;
unsigned long tramp, entry, ptr;
@@ -669,7 +670,7 @@ static int __ftrace_make_call_kernel(struct dyn_ftrace *rec, unsigned long addr)
int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
{
unsigned long ip = rec->ip;
- unsigned int old, new;
+ struct ppc_inst old, new;
/*
* If the calling address is more that 24 bits away,
@@ -708,7 +709,7 @@ static int
__ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
unsigned long addr)
{
- unsigned int op;
+ struct ppc_inst op;
unsigned long ip = rec->ip;
unsigned long entry, ptr, tramp;
struct module *mod = rec->arch.mod;
@@ -756,7 +757,7 @@ __ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
/* The new target may be within range */
if (test_24bit_addr(ip, addr)) {
/* within range */
- if (patch_branch((unsigned int *)ip, addr, BRANCH_SET_LINK)) {
+ if (patch_branch((struct ppc_inst *)ip, addr, BRANCH_SET_LINK)) {
pr_err("REL24 out of range!\n");
return -EINVAL;
}
@@ -784,12 +785,12 @@ __ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
}
/* Ensure branch is within 24 bits */
- if (create_branch(&op, (unsigned int *)ip, tramp, BRANCH_SET_LINK)) {
+ if (create_branch(&op, (struct ppc_inst *)ip, tramp, BRANCH_SET_LINK)) {
pr_err("Branch out of range\n");
return -EINVAL;
}
- if (patch_branch((unsigned int *)ip, tramp, BRANCH_SET_LINK)) {
+ if (patch_branch((struct ppc_inst *)ip, tramp, BRANCH_SET_LINK)) {
pr_err("REL24 out of range!\n");
return -EINVAL;
}
@@ -802,7 +803,7 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
unsigned long addr)
{
unsigned long ip = rec->ip;
- unsigned int old, new;
+ struct ppc_inst old, new;
/*
* If the calling address is more that 24 bits away,
@@ -842,10 +843,10 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
int ftrace_update_ftrace_func(ftrace_func_t func)
{
unsigned long ip = (unsigned long)(&ftrace_call);
- unsigned int old, new;
+ struct ppc_inst old, new;
int ret;
- old = *(unsigned int *)&ftrace_call;
+ old = *(struct ppc_inst *)&ftrace_call;
new = ftrace_call_replace(ip, (unsigned long)func, 1);
ret = ftrace_modify_code(ip, old, new);
@@ -853,7 +854,7 @@ int ftrace_update_ftrace_func(ftrace_func_t func)
/* Also update the regs callback function */
if (!ret) {
ip = (unsigned long)(&ftrace_regs_call);
- old = *(unsigned int *)&ftrace_regs_call;
+ old = *(struct ppc_inst *)&ftrace_regs_call;
new = ftrace_call_replace(ip, (unsigned long)func, 1);
ret = ftrace_modify_code(ip, old, new);
}
@@ -927,7 +928,7 @@ int ftrace_enable_ftrace_graph_caller(void)
unsigned long ip = (unsigned long)(&ftrace_graph_call);
unsigned long addr = (unsigned long)(&ftrace_graph_caller);
unsigned long stub = (unsigned long)(&ftrace_graph_stub);
- unsigned int old, new;
+ struct ppc_inst old, new;
old = ftrace_call_replace(ip, stub, 0);
new = ftrace_call_replace(ip, addr, 0);
@@ -940,7 +941,7 @@ int ftrace_disable_ftrace_graph_caller(void)
unsigned long ip = (unsigned long)(&ftrace_graph_call);
unsigned long addr = (unsigned long)(&ftrace_graph_caller);
unsigned long stub = (unsigned long)(&ftrace_graph_stub);
- unsigned int old, new;
+ struct ppc_inst old, new;
old = ftrace_call_replace(ip, addr, 0);
new = ftrace_call_replace(ip, stub, 0);
diff --git a/arch/powerpc/kernel/vecemu.c b/arch/powerpc/kernel/vecemu.c
index c8d21e812d8c..bbf536e10902 100644
--- a/arch/powerpc/kernel/vecemu.c
+++ b/arch/powerpc/kernel/vecemu.c
@@ -261,11 +261,12 @@ static unsigned int rfin(unsigned int x)
int emulate_altivec(struct pt_regs *regs)
{
- unsigned int instr, i, word;
+ struct ppc_inst instr;
+ unsigned int i, word;
unsigned int va, vb, vc, vd;
vector128 *vrs;
- if (get_user(instr, (unsigned int __user *) regs->nip))
+ if (get_user(instr.val, (unsigned int __user *) regs->nip))
return -EFAULT;
word = ppc_inst_val(instr);
diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index 33654c6334a9..91be4a0b51cb 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -19,12 +19,12 @@
#include <asm/setup.h>
#include <asm/inst.h>
-static int __patch_instruction(unsigned int *exec_addr, unsigned int instr,
- unsigned int *patch_addr)
+static int __patch_instruction(struct ppc_inst *exec_addr, struct ppc_inst instr,
+ struct ppc_inst *patch_addr)
{
int err = 0;
- __put_user_asm(instr, patch_addr, err, "stw");
+ __put_user_asm(ppc_inst_val(instr), patch_addr, err, "stw");
if (err)
return err;
@@ -34,7 +34,7 @@ static int __patch_instruction(unsigned int *exec_addr, unsigned int instr,
return 0;
}
-int raw_patch_instruction(unsigned int *addr, unsigned int instr)
+int raw_patch_instruction(struct ppc_inst *addr, struct ppc_inst instr)
{
return __patch_instruction(addr, instr, addr);
}
@@ -137,10 +137,10 @@ static inline int unmap_patch_area(unsigned long addr)
return 0;
}
-static int do_patch_instruction(unsigned int *addr, unsigned int instr)
+static int do_patch_instruction(struct ppc_inst *addr, struct ppc_inst instr)
{
int err;
- unsigned int *patch_addr = NULL;
+ struct ppc_inst *patch_addr = NULL;
unsigned long flags;
unsigned long text_poke_addr;
unsigned long kaddr = (unsigned long)addr;
@@ -177,14 +177,14 @@ static int do_patch_instruction(unsigned int *addr, unsigned int instr)
}
#else /* !CONFIG_STRICT_KERNEL_RWX */
-static int do_patch_instruction(unsigned int *addr, unsigned int instr)
+static int do_patch_instruction(struct ppc_inst *addr, struct ppc_inst instr)
{
return raw_patch_instruction(addr, instr);
}
#endif /* CONFIG_STRICT_KERNEL_RWX */
-int patch_instruction(unsigned int *addr, unsigned int instr)
+int patch_instruction(struct ppc_inst *addr, struct ppc_inst instr)
{
/* Make sure we aren't patching a freed init section */
if (init_mem_is_free && init_section_contains(addr, 4)) {
@@ -195,9 +195,9 @@ int patch_instruction(unsigned int *addr, unsigned int instr)
}
NOKPROBE_SYMBOL(patch_instruction);
-int patch_branch(unsigned int *addr, unsigned long target, int flags)
+int patch_branch(struct ppc_inst *addr, unsigned long target, int flags)
{
- unsigned int instr;
+ struct ppc_inst instr;
create_branch(&instr, addr, target, flags);
return patch_instruction(addr, instr);
@@ -229,7 +229,7 @@ bool is_offset_in_branch_range(long offset)
* Helper to check if a given instruction is a conditional branch
* Derived from the conditional checks in analyse_instr()
*/
-bool is_conditional_branch(unsigned int instr)
+bool is_conditional_branch(struct ppc_inst instr)
{
unsigned int opcode = ppc_inst_opcode(instr);
@@ -247,13 +247,13 @@ bool is_conditional_branch(unsigned int instr)
}
NOKPROBE_SYMBOL(is_conditional_branch);
-int create_branch(unsigned int *instr,
- const unsigned int *addr,
+int create_branch(struct ppc_inst *instr,
+ const struct ppc_inst *addr,
unsigned long target, int flags)
{
long offset;
- *instr = 0;
+ *instr = ppc_inst(0);
offset = target;
if (! (flags & BRANCH_ABSOLUTE))
offset = offset - (unsigned long)addr;
@@ -263,12 +263,12 @@ int create_branch(unsigned int *instr,
return 1;
/* Mask out the flags and target, so they don't step on each other. */
- *instr = 0x48000000 | (flags & 0x3) | (offset & 0x03FFFFFC);
+ *instr = ppc_inst(0x48000000 | (flags & 0x3) | (offset & 0x03FFFFFC));
return 0;
}
-int create_cond_branch(unsigned int *instr, const unsigned int *addr,
+int create_cond_branch(struct ppc_inst *instr, const struct ppc_inst *addr,
unsigned long target, int flags)
{
long offset;
@@ -282,27 +282,27 @@ int create_cond_branch(unsigned int *instr, const unsigned int *addr,
return 1;
/* Mask out the flags and target, so they don't step on each other. */
- *instr = 0x40000000 | (flags & 0x3FF0003) | (offset & 0xFFFC);
+ *instr = ppc_inst(0x40000000 | (flags & 0x3FF0003) | (offset & 0xFFFC));
return 0;
}
-static unsigned int branch_opcode(unsigned int instr)
+static unsigned int branch_opcode(struct ppc_inst instr)
{
return ppc_inst_opcode(instr) & 0x3F;
}
-static int instr_is_branch_iform(unsigned int instr)
+static int instr_is_branch_iform(struct ppc_inst instr)
{
return branch_opcode(instr) == 18;
}
-static int instr_is_branch_bform(unsigned int instr)
+static int instr_is_branch_bform(struct ppc_inst instr)
{
return branch_opcode(instr) == 16;
}
-int instr_is_relative_branch(unsigned int instr)
+int instr_is_relative_branch(struct ppc_inst instr)
{
if (ppc_inst_val(instr) & BRANCH_ABSOLUTE)
return 0;
@@ -310,12 +310,12 @@ int instr_is_relative_branch(unsigned int instr)
return instr_is_branch_iform(instr) || instr_is_branch_bform(instr);
}
-int instr_is_relative_link_branch(unsigned int instr)
+int instr_is_relative_link_branch(struct ppc_inst instr)
{
return instr_is_relative_branch(instr) && (ppc_inst_val(instr) & BRANCH_SET_LINK);
}
-static unsigned long branch_iform_target(const unsigned int *instr)
+static unsigned long branch_iform_target(const struct ppc_inst *instr)
{
signed long imm;
@@ -331,7 +331,7 @@ static unsigned long branch_iform_target(const unsigned int *instr)
return (unsigned long)imm;
}
-static unsigned long branch_bform_target(const unsigned int *instr)
+static unsigned long branch_bform_target(const struct ppc_inst *instr)
{
signed long imm;
@@ -347,7 +347,7 @@ static unsigned long branch_bform_target(const unsigned int *instr)
return (unsigned long)imm;
}
-unsigned long branch_target(const unsigned int *instr)
+unsigned long branch_target(const struct ppc_inst *instr)
{
if (instr_is_branch_iform(*instr))
return branch_iform_target(instr);
@@ -357,7 +357,7 @@ unsigned long branch_target(const unsigned int *instr)
return 0;
}
-int instr_is_branch_to_addr(const unsigned int *instr, unsigned long addr)
+int instr_is_branch_to_addr(const struct ppc_inst *instr, unsigned long addr)
{
if (instr_is_branch_iform(*instr) || instr_is_branch_bform(*instr))
return branch_target(instr) == addr;
@@ -365,7 +365,7 @@ int instr_is_branch_to_addr(const unsigned int *instr, unsigned long addr)
return 0;
}
-int translate_branch(unsigned int *instr, const unsigned int *dest, const unsigned int *src)
+int translate_branch(struct ppc_inst *instr, const struct ppc_inst *dest, const struct ppc_inst *src)
{
unsigned long target;
@@ -408,7 +408,7 @@ static void __init test_trampoline(void)
static void __init test_branch_iform(void)
{
int err;
- unsigned int instr;
+ struct ppc_inst instr;
unsigned long addr;
addr = (unsigned long)&instr;
@@ -483,12 +483,12 @@ static void __init test_branch_iform(void)
static void __init test_create_function_call(void)
{
- unsigned int *iptr;
+ struct ppc_inst *iptr;
unsigned long dest;
- unsigned int instr;
+ struct ppc_inst instr;
/* Check we can create a function call */
- iptr = (unsigned int *)ppc_function_entry(test_trampoline);
+ iptr = (struct ppc_inst *)ppc_function_entry(test_trampoline);
dest = ppc_function_entry(test_create_function_call);
create_branch(&instr, iptr, dest, BRANCH_SET_LINK);
patch_instruction(iptr, instr);
@@ -499,7 +499,8 @@ static void __init test_branch_bform(void)
{
int err;
unsigned long addr;
- unsigned int *iptr, instr, flags;
+ struct ppc_inst *iptr, instr;
+ unsigned int flags;
iptr = &instr;
addr = (unsigned long)iptr;
@@ -569,8 +570,8 @@ static void __init test_branch_bform(void)
static void __init test_translate_branch(void)
{
unsigned long addr;
- unsigned int *p, *q;
- unsigned int instr;
+ struct ppc_inst *p, *q;
+ struct ppc_inst instr;
void *buf;
buf = vmalloc(PAGE_ALIGN(0x2000000 + 1));
diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c
index 6e7479b8887a..8c5d0db77013 100644
--- a/arch/powerpc/lib/feature-fixups.c
+++ b/arch/powerpc/lib/feature-fixups.c
@@ -32,26 +32,26 @@ struct fixup_entry {
long alt_end_off;
};
-static unsigned int *calc_addr(struct fixup_entry *fcur, long offset)
+static struct ppc_inst *calc_addr(struct fixup_entry *fcur, long offset)
{
/*
* We store the offset to the code as a negative offset from
* the start of the alt_entry, to support the VDSO. This
* routine converts that back into an actual address.
*/
- return (unsigned int *)((unsigned long)fcur + offset);
+ return (struct ppc_inst *)((unsigned long)fcur + offset);
}
-static int patch_alt_instruction(unsigned int *src, unsigned int *dest,
- unsigned int *alt_start, unsigned int *alt_end)
+static int patch_alt_instruction(struct ppc_inst *src, struct ppc_inst *dest,
+ struct ppc_inst *alt_start, struct ppc_inst *alt_end)
{
int err;
- unsigned int instr;
+ struct ppc_inst instr;
instr = *src;
if (instr_is_relative_branch(*src)) {
- unsigned int *target = (unsigned int *)branch_target(src);
+ struct ppc_inst *target = (struct ppc_inst *)branch_target(src);
/* Branch within the section doesn't need translating */
if (target < alt_start || target > alt_end) {
@@ -68,7 +68,7 @@ static int patch_alt_instruction(unsigned int *src, unsigned int *dest,
static int patch_feature_section(unsigned long value, struct fixup_entry *fcur)
{
- unsigned int *start, *end, *alt_start, *alt_end, *src, *dest;
+ struct ppc_inst *start, *end, *alt_start, *alt_end, *src, *dest;
start = calc_addr(fcur, fcur->start_off);
end = calc_addr(fcur, fcur->end_off);
@@ -147,15 +147,15 @@ static void do_stf_entry_barrier_fixups(enum stf_barrier_type types)
pr_devel("patching dest %lx\n", (unsigned long)dest);
- patch_instruction(dest, ppc_inst(instrs[0]));
+ patch_instruction((struct ppc_inst *)dest, ppc_inst(instrs[0]));
if (types & STF_BARRIER_FALLBACK)
- patch_branch(dest + 1, (unsigned long)&stf_barrier_fallback,
+ patch_branch((struct ppc_inst *)(dest + 1), (unsigned long)&stf_barrier_fallback,
BRANCH_SET_LINK);
else
- patch_instruction(dest + 1, ppc_inst(instrs[1]));
+ patch_instruction((struct ppc_inst *)(dest + 1), ppc_inst(instrs[1]));
- patch_instruction(dest + 2, ppc_inst(instrs[2]));
+ patch_instruction((struct ppc_inst *)(dest + 2), ppc_inst(instrs[2]));
}
printk(KERN_DEBUG "stf-barrier: patched %d entry locations (%s barrier)\n", i,
@@ -208,12 +208,12 @@ static void do_stf_exit_barrier_fixups(enum stf_barrier_type types)
pr_devel("patching dest %lx\n", (unsigned long)dest);
- patch_instruction(dest, ppc_inst(instrs[0]));
- patch_instruction(dest + 1, ppc_inst(instrs[1]));
- patch_instruction(dest + 2, ppc_inst(instrs[2]));
- patch_instruction(dest + 3, ppc_inst(instrs[3]));
- patch_instruction(dest + 4, ppc_inst(instrs[4]));
- patch_instruction(dest + 5, ppc_inst(instrs[5]));
+ patch_instruction((struct ppc_inst *)dest, ppc_inst(instrs[0]));
+ patch_instruction((struct ppc_inst *)(dest + 1), ppc_inst(instrs[1]));
+ patch_instruction((struct ppc_inst *)(dest + 2), ppc_inst(instrs[2]));
+ patch_instruction((struct ppc_inst *)(dest + 3), ppc_inst(instrs[3]));
+ patch_instruction((struct ppc_inst *)(dest + 4), ppc_inst(instrs[4]));
+ patch_instruction((struct ppc_inst *)(dest + 5), ppc_inst(instrs[5]));
}
printk(KERN_DEBUG "stf-barrier: patched %d exit locations (%s barrier)\n", i,
(types == STF_BARRIER_NONE) ? "no" :
@@ -261,9 +261,9 @@ void do_rfi_flush_fixups(enum l1d_flush_type types)
pr_devel("patching dest %lx\n", (unsigned long)dest);
- patch_instruction(dest, ppc_inst(instrs[0]));
- patch_instruction(dest + 1, ppc_inst(instrs[1]));
- patch_instruction(dest + 2, ppc_inst(instrs[2]));
+ patch_instruction((struct ppc_inst *)dest, ppc_inst(instrs[0]));
+ patch_instruction((struct ppc_inst *)(dest + 1), ppc_inst(instrs[1]));
+ patch_instruction((struct ppc_inst *)(dest + 2), ppc_inst(instrs[2]));
}
printk(KERN_DEBUG "rfi-flush: patched %d locations (%s flush)\n", i,
@@ -296,7 +296,7 @@ void do_barrier_nospec_fixups_range(bool enable, void *fixup_start, void *fixup_
dest = (void *)start + *start;
pr_devel("patching dest %lx\n", (unsigned long)dest);
- patch_instruction(dest, ppc_inst(instr));
+ patch_instruction((struct ppc_inst *)dest, ppc_inst(instr));
}
printk(KERN_DEBUG "barrier-nospec: patched %d locations\n", i);
@@ -339,8 +339,8 @@ void do_barrier_nospec_fixups_range(bool enable, void *fixup_start, void *fixup_
dest = (void *)start + *start;
pr_devel("patching dest %lx\n", (unsigned long)dest);
- patch_instruction(dest, ppc_inst(instr[0]));
- patch_instruction(dest + 1, ppc_inst(instr[1]));
+ patch_instruction((struct ppc_inst *)dest, ppc_inst(instr[0]));
+ patch_instruction((struct ppc_inst *)(dest + 1), ppc_inst(instr[1]));
}
printk(KERN_DEBUG "barrier-nospec: patched %d locations\n", i);
@@ -373,7 +373,7 @@ void do_btb_flush_fixups(void)
void do_lwsync_fixups(unsigned long value, void *fixup_start, void *fixup_end)
{
long *start, *end;
- unsigned int *dest;
+ struct ppc_inst *dest;
if (!(value & CPU_FTR_LWSYNC))
return ;
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index 26e37176692e..52ddd3122dc8 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -1163,7 +1163,7 @@ static nokprobe_inline int trap_compare(long v1, long v2)
* otherwise.
*/
int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
- unsigned int instr)
+ struct ppc_inst instr)
{
unsigned int opcode, ra, rb, rc, rd, spr, u;
unsigned long int imm;
@@ -3103,7 +3103,7 @@ NOKPROBE_SYMBOL(emulate_loadstore);
* or -1 if the instruction is one that should not be stepped,
* such as an rfid, or a mtmsrd that would clear MSR_RI.
*/
-int emulate_step(struct pt_regs *regs, unsigned int instr)
+int emulate_step(struct pt_regs *regs, struct ppc_inst instr)
{
struct instruction_op op;
int r, err, type;
diff --git a/arch/powerpc/lib/test_emulate_step.c b/arch/powerpc/lib/test_emulate_step.c
index 16387a9bfda0..60b159b60545 100644
--- a/arch/powerpc/lib/test_emulate_step.c
+++ b/arch/powerpc/lib/test_emulate_step.c
@@ -461,7 +461,7 @@ struct compute_test {
struct {
char *descr;
unsigned long flags;
- unsigned int instr;
+ struct ppc_inst instr;
struct pt_regs regs;
} subtests[MAX_SUBTESTS + 1];
};
@@ -842,7 +842,7 @@ static struct compute_test compute_tests[] = {
};
static int __init emulate_compute_instr(struct pt_regs *regs,
- unsigned int instr)
+ struct ppc_inst instr)
{
struct instruction_op op;
@@ -860,7 +860,7 @@ static int __init emulate_compute_instr(struct pt_regs *regs,
}
static int __init execute_compute_instr(struct pt_regs *regs,
- unsigned int instr)
+ struct ppc_inst instr)
{
extern int exec_instr(struct pt_regs *regs);
extern s32 patch__exec_instr;
@@ -891,7 +891,8 @@ static void __init run_tests_compute(void)
unsigned long flags;
struct compute_test *test;
struct pt_regs *regs, exp, got;
- unsigned int i, j, k, instr;
+ unsigned int i, j, k;
+ struct ppc_inst instr;
bool ignore_gpr, ignore_xer, ignore_ccr, passed;
for (i = 0; i < ARRAY_SIZE(compute_tests); i++) {
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 3086055bf681..2d2580a4bfb5 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -421,14 +421,14 @@ static __u64 power_pmu_bhrb_to(u64 addr)
if (probe_kernel_read(&instr, (void *)addr, sizeof(instr)))
return 0;
- return branch_target(&instr);
+ return branch_target((struct ppc_inst *)&instr);
}
/* Userspace: need copy instruction here then translate it */
if (probe_user_read(&instr, (unsigned int __user *)addr, sizeof(instr)))
return 0;
- target = branch_target(&instr);
+ target = branch_target((struct ppc_inst *)&instr);
if ((!target) || (instr & BRANCH_ABSOLUTE))
return target;
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index f6c87d3d53ea..e3d8e1b8ce01 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -99,7 +99,7 @@ static long *xmon_fault_jmp[NR_CPUS];
/* Breakpoint stuff */
struct bpt {
unsigned long address;
- unsigned int *instr;
+ struct ppc_inst *instr;
atomic_t ref_count;
int enabled;
unsigned long pad;
@@ -117,7 +117,7 @@ static unsigned bpinstr = 0x7fe00008; /* trap */
#define BP_NUM(bp) ((bp) - bpts + 1)
-#define BPT_SIZE (sizeof(unsigned int) * 2)
+#define BPT_SIZE (sizeof(struct ppc_inst) * 2)
#define BPT_WORDS (BPT_SIZE / sizeof(unsigned int))
extern unsigned int bpt_table[NBPTS * BPT_WORDS];
@@ -879,8 +879,8 @@ static struct bpt *new_breakpoint(unsigned long a)
for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
if (!bp->enabled && atomic_read(&bp->ref_count) == 0) {
bp->address = a;
- bp->instr = bpt_table + ((bp - bpts) * BPT_WORDS);
- patch_instruction(bp->instr + 1, bpinstr);
+ bp->instr = (void *)(bpt_table + ((bp - bpts) * BPT_WORDS));
+ patch_instruction(bp->instr + 1, ppc_inst(bpinstr));
return bp;
}
}
@@ -892,7 +892,7 @@ static struct bpt *new_breakpoint(unsigned long a)
static void insert_bpts(void)
{
int i;
- unsigned int instr;
+ struct ppc_inst instr;
struct bpt *bp;
bp = bpts;
@@ -914,8 +914,8 @@ static void insert_bpts(void)
patch_instruction(bp->instr, instr);
if (bp->enabled & BP_CIABR)
continue;
- if (patch_instruction((unsigned int *)bp->address,
- bpinstr) != 0) {
+ if (patch_instruction((struct ppc_inst *)bp->address,
+ ppc_inst(bpinstr)) != 0) {
printf("Couldn't write instruction at %lx, "
"disabling breakpoint there\n", bp->address);
bp->enabled &= ~BP_TRAP;
@@ -943,7 +943,7 @@ static void remove_bpts(void)
{
int i;
struct bpt *bp;
- unsigned instr;
+ struct ppc_inst instr;
bp = bpts;
for (i = 0; i < NBPTS; ++i, ++bp) {
@@ -952,7 +952,7 @@ static void remove_bpts(void)
if (mread(bp->address, &instr, 4) == 4
&& ppc_inst_equal(instr, ppc_inst(bpinstr))
&& patch_instruction(
- (unsigned int *)bp->address, bp->instr[0]) != 0)
+ (struct ppc_inst *)bp->address, bp->instr[0]) != 0)
printf("Couldn't remove breakpoint at %lx\n",
bp->address);
}
@@ -1159,7 +1159,7 @@ static int do_step(struct pt_regs *regs)
*/
static int do_step(struct pt_regs *regs)
{
- unsigned int instr;
+ struct ppc_inst instr;
int stepped;
force_enable_xmon();
@@ -1325,7 +1325,7 @@ csum(void)
*/
static long check_bp_loc(unsigned long addr)
{
- unsigned int instr;
+ struct ppc_inst instr;
addr &= ~3;
if (!is_kernel_addr(addr)) {
@@ -2846,7 +2846,7 @@ generic_inst_dump(unsigned long adr, long count, int praddr,
{
int nr, dotted;
unsigned long first_adr;
- unsigned int inst, last_inst = ppc_inst(0);
+ struct ppc_inst inst, last_inst = ppc_inst(0);
unsigned char val[4];
dotted = 0;
--
2.17.1
^ permalink raw reply related [flat|nested] 71+ messages in thread
* [PATCH v5 10/21] powerpc: Use a function for reading instructions
2020-04-06 8:09 [PATCH v5 00/21] Initial Prefixed Instruction support Jordan Niethe
` (8 preceding siblings ...)
2020-04-06 8:09 ` [PATCH v5 09/21] powerpc: Use a datatype for instructions Jordan Niethe
@ 2020-04-06 8:09 ` Jordan Niethe
2020-04-07 10:42 ` Balamuruhan S
2020-04-06 8:09 ` [PATCH v5 11/21] powerpc: Define and use __get_user_instr{, inatomic}() Jordan Niethe
` (11 subsequent siblings)
21 siblings, 1 reply; 71+ messages in thread
From: Jordan Niethe @ 2020-04-06 8:09 UTC (permalink / raw)
To: linuxppc-dev; +Cc: alistair, npiggin, bala24, Jordan Niethe, dja
Prefixed instructions will mean there are instructions of different
length. As a result dereferencing a pointer to an instruction will not
necessarily give the desired result. Introduce a function for reading
instructions from memory into the instruction data type.
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v4: New to series
v5: - Rename read_inst() -> probe_kernel_read_inst()
- No longer modify uprobe probe type in this patch
---
arch/powerpc/include/asm/inst.h | 5 +++++
arch/powerpc/kernel/kprobes.c | 11 ++++------
arch/powerpc/kernel/mce_power.c | 2 +-
arch/powerpc/kernel/optprobes.c | 4 ++--
arch/powerpc/kernel/trace/ftrace.c | 33 +++++++++++++++++++-----------
arch/powerpc/lib/code-patching.c | 23 ++++++++++-----------
arch/powerpc/lib/feature-fixups.c | 2 +-
arch/powerpc/xmon/xmon.c | 6 +++---
8 files changed, 48 insertions(+), 38 deletions(-)
diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h
index a71decf5f871..369b35ce964c 100644
--- a/arch/powerpc/include/asm/inst.h
+++ b/arch/powerpc/include/asm/inst.h
@@ -27,6 +27,11 @@ static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
return ppc_inst(swab32(ppc_inst_val(x)));
}
+static inline struct ppc_inst ppc_inst_read(const struct ppc_inst *ptr)
+{
+ return *ptr;
+}
+
static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
{
return !memcmp(&x, &y, sizeof(struct ppc_inst));
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index 9ed996cb0589..ff53e5ef7e40 100644
--- a/arch/powerpc/kernel/kprobes.c
+++ b/arch/powerpc/kernel/kprobes.c
@@ -106,7 +106,7 @@ kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset)
int arch_prepare_kprobe(struct kprobe *p)
{
int ret = 0;
- struct ppc_inst insn = *(struct ppc_inst *)p->addr;
+ struct ppc_inst insn = ppc_inst_read((struct ppc_inst *)p->addr);
if ((unsigned long)p->addr & 0x03) {
printk("Attempt to register kprobe at an unaligned address\n");
@@ -125,11 +125,8 @@ int arch_prepare_kprobe(struct kprobe *p)
}
if (!ret) {
- memcpy(p->ainsn.insn, p->addr,
- MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
- p->opcode = *p->addr;
- flush_icache_range((unsigned long)p->ainsn.insn,
- (unsigned long)p->ainsn.insn + sizeof(kprobe_opcode_t));
+ patch_instruction((struct ppc_inst *)p->ainsn.insn, insn);
+ p->opcode = ppc_inst_val(insn);
}
p->ainsn.boostable = 0;
@@ -217,7 +214,7 @@ NOKPROBE_SYMBOL(arch_prepare_kretprobe);
static int try_to_emulate(struct kprobe *p, struct pt_regs *regs)
{
int ret;
- struct ppc_inst insn = *(struct ppc_inst *)p->ainsn.insn;
+ struct ppc_inst insn = ppc_inst_read((struct ppc_inst *)p->ainsn.insn);
/* regs->nip is also adjusted if emulate_step returns 1 */
ret = emulate_step(regs, insn);
diff --git a/arch/powerpc/kernel/mce_power.c b/arch/powerpc/kernel/mce_power.c
index 7118b46a6543..859b602fa270 100644
--- a/arch/powerpc/kernel/mce_power.c
+++ b/arch/powerpc/kernel/mce_power.c
@@ -374,7 +374,7 @@ static int mce_find_instr_ea_and_phys(struct pt_regs *regs, uint64_t *addr,
pfn = addr_to_pfn(regs, regs->nip);
if (pfn != ULONG_MAX) {
instr_addr = (pfn << PAGE_SHIFT) + (regs->nip & ~PAGE_MASK);
- instr = *(struct ppc_inst *)(instr_addr);
+ instr = ppc_inst_read((struct ppc_inst *)instr_addr);
if (!analyse_instr(&op, &tmp, instr)) {
pfn = addr_to_pfn(regs, op.ea);
*addr = op.ea;
diff --git a/arch/powerpc/kernel/optprobes.c b/arch/powerpc/kernel/optprobes.c
index b61bbcee84f4..684640b8fa2e 100644
--- a/arch/powerpc/kernel/optprobes.c
+++ b/arch/powerpc/kernel/optprobes.c
@@ -100,8 +100,8 @@ static unsigned long can_optimize(struct kprobe *p)
* Ensure that the instruction is not a conditional branch,
* and that can be emulated.
*/
- if (!is_conditional_branch(*(struct ppc_inst *)p->ainsn.insn) &&
- analyse_instr(&op, ®s, *(struct ppc_inst *)p->ainsn.insn) == 1) {
+ if (!is_conditional_branch(ppc_inst_read((struct ppc_inst *)p->ainsn.insn)) &&
+ analyse_instr(&op, ®s, ppc_inst_read((struct ppc_inst *)p->ainsn.insn)) == 1) {
emulate_update_regs(®s, &op);
nip = regs.nip;
}
diff --git a/arch/powerpc/kernel/trace/ftrace.c b/arch/powerpc/kernel/trace/ftrace.c
index 442c62fb68ff..e78742613b36 100644
--- a/arch/powerpc/kernel/trace/ftrace.c
+++ b/arch/powerpc/kernel/trace/ftrace.c
@@ -41,6 +41,12 @@
#define NUM_FTRACE_TRAMPS 8
static unsigned long ftrace_tramps[NUM_FTRACE_TRAMPS];
+static long
+probe_kernel_read_inst(struct ppc_inst *inst, const void *src)
+{
+ return probe_kernel_read((void *)inst, src, MCOUNT_INSN_SIZE);
+}
+
static struct ppc_inst
ftrace_call_replace(unsigned long ip, unsigned long addr, int link)
{
@@ -68,7 +74,7 @@ ftrace_modify_code(unsigned long ip, struct ppc_inst old, struct ppc_inst new)
*/
/* read the text we want to modify */
- if (probe_kernel_read(&replaced, (void *)ip, MCOUNT_INSN_SIZE))
+ if (probe_kernel_read_inst(&replaced, (void *)ip))
return -EFAULT;
/* Make sure it is what we expect it to be */
@@ -130,7 +136,7 @@ __ftrace_make_nop(struct module *mod,
struct ppc_inst op, pop;
/* read where this goes */
- if (probe_kernel_read(&op, (void *)ip, sizeof(int))) {
+ if (probe_kernel_read_inst(&op, (void *)ip)) {
pr_err("Fetching opcode failed.\n");
return -EFAULT;
}
@@ -164,7 +170,7 @@ __ftrace_make_nop(struct module *mod,
/* When using -mkernel_profile there is no load to jump over */
pop = ppc_inst(PPC_INST_NOP);
- if (probe_kernel_read(&op, (void *)(ip - 4), 4)) {
+ if (probe_kernel_read_inst(&op, (void *)(ip - 4))) {
pr_err("Fetching instruction at %lx failed.\n", ip - 4);
return -EFAULT;
}
@@ -196,7 +202,7 @@ __ftrace_make_nop(struct module *mod,
* Check what is in the next instruction. We can see ld r2,40(r1), but
* on first pass after boot we will see mflr r0.
*/
- if (probe_kernel_read(&op, (void *)(ip+4), MCOUNT_INSN_SIZE)) {
+ if (probe_kernel_read_inst(&op, (void *)(ip+4))) {
pr_err("Fetching op failed.\n");
return -EFAULT;
}
@@ -348,7 +354,7 @@ static int setup_mcount_compiler_tramp(unsigned long tramp)
return -1;
/* New trampoline -- read where this goes */
- if (probe_kernel_read(&op, (void *)tramp, sizeof(int))) {
+ if (probe_kernel_read_inst(&op, (void *)tramp)) {
pr_debug("Fetching opcode failed.\n");
return -1;
}
@@ -398,7 +404,7 @@ static int __ftrace_make_nop_kernel(struct dyn_ftrace *rec, unsigned long addr)
struct ppc_inst op;
/* Read where this goes */
- if (probe_kernel_read(&op, (void *)ip, sizeof(int))) {
+ if (probe_kernel_read_inst(&op, (void *)ip)) {
pr_err("Fetching opcode failed.\n");
return -EFAULT;
}
@@ -524,7 +530,10 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
struct module *mod = rec->arch.mod;
/* read where this goes */
- if (probe_kernel_read(op, ip, sizeof(op)))
+ if (probe_kernel_read_inst(op, ip))
+ return -EFAULT;
+
+ if (probe_kernel_read_inst(op + 1, ip + 4))
return -EFAULT;
if (!expected_nop_sequence(ip, op[0], op[1])) {
@@ -587,7 +596,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
unsigned long ip = rec->ip;
/* read where this goes */
- if (probe_kernel_read(&op, (void *)ip, MCOUNT_INSN_SIZE))
+ if (probe_kernel_read_inst(&op, (void *)ip))
return -EFAULT;
/* It should be pointing to a nop */
@@ -643,7 +652,7 @@ static int __ftrace_make_call_kernel(struct dyn_ftrace *rec, unsigned long addr)
}
/* Make sure we have a nop */
- if (probe_kernel_read(&op, ip, sizeof(op))) {
+ if (probe_kernel_read_inst(&op, ip)) {
pr_err("Unable to read ftrace location %p\n", ip);
return -EFAULT;
}
@@ -721,7 +730,7 @@ __ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
}
/* read where this goes */
- if (probe_kernel_read(&op, (void *)ip, sizeof(int))) {
+ if (probe_kernel_read_inst(&op, (void *)ip)) {
pr_err("Fetching opcode failed.\n");
return -EFAULT;
}
@@ -846,7 +855,7 @@ int ftrace_update_ftrace_func(ftrace_func_t func)
struct ppc_inst old, new;
int ret;
- old = *(struct ppc_inst *)&ftrace_call;
+ old = ppc_inst_read((struct ppc_inst *)&ftrace_call);
new = ftrace_call_replace(ip, (unsigned long)func, 1);
ret = ftrace_modify_code(ip, old, new);
@@ -854,7 +863,7 @@ int ftrace_update_ftrace_func(ftrace_func_t func)
/* Also update the regs callback function */
if (!ret) {
ip = (unsigned long)(&ftrace_regs_call);
- old = *(struct ppc_inst *)&ftrace_regs_call;
+ old = ppc_inst_read((struct ppc_inst *)&ftrace_regs_call);
new = ftrace_call_replace(ip, (unsigned long)func, 1);
ret = ftrace_modify_code(ip, old, new);
}
diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index 91be4a0b51cb..ba08f3815d00 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -349,9 +349,9 @@ static unsigned long branch_bform_target(const struct ppc_inst *instr)
unsigned long branch_target(const struct ppc_inst *instr)
{
- if (instr_is_branch_iform(*instr))
+ if (instr_is_branch_iform(ppc_inst_read(instr)))
return branch_iform_target(instr);
- else if (instr_is_branch_bform(*instr))
+ else if (instr_is_branch_bform(ppc_inst_read(instr)))
return branch_bform_target(instr);
return 0;
@@ -359,7 +359,7 @@ unsigned long branch_target(const struct ppc_inst *instr)
int instr_is_branch_to_addr(const struct ppc_inst *instr, unsigned long addr)
{
- if (instr_is_branch_iform(*instr) || instr_is_branch_bform(*instr))
+ if (instr_is_branch_iform(ppc_inst_read(instr)) || instr_is_branch_bform(ppc_inst_read(instr)))
return branch_target(instr) == addr;
return 0;
@@ -368,13 +368,12 @@ int instr_is_branch_to_addr(const struct ppc_inst *instr, unsigned long addr)
int translate_branch(struct ppc_inst *instr, const struct ppc_inst *dest, const struct ppc_inst *src)
{
unsigned long target;
-
target = branch_target(src);
- if (instr_is_branch_iform(*src))
- return create_branch(instr, dest, target, ppc_inst_val(*src));
- else if (instr_is_branch_bform(*src))
- return create_cond_branch(instr, dest, target, ppc_inst_val(*src));
+ if (instr_is_branch_iform(ppc_inst_read(src)))
+ return create_branch(instr, dest, target, ppc_inst_val(ppc_inst_read(src)));
+ else if (instr_is_branch_bform(ppc_inst_read(src)))
+ return create_cond_branch(instr, dest, target, ppc_inst_val(ppc_inst_read(src)));
return 1;
}
@@ -598,7 +597,7 @@ static void __init test_translate_branch(void)
patch_instruction(q, instr);
check(instr_is_branch_to_addr(p, addr));
check(instr_is_branch_to_addr(q, addr));
- check(ppc_inst_equal(*q, ppc_inst(0x4a000000)));
+ check(ppc_inst_equal(ppc_inst_read(q), ppc_inst(0x4a000000)));
/* Maximum positive case, move x to x - 32 MB + 4 */
p = buf + 0x2000000;
@@ -609,7 +608,7 @@ static void __init test_translate_branch(void)
patch_instruction(q, instr);
check(instr_is_branch_to_addr(p, addr));
check(instr_is_branch_to_addr(q, addr));
- check(ppc_inst_equal(*q, ppc_inst(0x49fffffc)));
+ check(ppc_inst_equal(ppc_inst_read(q), ppc_inst(0x49fffffc)));
/* Jump to x + 16 MB moved to x + 20 MB */
p = buf;
@@ -655,7 +654,7 @@ static void __init test_translate_branch(void)
patch_instruction(q, instr);
check(instr_is_branch_to_addr(p, addr));
check(instr_is_branch_to_addr(q, addr));
- check(ppc_inst_equal(*q, ppc_inst(0x43ff8000)));
+ check(ppc_inst_equal(ppc_inst_read(q), ppc_inst(0x43ff8000)));
/* Maximum positive case, move x to x - 32 KB + 4 */
p = buf + 0x8000;
@@ -667,7 +666,7 @@ static void __init test_translate_branch(void)
patch_instruction(q, instr);
check(instr_is_branch_to_addr(p, addr));
check(instr_is_branch_to_addr(q, addr));
- check(ppc_inst_equal(*q, ppc_inst(0x43ff7ffc)));
+ check(ppc_inst_equal(ppc_inst_read(q), ppc_inst(0x43ff7ffc)));
/* Jump to x + 12 KB moved to x + 20 KB */
p = buf;
diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c
index 8c5d0db77013..f00dd13b1c3c 100644
--- a/arch/powerpc/lib/feature-fixups.c
+++ b/arch/powerpc/lib/feature-fixups.c
@@ -48,7 +48,7 @@ static int patch_alt_instruction(struct ppc_inst *src, struct ppc_inst *dest,
int err;
struct ppc_inst instr;
- instr = *src;
+ instr = ppc_inst_read(src);
if (instr_is_relative_branch(*src)) {
struct ppc_inst *target = (struct ppc_inst *)branch_target(src);
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index e3d8e1b8ce01..5e3949322a6c 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -705,13 +705,13 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT)) {
bp = at_breakpoint(regs->nip);
if (bp != NULL) {
- int stepped = emulate_step(regs, bp->instr[0]);
+ int stepped = emulate_step(regs, ppc_inst_read(bp->instr));
if (stepped == 0) {
regs->nip = (unsigned long) &bp->instr[0];
atomic_inc(&bp->ref_count);
} else if (stepped < 0) {
printf("Couldn't single-step %s instruction\n",
- (IS_RFID(bp->instr[0])? "rfid": "mtmsrd"));
+ IS_RFID(ppc_inst_read(bp->instr))? "rfid": "mtmsrd");
}
}
}
@@ -952,7 +952,7 @@ static void remove_bpts(void)
if (mread(bp->address, &instr, 4) == 4
&& ppc_inst_equal(instr, ppc_inst(bpinstr))
&& patch_instruction(
- (struct ppc_inst *)bp->address, bp->instr[0]) != 0)
+ (struct ppc_inst *)bp->address, ppc_inst_read(bp->instr)) != 0)
printf("Couldn't remove breakpoint at %lx\n",
bp->address);
}
--
2.17.1
^ permalink raw reply related [flat|nested] 71+ messages in thread
* [PATCH v5 11/21] powerpc: Define and use __get_user_instr{, inatomic}()
2020-04-06 8:09 [PATCH v5 00/21] Initial Prefixed Instruction support Jordan Niethe
` (9 preceding siblings ...)
2020-04-06 8:09 ` [PATCH v5 10/21] powerpc: Use a function for reading instructions Jordan Niethe
@ 2020-04-06 8:09 ` Jordan Niethe
2020-04-07 10:48 ` Balamuruhan S
2020-04-06 8:09 ` [PATCH v5 12/21] powerpc: Introduce a function for reporting instruction length Jordan Niethe
` (10 subsequent siblings)
21 siblings, 1 reply; 71+ messages in thread
From: Jordan Niethe @ 2020-04-06 8:09 UTC (permalink / raw)
To: linuxppc-dev; +Cc: alistair, npiggin, bala24, Jordan Niethe, dja
Define specific __get_user_instr() and __get_user_instr_inatomic()
macros for reading instructions from user space.
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
arch/powerpc/include/asm/uaccess.h | 5 +++++
arch/powerpc/kernel/align.c | 2 +-
arch/powerpc/kernel/hw_breakpoint.c | 2 +-
arch/powerpc/kernel/vecemu.c | 2 +-
4 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h
index 2f500debae21..c0a35e4586a5 100644
--- a/arch/powerpc/include/asm/uaccess.h
+++ b/arch/powerpc/include/asm/uaccess.h
@@ -105,6 +105,11 @@ 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)))
+#define __get_user_instr(x, ptr) \
+ __get_user_nocheck((x).val, (u32 *)(ptr), sizeof(u32), true)
+
+#define __get_user_instr_inatomic(x, ptr) \
+ __get_user_nosleep((x).val, (u32 *)(ptr), sizeof(u32))
extern long __put_user_bad(void);
/*
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
index 66a6d1de7799..65cdfd41e3a1 100644
--- a/arch/powerpc/kernel/align.c
+++ b/arch/powerpc/kernel/align.c
@@ -304,7 +304,7 @@ int fix_alignment(struct pt_regs *regs)
*/
CHECK_FULL_REGS(regs);
- if (unlikely(__get_user(instr.val, (unsigned int __user *)regs->nip)))
+ if (unlikely(__get_user_instr(instr, (void __user *)regs->nip)))
return -EFAULT;
if ((regs->msr & MSR_LE) != (MSR_KERNEL & MSR_LE)) {
/* We don't handle PPC little-endian any more... */
diff --git a/arch/powerpc/kernel/hw_breakpoint.c b/arch/powerpc/kernel/hw_breakpoint.c
index 542f65ccf68b..cebab14e2788 100644
--- a/arch/powerpc/kernel/hw_breakpoint.c
+++ b/arch/powerpc/kernel/hw_breakpoint.c
@@ -249,7 +249,7 @@ static bool stepping_handler(struct pt_regs *regs, struct perf_event *bp,
struct instruction_op op;
unsigned long addr = info->address;
- if (__get_user_inatomic(instr.val, (unsigned int *)regs->nip))
+ if (__get_user_instr_inatomic(instr, (void __user *)regs->nip))
goto fail;
ret = analyse_instr(&op, regs, instr);
diff --git a/arch/powerpc/kernel/vecemu.c b/arch/powerpc/kernel/vecemu.c
index bbf536e10902..c82ede46d71b 100644
--- a/arch/powerpc/kernel/vecemu.c
+++ b/arch/powerpc/kernel/vecemu.c
@@ -266,7 +266,7 @@ int emulate_altivec(struct pt_regs *regs)
unsigned int va, vb, vc, vd;
vector128 *vrs;
- if (get_user(instr.val, (unsigned int __user *) regs->nip))
+ if (__get_user_instr(instr, (void __user *) regs->nip))
return -EFAULT;
word = ppc_inst_val(instr);
--
2.17.1
^ permalink raw reply related [flat|nested] 71+ messages in thread
* [PATCH v5 12/21] powerpc: Introduce a function for reporting instruction length
2020-04-06 8:09 [PATCH v5 00/21] Initial Prefixed Instruction support Jordan Niethe
` (10 preceding siblings ...)
2020-04-06 8:09 ` [PATCH v5 11/21] powerpc: Define and use __get_user_instr{, inatomic}() Jordan Niethe
@ 2020-04-06 8:09 ` Jordan Niethe
2020-04-07 11:14 ` Balamuruhan S
2020-04-06 8:09 ` [PATCH v5 13/21] powerpc/xmon: Use a function for reading instructions Jordan Niethe
` (9 subsequent siblings)
21 siblings, 1 reply; 71+ messages in thread
From: Jordan Niethe @ 2020-04-06 8:09 UTC (permalink / raw)
To: linuxppc-dev; +Cc: alistair, npiggin, bala24, Jordan Niethe, dja
Currently all instructions have the same length, but in preparation for
prefixed instructions introduce a function for returning instruction
length.
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
arch/powerpc/include/asm/inst.h | 5 +++++
arch/powerpc/kernel/kprobes.c | 6 ++++--
arch/powerpc/kernel/uprobes.c | 2 +-
3 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h
index 369b35ce964c..70b37a35a91a 100644
--- a/arch/powerpc/include/asm/inst.h
+++ b/arch/powerpc/include/asm/inst.h
@@ -17,6 +17,11 @@ static inline u32 ppc_inst_val(struct ppc_inst x)
return x.val;
}
+static inline bool ppc_inst_len(struct ppc_inst x)
+{
+ return sizeof(struct ppc_inst);
+}
+
static inline int ppc_inst_opcode(struct ppc_inst x)
{
return x.val >> 26;
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index ff53e5ef7e40..8d17cfdcdc54 100644
--- a/arch/powerpc/kernel/kprobes.c
+++ b/arch/powerpc/kernel/kprobes.c
@@ -474,14 +474,16 @@ NOKPROBE_SYMBOL(trampoline_probe_handler);
*/
int kprobe_post_handler(struct pt_regs *regs)
{
+ int len;
struct kprobe *cur = kprobe_running();
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
if (!cur || user_mode(regs))
return 0;
+ len = ppc_inst_len(ppc_inst_read((struct ppc_inst *)cur->ainsn.insn));
/* make sure we got here for instruction we have a kprobe on */
- if (((unsigned long)cur->ainsn.insn + 4) != regs->nip)
+ if (((unsigned long)cur->ainsn.insn + len) != regs->nip)
return 0;
if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) {
@@ -490,7 +492,7 @@ int kprobe_post_handler(struct pt_regs *regs)
}
/* Adjust nip to after the single-stepped instruction */
- regs->nip = (unsigned long)cur->addr + 4;
+ regs->nip = (unsigned long)cur->addr + len;
regs->msr |= kcb->kprobe_saved_msr;
/*Restore back the original saved kprobes variables and continue. */
diff --git a/arch/powerpc/kernel/uprobes.c b/arch/powerpc/kernel/uprobes.c
index 31c870287f2b..8e63afa012ba 100644
--- a/arch/powerpc/kernel/uprobes.c
+++ b/arch/powerpc/kernel/uprobes.c
@@ -112,7 +112,7 @@ int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
* support doesn't exist and have to fix-up the next instruction
* to be executed.
*/
- regs->nip = utask->vaddr + MAX_UINSN_BYTES;
+ regs->nip = utask->vaddr + ppc_inst_len(auprobe->insn);
user_disable_single_step(current);
return 0;
--
2.17.1
^ permalink raw reply related [flat|nested] 71+ messages in thread
* [PATCH v5 13/21] powerpc/xmon: Use a function for reading instructions
2020-04-06 8:09 [PATCH v5 00/21] Initial Prefixed Instruction support Jordan Niethe
` (11 preceding siblings ...)
2020-04-06 8:09 ` [PATCH v5 12/21] powerpc: Introduce a function for reporting instruction length Jordan Niethe
@ 2020-04-06 8:09 ` Jordan Niethe
2020-04-07 11:30 ` Balamuruhan S
2020-04-06 8:09 ` [PATCH v5 14/21] powerpc/xmon: Move insertion of breakpoint for xol'ing Jordan Niethe
` (8 subsequent siblings)
21 siblings, 1 reply; 71+ messages in thread
From: Jordan Niethe @ 2020-04-06 8:09 UTC (permalink / raw)
To: linuxppc-dev; +Cc: alistair, npiggin, bala24, Jordan Niethe, dja
Currently in xmon, mread() is used for reading instructions. In
preparation for prefixed instructions, create and use a new function,
mread_instr(), especially for reading instructions.
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v5: New to series, seperated from "Add prefixed instructions to
instruction data type"
---
arch/powerpc/xmon/xmon.c | 24 ++++++++++++++++++++----
1 file changed, 20 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 5e3949322a6c..6f4cf01a58c1 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -125,6 +125,7 @@ extern unsigned int bpt_table[NBPTS * BPT_WORDS];
static int cmds(struct pt_regs *);
static int mread(unsigned long, void *, int);
static int mwrite(unsigned long, void *, int);
+static int mread_instr(unsigned long, struct ppc_inst *);
static int handle_fault(struct pt_regs *);
static void byterev(unsigned char *, int);
static void memex(void);
@@ -899,7 +900,7 @@ static void insert_bpts(void)
for (i = 0; i < NBPTS; ++i, ++bp) {
if ((bp->enabled & (BP_TRAP|BP_CIABR)) == 0)
continue;
- if (mread(bp->address, &instr, 4) != 4) {
+ if (!mread_instr(bp->address, &instr)) {
printf("Couldn't read instruction at %lx, "
"disabling breakpoint there\n", bp->address);
bp->enabled = 0;
@@ -949,7 +950,7 @@ static void remove_bpts(void)
for (i = 0; i < NBPTS; ++i, ++bp) {
if ((bp->enabled & (BP_TRAP|BP_CIABR)) != BP_TRAP)
continue;
- if (mread(bp->address, &instr, 4) == 4
+ if (mread_instr(bp->address, &instr)
&& ppc_inst_equal(instr, ppc_inst(bpinstr))
&& patch_instruction(
(struct ppc_inst *)bp->address, ppc_inst_read(bp->instr)) != 0)
@@ -1165,7 +1166,7 @@ static int do_step(struct pt_regs *regs)
force_enable_xmon();
/* check we are in 64-bit kernel mode, translation enabled */
if ((regs->msr & (MSR_64BIT|MSR_PR|MSR_IR)) == (MSR_64BIT|MSR_IR)) {
- if (mread(regs->nip, &instr, 4) == 4) {
+ if (mread_instr(regs->nip, &instr)) {
stepped = emulate_step(regs, instr);
if (stepped < 0) {
printf("Couldn't single-step %s instruction\n",
@@ -1332,7 +1333,7 @@ static long check_bp_loc(unsigned long addr)
printf("Breakpoints may only be placed at kernel addresses\n");
return 0;
}
- if (!mread(addr, &instr, sizeof(instr))) {
+ if (!mread_instr(addr, &instr)) {
printf("Can't read instruction at address %lx\n", addr);
return 0;
}
@@ -2125,6 +2126,21 @@ mwrite(unsigned long adrs, void *buf, int size)
return n;
}
+static int
+mread_instr(unsigned long adrs, struct ppc_inst *instr)
+{
+ if (setjmp(bus_error_jmp) == 0) {
+ catch_memory_errors = 1;
+ sync();
+ *instr = ppc_inst_read((struct ppc_inst *)adrs);
+ sync();
+ /* wait a little while to see if we get a machine check */
+ __delay(200);
+ }
+ catch_memory_errors = 0;
+ return ppc_inst_len(*instr);
+}
+
static int fault_type;
static int fault_except;
static char *fault_chars[] = { "--", "**", "##" };
--
2.17.1
^ permalink raw reply related [flat|nested] 71+ messages in thread
* [PATCH v5 14/21] powerpc/xmon: Move insertion of breakpoint for xol'ing
2020-04-06 8:09 [PATCH v5 00/21] Initial Prefixed Instruction support Jordan Niethe
` (12 preceding siblings ...)
2020-04-06 8:09 ` [PATCH v5 13/21] powerpc/xmon: Use a function for reading instructions Jordan Niethe
@ 2020-04-06 8:09 ` Jordan Niethe
2020-04-06 8:09 ` [PATCH v5 15/21] powerpc: Make test_translate_branch() independent of instruction length Jordan Niethe
` (7 subsequent siblings)
21 siblings, 0 replies; 71+ messages in thread
From: Jordan Niethe @ 2020-04-06 8:09 UTC (permalink / raw)
To: linuxppc-dev; +Cc: alistair, npiggin, bala24, Jordan Niethe, dja
When a new breakpoint is created, the second instruction of that
breakpoint is patched with a trap instruction. This assumes the length
of the instruction is always the same. In preparation for prefixed
instructions, remove this assumption. Insert the trap instruction at the
same time the first instruction is inserted.
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
arch/powerpc/xmon/xmon.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 6f4cf01a58c1..6f3bcdcfc9c7 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -881,7 +881,6 @@ static struct bpt *new_breakpoint(unsigned long a)
if (!bp->enabled && atomic_read(&bp->ref_count) == 0) {
bp->address = a;
bp->instr = (void *)(bpt_table + ((bp - bpts) * BPT_WORDS));
- patch_instruction(bp->instr + 1, ppc_inst(bpinstr));
return bp;
}
}
@@ -913,6 +912,7 @@ static void insert_bpts(void)
continue;
}
patch_instruction(bp->instr, instr);
+ patch_instruction((void *)bp->instr + ppc_inst_len(instr), ppc_inst(bpinstr));
if (bp->enabled & BP_CIABR)
continue;
if (patch_instruction((struct ppc_inst *)bp->address,
--
2.17.1
^ permalink raw reply related [flat|nested] 71+ messages in thread
* [PATCH v5 15/21] powerpc: Make test_translate_branch() independent of instruction length
2020-04-06 8:09 [PATCH v5 00/21] Initial Prefixed Instruction support Jordan Niethe
` (13 preceding siblings ...)
2020-04-06 8:09 ` [PATCH v5 14/21] powerpc/xmon: Move insertion of breakpoint for xol'ing Jordan Niethe
@ 2020-04-06 8:09 ` Jordan Niethe
2020-04-06 8:09 ` [PATCH v5 16/21] powerpc: Enable Prefixed Instructions Jordan Niethe
` (6 subsequent siblings)
21 siblings, 0 replies; 71+ messages in thread
From: Jordan Niethe @ 2020-04-06 8:09 UTC (permalink / raw)
To: linuxppc-dev; +Cc: alistair, npiggin, bala24, Jordan Niethe, dja
test_translate_branch() uses two pointers to instructions within a
buffer, p and q, to test patch_branch(). The pointer arithmetic done on
them assumes a size of 4. This will not work if the instruction length
changes. Instead do the arithmetic relative to the void * to the buffer.
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v4: New to series
---
arch/powerpc/lib/code-patching.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index ba08f3815d00..c329ad657302 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -569,7 +569,7 @@ static void __init test_branch_bform(void)
static void __init test_translate_branch(void)
{
unsigned long addr;
- struct ppc_inst *p, *q;
+ void *p, *q;
struct ppc_inst instr;
void *buf;
@@ -583,7 +583,7 @@ static void __init test_translate_branch(void)
addr = (unsigned long)p;
patch_branch(p, addr, 0);
check(instr_is_branch_to_addr(p, addr));
- q = p + 1;
+ q = p + 4;
translate_branch(&instr, q, p);
patch_instruction(q, instr);
check(instr_is_branch_to_addr(q, addr));
@@ -639,7 +639,7 @@ static void __init test_translate_branch(void)
create_cond_branch(&instr, p, addr, 0);
patch_instruction(p, instr);
check(instr_is_branch_to_addr(p, addr));
- q = p + 1;
+ q = buf + 4;
translate_branch(&instr, q, p);
patch_instruction(q, instr);
check(instr_is_branch_to_addr(q, addr));
--
2.17.1
^ permalink raw reply related [flat|nested] 71+ messages in thread
* [PATCH v5 16/21] powerpc: Enable Prefixed Instructions
2020-04-06 8:09 [PATCH v5 00/21] Initial Prefixed Instruction support Jordan Niethe
` (14 preceding siblings ...)
2020-04-06 8:09 ` [PATCH v5 15/21] powerpc: Make test_translate_branch() independent of instruction length Jordan Niethe
@ 2020-04-06 8:09 ` Jordan Niethe
2020-04-06 8:09 ` [PATCH v5 17/21] powerpc: Define new SRR1 bits for a future ISA version Jordan Niethe
` (5 subsequent siblings)
21 siblings, 0 replies; 71+ messages in thread
From: Jordan Niethe @ 2020-04-06 8:09 UTC (permalink / raw)
To: linuxppc-dev; +Cc: alistair, npiggin, bala24, Jordan Niethe, dja
From: Alistair Popple <alistair@popple.id.au>
Prefix instructions have their own FSCR bit which needs to enabled via
a CPU feature. The kernel will save the FSCR for problem state but it
needs to be enabled initially.
If prefixed instructions are made unavailable by the [H]FSCR, attempting
to use them will cause a facility unavailable exception. Add "PREFIX" to
the facility_strings[].
Currently there are no prefixed instructions that are actually emulated
by emulate_instruction() within facility_unavailable_exception().
However, when caused by a prefixed instructions the SRR1 PREFIXED bit is
set. Prepare for dealing with emulated prefixed instructions by checking
for this bit.
Reviewed-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Alistair Popple <alistair@popple.id.au>
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v4:
- Squash "Check for prefixed instructions in
facility_unavailable_exception()" here
- Remove dt parts for now
---
arch/powerpc/include/asm/reg.h | 3 +++
arch/powerpc/kernel/traps.c | 1 +
2 files changed, 4 insertions(+)
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 1aa46dff0957..c7758c2ccc5f 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -397,6 +397,7 @@
#define SPRN_RWMR 0x375 /* Region-Weighting Mode Register */
/* HFSCR and FSCR bit numbers are the same */
+#define FSCR_PREFIX_LG 13 /* Enable Prefix Instructions */
#define FSCR_SCV_LG 12 /* Enable System Call Vectored */
#define FSCR_MSGP_LG 10 /* Enable MSGP */
#define FSCR_TAR_LG 8 /* Enable Target Address Register */
@@ -408,11 +409,13 @@
#define FSCR_VECVSX_LG 1 /* Enable VMX/VSX */
#define FSCR_FP_LG 0 /* Enable Floating Point */
#define SPRN_FSCR 0x099 /* Facility Status & Control Register */
+#define FSCR_PREFIX __MASK(FSCR_PREFIX_LG)
#define FSCR_SCV __MASK(FSCR_SCV_LG)
#define FSCR_TAR __MASK(FSCR_TAR_LG)
#define FSCR_EBB __MASK(FSCR_EBB_LG)
#define FSCR_DSCR __MASK(FSCR_DSCR_LG)
#define SPRN_HFSCR 0xbe /* HV=1 Facility Status & Control Register */
+#define HFSCR_PREFIX __MASK(FSCR_PREFIX_LG)
#define HFSCR_MSGP __MASK(FSCR_MSGP_LG)
#define HFSCR_TAR __MASK(FSCR_TAR_LG)
#define HFSCR_EBB __MASK(FSCR_EBB_LG)
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 82a3438300fd..a4764b039749 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -1720,6 +1720,7 @@ void facility_unavailable_exception(struct pt_regs *regs)
[FSCR_TAR_LG] = "TAR",
[FSCR_MSGP_LG] = "MSGP",
[FSCR_SCV_LG] = "SCV",
+ [FSCR_PREFIX_LG] = "PREFIX",
};
char *facility = "unknown";
u64 value;
--
2.17.1
^ permalink raw reply related [flat|nested] 71+ messages in thread
* [PATCH v5 17/21] powerpc: Define new SRR1 bits for a future ISA version
2020-04-06 8:09 [PATCH v5 00/21] Initial Prefixed Instruction support Jordan Niethe
` (15 preceding siblings ...)
2020-04-06 8:09 ` [PATCH v5 16/21] powerpc: Enable Prefixed Instructions Jordan Niethe
@ 2020-04-06 8:09 ` Jordan Niethe
2020-04-06 8:09 ` [PATCH v5 18/21] powerpc64: Add prefixed instructions to instruction data type Jordan Niethe
` (4 subsequent siblings)
21 siblings, 0 replies; 71+ messages in thread
From: Jordan Niethe @ 2020-04-06 8:09 UTC (permalink / raw)
To: linuxppc-dev; +Cc: alistair, npiggin, bala24, Jordan Niethe, dja
Add the BOUNDARY SRR1 bit definition for when the cause of an alignment
exception is a prefixed instruction that crosses a 64-byte boundary.
Add the PREFIXED SRR1 bit definition for exceptions caused by prefixed
instructions.
Bit 35 of SRR1 is called SRR1_ISI_N_OR_G. This name comes from it being
used to indicate that an ISI was due to the access being no-exec or
guarded. A future ISA version adds another purpose. It is also set if
there is an access in a cache-inhibited location for prefixed
instruction. Rename from SRR1_ISI_N_OR_G to SRR1_ISI_N_G_OR_CIP.
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v2: Combined all the commits concerning SRR1 bits.
---
arch/powerpc/include/asm/reg.h | 4 +++-
arch/powerpc/kvm/book3s_hv_nested.c | 2 +-
arch/powerpc/kvm/book3s_hv_rm_mmu.c | 2 +-
3 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index c7758c2ccc5f..173f33df4fab 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -762,7 +762,7 @@
#endif
#define SRR1_ISI_NOPT 0x40000000 /* ISI: Not found in hash */
-#define SRR1_ISI_N_OR_G 0x10000000 /* ISI: Access is no-exec or G */
+#define SRR1_ISI_N_G_OR_CIP 0x10000000 /* ISI: Access is no-exec or G or CI for a prefixed instruction */
#define SRR1_ISI_PROT 0x08000000 /* ISI: Other protection fault */
#define SRR1_WAKEMASK 0x00380000 /* reason for wakeup */
#define SRR1_WAKEMASK_P8 0x003c0000 /* reason for wakeup on POWER8 and 9 */
@@ -789,6 +789,8 @@
#define SRR1_PROGADDR 0x00010000 /* SRR0 contains subsequent addr */
#define SRR1_MCE_MCP 0x00080000 /* Machine check signal caused interrupt */
+#define SRR1_BOUNDARY 0x10000000 /* Prefixed instruction crosses 64-byte boundary */
+#define SRR1_PREFIXED 0x20000000 /* Exception caused by prefixed instruction */
#define SPRN_HSRR0 0x13A /* Save/Restore Register 0 */
#define SPRN_HSRR1 0x13B /* Save/Restore Register 1 */
diff --git a/arch/powerpc/kvm/book3s_hv_nested.c b/arch/powerpc/kvm/book3s_hv_nested.c
index dc97e5be76f6..6ab685227574 100644
--- a/arch/powerpc/kvm/book3s_hv_nested.c
+++ b/arch/powerpc/kvm/book3s_hv_nested.c
@@ -1169,7 +1169,7 @@ static int kvmhv_translate_addr_nested(struct kvm_vcpu *vcpu,
} else if (vcpu->arch.trap == BOOK3S_INTERRUPT_H_INST_STORAGE) {
/* Can we execute? */
if (!gpte_p->may_execute) {
- flags |= SRR1_ISI_N_OR_G;
+ flags |= SRR1_ISI_N_G_OR_CIP;
goto forward_to_l1;
}
} else {
diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
index 220305454c23..b53a9f1c1a46 100644
--- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c
+++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
@@ -1260,7 +1260,7 @@ long kvmppc_hpte_hv_fault(struct kvm_vcpu *vcpu, unsigned long addr,
status &= ~DSISR_NOHPTE; /* DSISR_NOHPTE == SRR1_ISI_NOPT */
if (!data) {
if (gr & (HPTE_R_N | HPTE_R_G))
- return status | SRR1_ISI_N_OR_G;
+ return status | SRR1_ISI_N_G_OR_CIP;
if (!hpte_read_permission(pp, slb_v & key))
return status | SRR1_ISI_PROT;
} else if (status & DSISR_ISSTORE) {
--
2.17.1
^ permalink raw reply related [flat|nested] 71+ messages in thread
* [PATCH v5 18/21] powerpc64: Add prefixed instructions to instruction data type
2020-04-06 8:09 [PATCH v5 00/21] Initial Prefixed Instruction support Jordan Niethe
` (16 preceding siblings ...)
2020-04-06 8:09 ` [PATCH v5 17/21] powerpc: Define new SRR1 bits for a future ISA version Jordan Niethe
@ 2020-04-06 8:09 ` Jordan Niethe
2020-04-06 9:52 ` Alistair Popple
` (2 more replies)
2020-04-06 8:09 ` [PATCH v5 19/21] powerpc: Support prefixed instructions in alignment handler Jordan Niethe
` (3 subsequent siblings)
21 siblings, 3 replies; 71+ messages in thread
From: Jordan Niethe @ 2020-04-06 8:09 UTC (permalink / raw)
To: linuxppc-dev; +Cc: alistair, npiggin, bala24, Jordan Niethe, dja
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>
---
v4: New to series
v5: - Distinguish normal instructions from prefixed instructions with a
0xff marker for the suffix.
- __patch_instruction() using std for prefixed instructions
---
arch/powerpc/include/asm/inst.h | 71 ++++++++++++++++++++++++++--
arch/powerpc/include/asm/kprobes.h | 2 +-
arch/powerpc/include/asm/uaccess.h | 31 ++++++++++--
arch/powerpc/include/asm/uprobes.h | 2 +-
arch/powerpc/kernel/optprobes.c | 42 ++++++++--------
arch/powerpc/kernel/optprobes_head.S | 3 ++
arch/powerpc/kernel/trace/ftrace.c | 26 +++++++++-
arch/powerpc/lib/code-patching.c | 19 +++++---
arch/powerpc/lib/feature-fixups.c | 5 +-
arch/powerpc/lib/sstep.c | 4 +-
arch/powerpc/xmon/xmon.c | 6 +--
arch/powerpc/xmon/xmon_bpts.S | 4 +-
12 files changed, 171 insertions(+), 44 deletions(-)
diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h
index 70b37a35a91a..7e23e7146c66 100644
--- a/arch/powerpc/include/asm/inst.h
+++ b/arch/powerpc/include/asm/inst.h
@@ -8,23 +8,67 @@
struct ppc_inst {
u32 val;
+#ifdef __powerpc64__
+ u32 suffix;
+#endif /* __powerpc64__ */
} __packed;
-#define ppc_inst(x) ((struct ppc_inst){ .val = x })
+static inline int ppc_inst_opcode(struct ppc_inst x)
+{
+ return x.val >> 26;
+}
static inline u32 ppc_inst_val(struct ppc_inst x)
{
return x.val;
}
-static inline bool ppc_inst_len(struct ppc_inst x)
+#ifdef __powerpc64__
+#define ppc_inst(x) ((struct ppc_inst){ .val = (x), .suffix = 0xff })
+
+#define ppc_inst_prefix(x, y) ((struct ppc_inst){ .val = (x), .suffix = (y) })
+
+static inline u32 ppc_inst_suffix(struct ppc_inst x)
{
- return sizeof(struct ppc_inst);
+ return x.suffix;
}
-static inline int ppc_inst_opcode(struct ppc_inst x)
+static inline bool ppc_inst_prefixed(struct ppc_inst x) {
+ return ((ppc_inst_val(x) >> 26) == 1) && ppc_inst_suffix(x) != 0xff;
+}
+
+static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
{
- return x.val >> 26;
+ return ppc_inst_prefix(swab32(ppc_inst_val(x)),
+ swab32(ppc_inst_suffix(x)));
+}
+
+static inline struct ppc_inst ppc_inst_read(const struct ppc_inst *ptr)
+{
+ u32 val, suffix = 0xff;
+ val = *(u32 *)ptr;
+ if ((val >> 26) == 1)
+ suffix = *((u32 *)ptr + 1);
+ return ppc_inst_prefix(val, suffix);
+}
+
+static inline void ppc_inst_write(struct ppc_inst *ptr, struct ppc_inst x)
+{
+ if (ppc_inst_prefixed(x)) {
+ *(u32 *)ptr = x.val;
+ *((u32 *)ptr + 1) = x.suffix;
+ } else {
+ *(u32 *)ptr = x.val;
+ }
+}
+
+#else
+
+#define ppc_inst(x) ((struct ppc_inst){ .val = x })
+
+static inline bool ppc_inst_prefixed(ppc_inst x)
+{
+ return 0;
}
static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
@@ -32,14 +76,31 @@ static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
return ppc_inst(swab32(ppc_inst_val(x)));
}
+static inline u32 ppc_inst_val(struct ppc_inst x)
+{
+ return x.val;
+}
+
static inline struct ppc_inst ppc_inst_read(const struct ppc_inst *ptr)
{
return *ptr;
}
+static inline void ppc_inst_write(struct ppc_inst *ptr, struct ppc_inst x)
+{
+ *ptr = x;
+}
+
+#endif /* __powerpc64__ */
+
static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
{
return !memcmp(&x, &y, sizeof(struct ppc_inst));
}
+static inline int ppc_inst_len(struct ppc_inst x)
+{
+ return (ppc_inst_prefixed(x)) ? 8 : 4;
+}
+
#endif /* _ASM_INST_H */
diff --git a/arch/powerpc/include/asm/kprobes.h b/arch/powerpc/include/asm/kprobes.h
index 66b3f2983b22..4fc0e15e23a5 100644
--- a/arch/powerpc/include/asm/kprobes.h
+++ b/arch/powerpc/include/asm/kprobes.h
@@ -43,7 +43,7 @@ extern kprobe_opcode_t optprobe_template_ret[];
extern kprobe_opcode_t optprobe_template_end[];
/* Fixed instruction size for powerpc */
-#define MAX_INSN_SIZE 1
+#define MAX_INSN_SIZE 2
#define MAX_OPTIMIZED_LENGTH sizeof(kprobe_opcode_t) /* 4 bytes */
#define MAX_OPTINSN_SIZE (optprobe_template_end - optprobe_template_entry)
#define RELATIVEJUMP_SIZE sizeof(kprobe_opcode_t) /* 4 bytes */
diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h
index c0a35e4586a5..5a3f486ddf02 100644
--- a/arch/powerpc/include/asm/uaccess.h
+++ b/arch/powerpc/include/asm/uaccess.h
@@ -105,11 +105,34 @@ 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)))
-#define __get_user_instr(x, ptr) \
- __get_user_nocheck((x).val, (u32 *)(ptr), sizeof(u32), true)
+#define __get_user_instr(x, ptr) \
+({ \
+ long __gui_ret = 0; \
+ unsigned int prefix, suffix; \
+ __gui_ret = __get_user(prefix, (unsigned int __user *)ptr); \
+ if (!__gui_ret && (prefix >> 26) == 1) { \
+ __gui_ret = __get_user(suffix, (unsigned int __user *)ptr + 1); \
+ (x) = ppc_inst_prefix(prefix, suffix); \
+ } else { \
+ (x) = ppc_inst(prefix); \
+ } \
+ __gui_ret; \
+})
+
+#define __get_user_instr_inatomic(x, ptr) \
+({ \
+ long __gui_ret = 0; \
+ unsigned int prefix, suffix; \
+ __gui_ret = __get_user_inatomic(prefix, (unsigned int __user *)ptr); \
+ if (!__gui_ret && (prefix >> 26) == 1) { \
+ __gui_ret = __get_user_inatomic(suffix, (unsigned int __user *)ptr + 1); \
+ (x) = ppc_inst_prefix(prefix, suffix); \
+ } else { \
+ (x) = ppc_inst(prefix); \
+ } \
+ __gui_ret; \
+})
-#define __get_user_instr_inatomic(x, ptr) \
- __get_user_nosleep((x).val, (u32 *)(ptr), sizeof(u32))
extern long __put_user_bad(void);
/*
diff --git a/arch/powerpc/include/asm/uprobes.h b/arch/powerpc/include/asm/uprobes.h
index 7e3b329ba2d3..5bf65f5d44a9 100644
--- a/arch/powerpc/include/asm/uprobes.h
+++ b/arch/powerpc/include/asm/uprobes.h
@@ -15,7 +15,7 @@
typedef ppc_opcode_t uprobe_opcode_t;
-#define MAX_UINSN_BYTES 4
+#define MAX_UINSN_BYTES 8
#define UPROBE_XOL_SLOT_BYTES (MAX_UINSN_BYTES)
/* The following alias is needed for reference from arch-agnostic code */
diff --git a/arch/powerpc/kernel/optprobes.c b/arch/powerpc/kernel/optprobes.c
index 684640b8fa2e..689daf430161 100644
--- a/arch/powerpc/kernel/optprobes.c
+++ b/arch/powerpc/kernel/optprobes.c
@@ -159,38 +159,38 @@ void patch_imm32_load_insns(unsigned int val, kprobe_opcode_t *addr)
/*
* Generate instructions to load provided immediate 64-bit value
- * to register 'r3' and patch these instructions at 'addr'.
+ * to register 'reg' and patch these instructions at 'addr'.
*/
-void patch_imm64_load_insns(unsigned long val, kprobe_opcode_t *addr)
+void patch_imm64_load_insns(unsigned long val, int reg, kprobe_opcode_t *addr)
{
- /* lis r3,(op)@highest */
- patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ADDIS | ___PPC_RT(3) |
+ /* lis reg,(op)@highest */
+ patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ADDIS | ___PPC_RT(reg) |
((val >> 48) & 0xffff)));
addr++;
- /* ori r3,r3,(op)@higher */
- patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI | ___PPC_RA(3) |
- ___PPC_RS(3) | ((val >> 32) & 0xffff)));
+ /* ori reg,reg,(op)@higher */
+ patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI | ___PPC_RA(reg) |
+ ___PPC_RS(reg) | ((val >> 32) & 0xffff)));
addr++;
- /* rldicr r3,r3,32,31 */
- patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_RLDICR | ___PPC_RA(3) |
- ___PPC_RS(3) | __PPC_SH64(32) | __PPC_ME64(31)));
+ /* rldicr reg,reg,32,31 */
+ patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_RLDICR | ___PPC_RA(reg) |
+ ___PPC_RS(reg) | __PPC_SH64(32) | __PPC_ME64(31)));
addr++;
- /* oris r3,r3,(op)@h */
- patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORIS | ___PPC_RA(3) |
- ___PPC_RS(3) | ((val >> 16) & 0xffff)));
+ /* oris reg,reg,(op)@h */
+ patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORIS | ___PPC_RA(reg) |
+ ___PPC_RS(reg) | ((val >> 16) & 0xffff)));
addr++;
- /* ori r3,r3,(op)@l */
- patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI | ___PPC_RA(3) |
- ___PPC_RS(3) | (val & 0xffff)));
+ /* ori reg,reg,(op)@l */
+ patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI | ___PPC_RA(reg) |
+ ___PPC_RS(reg) | (val & 0xffff)));
}
int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p)
{
- struct ppc_inst branch_op_callback, branch_emulate_step;
+ struct ppc_inst branch_op_callback, branch_emulate_step, temp;
kprobe_opcode_t *op_callback_addr, *emulate_step_addr, *buff;
long b_offset;
unsigned long nip, size;
@@ -240,7 +240,7 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p)
* Fixup the template with instructions to:
* 1. load the address of the actual probepoint
*/
- patch_imm64_load_insns((unsigned long)op, buff + TMPL_OP_IDX);
+ patch_imm64_load_insns((unsigned long)op, 3, buff + TMPL_OP_IDX);
/*
* 2. branch to optimized_callback() and emulate_step()
@@ -271,7 +271,11 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p)
/*
* 3. load instruction to be emulated into relevant register, and
*/
- patch_imm32_load_insns(*p->ainsn.insn, buff + TMPL_INSN_IDX);
+ 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);
/*
* 4. branch back from trampoline
diff --git a/arch/powerpc/kernel/optprobes_head.S b/arch/powerpc/kernel/optprobes_head.S
index cf383520843f..ff8ba4d3824d 100644
--- a/arch/powerpc/kernel/optprobes_head.S
+++ b/arch/powerpc/kernel/optprobes_head.S
@@ -94,6 +94,9 @@ optprobe_template_insn:
/* 2, Pass instruction to be emulated in r4 */
nop
nop
+ nop
+ nop
+ nop
.global optprobe_template_call_emulate
optprobe_template_call_emulate:
diff --git a/arch/powerpc/kernel/trace/ftrace.c b/arch/powerpc/kernel/trace/ftrace.c
index e78742613b36..16041a5c86d5 100644
--- a/arch/powerpc/kernel/trace/ftrace.c
+++ b/arch/powerpc/kernel/trace/ftrace.c
@@ -41,11 +41,35 @@
#define NUM_FTRACE_TRAMPS 8
static unsigned long ftrace_tramps[NUM_FTRACE_TRAMPS];
+#ifdef __powerpc64__
static long
probe_kernel_read_inst(struct ppc_inst *inst, const void *src)
{
- return probe_kernel_read((void *)inst, src, MCOUNT_INSN_SIZE);
+ u32 val, suffix = 0;
+ long err;
+
+ err = probe_kernel_read((void *)&val,
+ src, sizeof(val));
+ if (err)
+ return err;
+
+ if ((val >> 26) == 1)
+ err = probe_kernel_read((void *)&suffix,
+ src + 4, MCOUNT_INSN_SIZE);
+ if (err)
+ return err;
+
+ *inst = ppc_inst_prefix(val, suffix);
+
+ return 0;
}
+#else
+static long
+probe_kernel_read_inst(struct ppc_inst *inst, const void *src)
+{
+ return probe_kernel_read((void *)inst, src, MCOUNT_INSN_SIZE)
+}
+#endif
static struct ppc_inst
ftrace_call_replace(unsigned long ip, unsigned long addr, int link)
diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index c329ad657302..b4007e03d8fa 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -24,12 +24,19 @@ static int __patch_instruction(struct ppc_inst *exec_addr, struct ppc_inst instr
{
int err = 0;
- __put_user_asm(ppc_inst_val(instr), patch_addr, err, "stw");
- if (err)
- return err;
-
- asm ("dcbst 0, %0; sync; icbi 0,%1; sync; isync" :: "r" (patch_addr),
- "r" (exec_addr));
+ if (!ppc_inst_prefixed(instr)) {
+ __put_user_asm(ppc_inst_val(instr), patch_addr, err, "stw");
+ if (err)
+ return err;
+ asm ("dcbst 0, %0; sync; icbi 0,%1; sync; isync" :: "r" (patch_addr),
+ "r" (exec_addr));
+ } else {
+ __put_user_asm((u64)ppc_inst_suffix(instr) << 32 | ppc_inst_val(instr), patch_addr, err, "std");
+ 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/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c
index f00dd13b1c3c..5519cec83cc8 100644
--- a/arch/powerpc/lib/feature-fixups.c
+++ b/arch/powerpc/lib/feature-fixups.c
@@ -84,12 +84,13 @@ static int patch_feature_section(unsigned long value, struct fixup_entry *fcur)
src = alt_start;
dest = start;
- for (; src < alt_end; src++, dest++) {
+ for (; src < alt_end; src = (void *)src + ppc_inst_len(ppc_inst_read(src)),
+ (dest = (void *)dest + ppc_inst_len(ppc_inst_read(dest)))) {
if (patch_alt_instruction(src, dest, alt_start, alt_end))
return 1;
}
- for (; dest < end; dest++)
+ for (; dest < end; dest = (void *)dest + ppc_inst_len(ppc_inst(PPC_INST_NOP)))
raw_patch_instruction(dest, ppc_inst(PPC_INST_NOP));
return 0;
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index 52ddd3122dc8..8b285bf11218 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -1169,10 +1169,12 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
unsigned long int imm;
unsigned long int val, val2;
unsigned int mb, me, sh;
- unsigned int word;
+ unsigned int word, suffix;
long ival;
word = ppc_inst_val(instr);
+ suffix = ppc_inst_suffix(instr);
+
op->type = COMPUTE;
opcode = word >> 26;
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 6f3bcdcfc9c7..b704aebb099a 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -761,8 +761,8 @@ static int xmon_bpt(struct pt_regs *regs)
/* Are we at the trap at bp->instr[1] for some bp? */
bp = in_breakpoint_table(regs->nip, &offset);
- if (bp != NULL && offset == 4) {
- regs->nip = bp->address + 4;
+ if (bp != NULL && (offset == 4 || offset == 8)) {
+ regs->nip = bp->address + offset;
atomic_dec(&bp->ref_count);
return 1;
}
@@ -863,7 +863,7 @@ static struct bpt *in_breakpoint_table(unsigned long nip, unsigned long *offp)
if (off >= sizeof(bpt_table))
return NULL;
*offp = off % BPT_SIZE;
- if (*offp != 0 && *offp != 4)
+ if (*offp != 0 && *offp != 4 && *offp != 8)
return NULL;
return bpts + (off / BPT_SIZE);
}
diff --git a/arch/powerpc/xmon/xmon_bpts.S b/arch/powerpc/xmon/xmon_bpts.S
index ebb2dbc70ca8..09058eb6abbd 100644
--- a/arch/powerpc/xmon/xmon_bpts.S
+++ b/arch/powerpc/xmon/xmon_bpts.S
@@ -3,6 +3,8 @@
#include <asm/asm-compat.h>
#include "xmon_bpts.h"
+/* Prefixed instructions can not cross 64 byte boundaries */
+.align 6
.global bpt_table
bpt_table:
- .space NBPTS * 8
+ .space NBPTS * 16
--
2.17.1
^ permalink raw reply related [flat|nested] 71+ messages in thread
* [PATCH v5 19/21] powerpc: Support prefixed instructions in alignment handler
2020-04-06 8:09 [PATCH v5 00/21] Initial Prefixed Instruction support Jordan Niethe
` (17 preceding siblings ...)
2020-04-06 8:09 ` [PATCH v5 18/21] powerpc64: Add prefixed instructions to instruction data type Jordan Niethe
@ 2020-04-06 8:09 ` Jordan Niethe
2020-04-06 8:09 ` [PATCH v5 20/21] powerpc sstep: Add support for prefixed load/stores Jordan Niethe
` (2 subsequent siblings)
21 siblings, 0 replies; 71+ messages in thread
From: Jordan Niethe @ 2020-04-06 8:09 UTC (permalink / raw)
To: linuxppc-dev; +Cc: alistair, npiggin, bala24, Jordan Niethe, dja
If a prefixed instruction results in an alignment exception, the
SRR1_PREFIXED bit is set. The handler attempts to emulate the
responsible instruction and then increment the NIP past it. Use
SRR1_PREFIXED to determine by how much the NIP should be incremented.
Prefixed instructions are not permitted to cross 64-byte boundaries. If
they do the alignment interrupt is invoked with SRR1 BOUNDARY bit set.
If this occurs send a SIGBUS to the offending process if in user mode.
If in kernel mode call bad_page_fault().
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v2: - Move __get_user_instr() and __get_user_instr_inatomic() to this
commit (previously in "powerpc sstep: Prepare to support prefixed
instructions").
- Rename sufx to suffix
- Use a macro for calculating instruction length
v3: Move __get_user_{instr(), instr_inatomic()} up with the other
get_user definitions and remove nested if.
v4: Rolled into "Add prefixed instructions to instruction data type"
v5: Only one definition of inst_length()
---
arch/powerpc/kernel/traps.c | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index a4764b039749..9b97d2e6055a 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -583,6 +583,8 @@ static inline int check_io_access(struct pt_regs *regs)
#define REASON_ILLEGAL (ESR_PIL | ESR_PUO)
#define REASON_PRIVILEGED ESR_PPR
#define REASON_TRAP ESR_PTR
+#define REASON_PREFIXED 0
+#define REASON_BOUNDARY 0
/* single-step stuff */
#define single_stepping(regs) (current->thread.debug.dbcr0 & DBCR0_IC)
@@ -597,12 +599,16 @@ static inline int check_io_access(struct pt_regs *regs)
#define REASON_ILLEGAL SRR1_PROGILL
#define REASON_PRIVILEGED SRR1_PROGPRIV
#define REASON_TRAP SRR1_PROGTRAP
+#define REASON_PREFIXED SRR1_PREFIXED
+#define REASON_BOUNDARY SRR1_BOUNDARY
#define single_stepping(regs) ((regs)->msr & MSR_SE)
#define clear_single_step(regs) ((regs)->msr &= ~MSR_SE)
#define clear_br_trace(regs) ((regs)->msr &= ~MSR_BE)
#endif
+#define inst_length(reason) (((reason) & REASON_PREFIXED) ? 8 : 4)
+
#if defined(CONFIG_E500)
int machine_check_e500mc(struct pt_regs *regs)
{
@@ -1593,11 +1599,20 @@ void alignment_exception(struct pt_regs *regs)
{
enum ctx_state prev_state = exception_enter();
int sig, code, fixed = 0;
+ unsigned long reason;
/* We restore the interrupt state now */
if (!arch_irq_disabled_regs(regs))
local_irq_enable();
+ reason = get_reason(regs);
+
+ if (reason & REASON_BOUNDARY) {
+ sig = SIGBUS;
+ code = BUS_ADRALN;
+ goto bad;
+ }
+
if (tm_abort_check(regs, TM_CAUSE_ALIGNMENT | TM_CAUSE_PERSISTENT))
goto bail;
@@ -1606,7 +1621,8 @@ void alignment_exception(struct pt_regs *regs)
fixed = fix_alignment(regs);
if (fixed == 1) {
- regs->nip += 4; /* skip over emulated instruction */
+ /* skip over emulated instruction */
+ regs->nip += inst_length(reason);
emulate_single_step(regs);
goto bail;
}
@@ -1619,6 +1635,7 @@ void alignment_exception(struct pt_regs *regs)
sig = SIGBUS;
code = BUS_ADRALN;
}
+bad:
if (user_mode(regs))
_exception(sig, regs, code, regs->dar);
else
--
2.17.1
^ permalink raw reply related [flat|nested] 71+ messages in thread
* [PATCH v5 20/21] powerpc sstep: Add support for prefixed load/stores
2020-04-06 8:09 [PATCH v5 00/21] Initial Prefixed Instruction support Jordan Niethe
` (18 preceding siblings ...)
2020-04-06 8:09 ` [PATCH v5 19/21] powerpc: Support prefixed instructions in alignment handler Jordan Niethe
@ 2020-04-06 8:09 ` Jordan Niethe
2020-04-06 11:29 ` kbuild test robot
2020-04-06 8:09 ` [PATCH v5 21/21] powerpc sstep: Add support for prefixed fixed-point arithmetic Jordan Niethe
2020-04-09 6:39 ` [PATCH v5 00/21] Initial Prefixed Instruction support Christophe Leroy
21 siblings, 1 reply; 71+ messages in thread
From: Jordan Niethe @ 2020-04-06 8:09 UTC (permalink / raw)
To: linuxppc-dev; +Cc: alistair, npiggin, bala24, Jordan Niethe, dja
This adds emulation support for the following prefixed integer
load/stores:
* Prefixed Load Byte and Zero (plbz)
* Prefixed Load Halfword and Zero (plhz)
* Prefixed Load Halfword Algebraic (plha)
* Prefixed Load Word and Zero (plwz)
* Prefixed Load Word Algebraic (plwa)
* Prefixed Load Doubleword (pld)
* Prefixed Store Byte (pstb)
* Prefixed Store Halfword (psth)
* Prefixed Store Word (pstw)
* Prefixed Store Doubleword (pstd)
* Prefixed Load Quadword (plq)
* Prefixed Store Quadword (pstq)
the follow prefixed floating-point load/stores:
* Prefixed Load Floating-Point Single (plfs)
* Prefixed Load Floating-Point Double (plfd)
* Prefixed Store Floating-Point Single (pstfs)
* Prefixed Store Floating-Point Double (pstfd)
and for the following prefixed VSX load/stores:
* Prefixed Load VSX Scalar Doubleword (plxsd)
* Prefixed Load VSX Scalar Single-Precision (plxssp)
* Prefixed Load VSX Vector [0|1] (plxv, plxv0, plxv1)
* Prefixed Store VSX Scalar Doubleword (pstxsd)
* Prefixed Store VSX Scalar Single-Precision (pstxssp)
* Prefixed Store VSX Vector [0|1] (pstxv, pstxv0, pstxv1)
Reviewed-by: Balamuruhan S <bala24@linux.ibm.com>
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v2: - Combine all load/store patches
- Fix the name of Type 01 instructions
- Remove sign extension flag from pstd/pld
- Rename sufx -> suffix
v3: - Move prefixed loads and stores into the switch statement
---
arch/powerpc/include/asm/sstep.h | 4 +
arch/powerpc/lib/sstep.c | 159 +++++++++++++++++++++++++++++++
2 files changed, 163 insertions(+)
diff --git a/arch/powerpc/include/asm/sstep.h b/arch/powerpc/include/asm/sstep.h
index c3ce903ac488..9b200a5f8794 100644
--- a/arch/powerpc/include/asm/sstep.h
+++ b/arch/powerpc/include/asm/sstep.h
@@ -90,11 +90,15 @@ enum instruction_type {
#define VSX_LDLEFT 4 /* load VSX register from left */
#define VSX_CHECK_VEC 8 /* check MSR_VEC not MSR_VSX for reg >= 32 */
+/* Prefixed flag, ORed in with type */
+#define PREFIXED 0x800
+
/* Size field in type word */
#define SIZE(n) ((n) << 12)
#define GETSIZE(w) ((w) >> 12)
#define GETTYPE(t) ((t) & INSTR_TYPE_MASK)
+#define GETLENGTH(t) (((t) & PREFIXED) ? 8 : 4)
#define MKOP(t, f, s) ((t) | (f) | SIZE(s))
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index 8b285bf11218..8b6aee0ee636 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -187,6 +187,44 @@ static nokprobe_inline unsigned long xform_ea(unsigned int instr,
return ea;
}
+/*
+ * Calculate effective address for a MLS:D-form / 8LS:D-form
+ * prefixed instruction
+ */
+static nokprobe_inline unsigned long mlsd_8lsd_ea(unsigned int instr,
+ unsigned int suffix,
+ const struct pt_regs *regs)
+{
+ int ra, prefix_r;
+ unsigned int dd;
+ unsigned long ea, d0, d1, d;
+
+ prefix_r = instr & (1ul << 20);
+ ra = (suffix >> 16) & 0x1f;
+
+ d0 = instr & 0x3ffff;
+ d1 = suffix & 0xffff;
+ d = (d0 << 16) | d1;
+
+ /*
+ * sign extend a 34 bit number
+ */
+ dd = (unsigned int)(d >> 2);
+ ea = (signed int)dd;
+ ea = (ea << 2) | (d & 0x3);
+
+ if (!prefix_r && ra)
+ ea += regs->gpr[ra];
+ else if (!prefix_r && !ra)
+ ; /* Leave ea as is */
+ else if (prefix_r && !ra)
+ ea += regs->nip;
+ else if (prefix_r && ra)
+ ; /* Invalid form. Should already be checked for by caller! */
+
+ return ea;
+}
+
/*
* Return the largest power of 2, not greater than sizeof(unsigned long),
* such that x is a multiple of it.
@@ -1166,6 +1204,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
struct ppc_inst instr)
{
unsigned int opcode, ra, rb, rc, rd, spr, u;
+ unsigned int suffixopcode, prefixtype, prefix_r;
unsigned long int imm;
unsigned long int val, val2;
unsigned int mb, me, sh;
@@ -2652,6 +2691,126 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
break;
}
break;
+ case 1: /* Prefixed instructions */
+ prefix_r = word & (1ul << 20);
+ ra = (suffix >> 16) & 0x1f;
+ op->update_reg = ra;
+ rd = (suffix >> 21) & 0x1f;
+ op->reg = rd;
+ op->val = regs->gpr[rd];
+
+ suffixopcode = suffix >> 26;
+ prefixtype = (word >> 24) & 0x3;
+ switch (prefixtype) {
+ case 0: /* Type 00 Eight-Byte Load/Store */
+ if (prefix_r && ra)
+ break;
+ op->ea = mlsd_8lsd_ea(word, suffix, regs);
+ switch (suffixopcode) {
+ case 41: /* plwa */
+ op->type = MKOP(LOAD, PREFIXED | SIGNEXT, 4);
+ break;
+ case 42: /* plxsd */
+ op->reg = rd + 32;
+ op->type = MKOP(LOAD_VSX, PREFIXED, 8);
+ op->element_size = 8;
+ op->vsx_flags = VSX_CHECK_VEC;
+ break;
+ case 43: /* plxssp */
+ op->reg = rd + 32;
+ op->type = MKOP(LOAD_VSX, PREFIXED, 4);
+ op->element_size = 8;
+ op->vsx_flags = VSX_FPCONV | VSX_CHECK_VEC;
+ break;
+ case 46: /* pstxsd */
+ op->reg = rd + 32;
+ op->type = MKOP(STORE_VSX, PREFIXED, 8);
+ op->element_size = 8;
+ op->vsx_flags = VSX_CHECK_VEC;
+ break;
+ case 47: /* pstxssp */
+ op->reg = rd + 32;
+ op->type = MKOP(STORE_VSX, PREFIXED, 4);
+ op->element_size = 8;
+ op->vsx_flags = VSX_FPCONV | VSX_CHECK_VEC;
+ break;
+ case 51: /* plxv1 */
+ op->reg += 32;
+
+ /* fallthru */
+ case 50: /* plxv0 */
+ op->type = MKOP(LOAD_VSX, PREFIXED, 16);
+ op->element_size = 16;
+ op->vsx_flags = VSX_CHECK_VEC;
+ break;
+ case 55: /* pstxv1 */
+ op->reg = rd + 32;
+
+ /* fallthru */
+ case 54: /* pstxv0 */
+ op->type = MKOP(STORE_VSX, PREFIXED, 16);
+ op->element_size = 16;
+ op->vsx_flags = VSX_CHECK_VEC;
+ break;
+ case 56: /* plq */
+ op->type = MKOP(LOAD, PREFIXED, 16);
+ break;
+ case 57: /* pld */
+ op->type = MKOP(LOAD, PREFIXED, 8);
+ break;
+ case 60: /* stq */
+ op->type = MKOP(STORE, PREFIXED, 16);
+ break;
+ case 61: /* pstd */
+ op->type = MKOP(STORE, PREFIXED, 8);
+ break;
+ }
+ break;
+ case 1: /* Type 01 Eight-Byte Register-to-Register */
+ break;
+ case 2: /* Type 10 Modified Load/Store */
+ if (prefix_r && ra)
+ break;
+ op->ea = mlsd_8lsd_ea(word, suffix, regs);
+ switch (suffixopcode) {
+ case 32: /* plwz */
+ op->type = MKOP(LOAD, PREFIXED, 4);
+ break;
+ case 34: /* plbz */
+ op->type = MKOP(LOAD, PREFIXED, 1);
+ break;
+ case 36: /* pstw */
+ op->type = MKOP(STORE, PREFIXED, 4);
+ break;
+ case 38: /* pstb */
+ op->type = MKOP(STORE, PREFIXED, 1);
+ break;
+ case 40: /* plhz */
+ op->type = MKOP(LOAD, PREFIXED, 2);
+ break;
+ case 42: /* plha */
+ op->type = MKOP(LOAD, PREFIXED | SIGNEXT, 2);
+ break;
+ case 44: /* psth */
+ op->type = MKOP(STORE, PREFIXED, 2);
+ break;
+ case 48: /* plfs */
+ op->type = MKOP(LOAD_FP, PREFIXED | FPCONV, 4);
+ break;
+ case 50: /* plfd */
+ op->type = MKOP(LOAD_FP, PREFIXED, 8);
+ break;
+ case 52: /* pstfs */
+ op->type = MKOP(STORE_FP, PREFIXED | FPCONV, 4);
+ break;
+ case 54: /* pstfd */
+ op->type = MKOP(STORE_FP, PREFIXED, 8);
+ break;
+ }
+ break;
+ case 3: /* Type 11 Modified Register-to-Register */
+ break;
+ }
#endif /* __powerpc64__ */
}
--
2.17.1
^ permalink raw reply related [flat|nested] 71+ messages in thread
* [PATCH v5 21/21] powerpc sstep: Add support for prefixed fixed-point arithmetic
2020-04-06 8:09 [PATCH v5 00/21] Initial Prefixed Instruction support Jordan Niethe
` (19 preceding siblings ...)
2020-04-06 8:09 ` [PATCH v5 20/21] powerpc sstep: Add support for prefixed load/stores Jordan Niethe
@ 2020-04-06 8:09 ` Jordan Niethe
2020-04-09 6:39 ` [PATCH v5 00/21] Initial Prefixed Instruction support Christophe Leroy
21 siblings, 0 replies; 71+ messages in thread
From: Jordan Niethe @ 2020-04-06 8:09 UTC (permalink / raw)
To: linuxppc-dev; +Cc: alistair, npiggin, bala24, Jordan Niethe, dja
This adds emulation support for the following prefixed Fixed-Point
Arithmetic instructions:
* Prefixed Add Immediate (paddi)
Reviewed-by: Balamuruhan S <bala24@linux.ibm.com>
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v3: Since we moved the prefixed loads/stores into the load/store switch
statement it no longer makes sense to have paddi in there, so move it
out.
---
arch/powerpc/lib/sstep.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index 8b6aee0ee636..eb24dbfc051a 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -1335,6 +1335,26 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
switch (opcode) {
#ifdef __powerpc64__
+ case 1:
+ prefix_r = word & (1ul << 20);
+ ra = (suffix >> 16) & 0x1f;
+ rd = (suffix >> 21) & 0x1f;
+ op->reg = rd;
+ op->val = regs->gpr[rd];
+ suffixopcode = suffix >> 26;
+ prefixtype = (word >> 24) & 0x3;
+ switch (prefixtype) {
+ case 2:
+ if (prefix_r && ra)
+ return 0;
+ switch (suffixopcode) {
+ case 14: /* paddi */
+ op->type = COMPUTE | PREFIXED;
+ op->val = mlsd_8lsd_ea(word, suffix, regs);
+ goto compute_done;
+ }
+ }
+ break;
case 2: /* tdi */
if (rd & trap_compare(regs->gpr[ra], (short) word))
goto trap;
--
2.17.1
^ permalink raw reply related [flat|nested] 71+ messages in thread
* Re: [PATCH v5 05/21] powerpc: Use a function for getting the instruction op code
2020-04-06 8:09 ` [PATCH v5 05/21] powerpc: Use a function for getting the instruction op code Jordan Niethe
@ 2020-04-06 8:22 ` Christophe Leroy
2020-04-06 9:38 ` Jordan Niethe
2020-04-07 7:04 ` Balamuruhan S
2020-04-08 18:21 ` Segher Boessenkool
2 siblings, 1 reply; 71+ messages in thread
From: Christophe Leroy @ 2020-04-06 8:22 UTC (permalink / raw)
To: Jordan Niethe, linuxppc-dev; +Cc: bala24, alistair, dja, npiggin
Le 06/04/2020 à 10:09, Jordan Niethe a écrit :
> In preparation for using a data type for instructions that can not be
> directly used with the '>>' operator use a function for getting the op
> code of an instruction.
>
> Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> ---
> v4: New to series
> ---
> arch/powerpc/include/asm/inst.h | 5 +++++
> arch/powerpc/kernel/align.c | 2 +-
> arch/powerpc/lib/code-patching.c | 4 ++--
What about store_updates_sp() in mm/fault.c ?
Christophe
> 3 files changed, 8 insertions(+), 3 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h
> index 5298ba33b6e5..93959016fe4b 100644
> --- a/arch/powerpc/include/asm/inst.h
> +++ b/arch/powerpc/include/asm/inst.h
> @@ -8,4 +8,9 @@
>
> #define ppc_inst(x) (x)
>
> +static inline int ppc_inst_opcode(u32 x)
> +{
> + return x >> 26;
> +}
> +
> #endif /* _ASM_INST_H */
> diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
> index 86e9bf62f18c..691013aa9f3c 100644
> --- a/arch/powerpc/kernel/align.c
> +++ b/arch/powerpc/kernel/align.c
> @@ -314,7 +314,7 @@ int fix_alignment(struct pt_regs *regs)
> }
>
> #ifdef CONFIG_SPE
> - if ((instr >> 26) == 0x4) {
> + if (ppc_inst_opcode(instr) == 0x4) {
> int reg = (instr >> 21) & 0x1f;
> PPC_WARN_ALIGNMENT(spe, regs);
> return emulate_spe(regs, reg, instr);
> diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
> index fdf0d6ea3575..099a515202aa 100644
> --- a/arch/powerpc/lib/code-patching.c
> +++ b/arch/powerpc/lib/code-patching.c
> @@ -231,7 +231,7 @@ bool is_offset_in_branch_range(long offset)
> */
> bool is_conditional_branch(unsigned int instr)
> {
> - unsigned int opcode = instr >> 26;
> + unsigned int opcode = ppc_inst_opcode(instr);
>
> if (opcode == 16) /* bc, bca, bcl, bcla */
> return true;
> @@ -289,7 +289,7 @@ int create_cond_branch(unsigned int *instr, const unsigned int *addr,
>
> static unsigned int branch_opcode(unsigned int instr)
> {
> - return (instr >> 26) & 0x3F;
> + return ppc_inst_opcode(instr) & 0x3F;
> }
>
> static int instr_is_branch_iform(unsigned int instr)
>
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 05/21] powerpc: Use a function for getting the instruction op code
2020-04-06 8:22 ` Christophe Leroy
@ 2020-04-06 9:38 ` Jordan Niethe
0 siblings, 0 replies; 71+ messages in thread
From: Jordan Niethe @ 2020-04-06 9:38 UTC (permalink / raw)
To: Christophe Leroy
Cc: Alistair Popple, Nicholas Piggin, Balamuruhan S, linuxppc-dev,
Daniel Axtens
On Mon, Apr 6, 2020 at 6:22 PM Christophe Leroy <christophe.leroy@c-s.fr> wrote:
>
>
>
> Le 06/04/2020 à 10:09, Jordan Niethe a écrit :
> > In preparation for using a data type for instructions that can not be
> > directly used with the '>>' operator use a function for getting the op
> > code of an instruction.
> >
> > Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> > ---
> > v4: New to series
> > ---
> > arch/powerpc/include/asm/inst.h | 5 +++++
> > arch/powerpc/kernel/align.c | 2 +-
> > arch/powerpc/lib/code-patching.c | 4 ++--
>
> What about store_updates_sp() in mm/fault.c ?
True. An early revision of this series used analyse_instr() there,
which ended up causing issues. But it still can use the instruction
data type. I will change that.
>
> Christophe
>
> > 3 files changed, 8 insertions(+), 3 deletions(-)
> >
> > diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h
> > index 5298ba33b6e5..93959016fe4b 100644
> > --- a/arch/powerpc/include/asm/inst.h
> > +++ b/arch/powerpc/include/asm/inst.h
> > @@ -8,4 +8,9 @@
> >
> > #define ppc_inst(x) (x)
> >
> > +static inline int ppc_inst_opcode(u32 x)
> > +{
> > + return x >> 26;
> > +}
> > +
> > #endif /* _ASM_INST_H */
> > diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
> > index 86e9bf62f18c..691013aa9f3c 100644
> > --- a/arch/powerpc/kernel/align.c
> > +++ b/arch/powerpc/kernel/align.c
> > @@ -314,7 +314,7 @@ int fix_alignment(struct pt_regs *regs)
> > }
> >
> > #ifdef CONFIG_SPE
> > - if ((instr >> 26) == 0x4) {
> > + if (ppc_inst_opcode(instr) == 0x4) {
> > int reg = (instr >> 21) & 0x1f;
> > PPC_WARN_ALIGNMENT(spe, regs);
> > return emulate_spe(regs, reg, instr);
> > diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
> > index fdf0d6ea3575..099a515202aa 100644
> > --- a/arch/powerpc/lib/code-patching.c
> > +++ b/arch/powerpc/lib/code-patching.c
> > @@ -231,7 +231,7 @@ bool is_offset_in_branch_range(long offset)
> > */
> > bool is_conditional_branch(unsigned int instr)
> > {
> > - unsigned int opcode = instr >> 26;
> > + unsigned int opcode = ppc_inst_opcode(instr);
> >
> > if (opcode == 16) /* bc, bca, bcl, bcla */
> > return true;
> > @@ -289,7 +289,7 @@ int create_cond_branch(unsigned int *instr, const unsigned int *addr,
> >
> > static unsigned int branch_opcode(unsigned int instr)
> > {
> > - return (instr >> 26) & 0x3F;
> > + return ppc_inst_opcode(instr) & 0x3F;
> > }
> >
> > static int instr_is_branch_iform(unsigned int instr)
> >
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 18/21] powerpc64: Add prefixed instructions to instruction data type
2020-04-06 8:09 ` [PATCH v5 18/21] powerpc64: Add prefixed instructions to instruction data type Jordan Niethe
@ 2020-04-06 9:52 ` Alistair Popple
2020-04-06 10:25 ` Christophe Leroy
2020-04-06 10:42 ` Jordan Niethe
2020-04-06 11:04 ` kbuild test robot
2020-04-13 12:04 ` Balamuruhan S
2 siblings, 2 replies; 71+ messages in thread
From: Alistair Popple @ 2020-04-06 9:52 UTC (permalink / raw)
To: Jordan Niethe; +Cc: npiggin, bala24, linuxppc-dev, dja
> diff --git a/arch/powerpc/include/asm/inst.h
> b/arch/powerpc/include/asm/inst.h index 70b37a35a91a..7e23e7146c66 100644
> --- a/arch/powerpc/include/asm/inst.h
> +++ b/arch/powerpc/include/asm/inst.h
> @@ -8,23 +8,67 @@
>
> struct ppc_inst {
> u32 val;
> +#ifdef __powerpc64__
> + u32 suffix;
> +#endif /* __powerpc64__ */
> } __packed;
>
> -#define ppc_inst(x) ((struct ppc_inst){ .val = x })
> +static inline int ppc_inst_opcode(struct ppc_inst x)
> +{
> + return x.val >> 26;
> +}
>
> static inline u32 ppc_inst_val(struct ppc_inst x)
> {
> return x.val;
> }
>
> -static inline bool ppc_inst_len(struct ppc_inst x)
> +#ifdef __powerpc64__
> +#define ppc_inst(x) ((struct ppc_inst){ .val = (x), .suffix = 0xff })
> +
> +#define ppc_inst_prefix(x, y) ((struct ppc_inst){ .val = (x), .suffix = (y)
> }) +
> +static inline u32 ppc_inst_suffix(struct ppc_inst x)
> {
> - return sizeof(struct ppc_inst);
> + return x.suffix;
> }
>
> -static inline int ppc_inst_opcode(struct ppc_inst x)
> +static inline bool ppc_inst_prefixed(struct ppc_inst x) {
> + return ((ppc_inst_val(x) >> 26) == 1) && ppc_inst_suffix(x) != 0xff;
> +}
> +
> +static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
> {
> - return x.val >> 26;
> + return ppc_inst_prefix(swab32(ppc_inst_val(x)),
> + swab32(ppc_inst_suffix(x)));
> +}
> +
> +static inline struct ppc_inst ppc_inst_read(const struct ppc_inst *ptr)
> +{
> + u32 val, suffix = 0xff;
> + val = *(u32 *)ptr;
> + if ((val >> 26) == 1)
> + suffix = *((u32 *)ptr + 1);
> + return ppc_inst_prefix(val, suffix);
> +}
> +
> +static inline void ppc_inst_write(struct ppc_inst *ptr, struct ppc_inst x)
> +{
> + if (ppc_inst_prefixed(x)) {
> + *(u32 *)ptr = x.val;
> + *((u32 *)ptr + 1) = x.suffix;
> + } else {
> + *(u32 *)ptr = x.val;
> + }
> +}
> +
> +#else
> +
> +#define ppc_inst(x) ((struct ppc_inst){ .val = x })
> +
> +static inline bool ppc_inst_prefixed(ppc_inst x)
> +{
> + return 0;
> }
>
> static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
> @@ -32,14 +76,31 @@ static inline struct ppc_inst ppc_inst_swab(struct
> ppc_inst x) return ppc_inst(swab32(ppc_inst_val(x)));
> }
>
> +static inline u32 ppc_inst_val(struct ppc_inst x)
> +{
> + return x.val;
> +}
> +
> static inline struct ppc_inst ppc_inst_read(const struct ppc_inst *ptr)
> {
> return *ptr;
> }
>
> +static inline void ppc_inst_write(struct ppc_inst *ptr, struct ppc_inst x)
> +{
> + *ptr = x;
> +}
> +
> +#endif /* __powerpc64__ */
> +
> static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
> {
> return !memcmp(&x, &y, sizeof(struct ppc_inst));
> }
Apologies for not picking this up earlier, I was hoping to get to the bottom
of the issue I was seeing before you sent out v5. However the above definition
of instruction equality does not seem correct because it does not consider the
case when an instruction is not prefixed - a non-prefixed instruction should be
considered equal if the first 32-bit opcode/value is the same. Something like:
if (ppc_inst_prefixed(x) != ppc_inst_prefixed(y))
return false;
else if (ppc_inst_prefixed(x))
return !memcmp(&x, &y, sizeof(struct ppc_inst));
else
return x.val == y.val;
This was causing failures in ftrace_modify_code() as it would falsely detect
two non-prefixed instructions as being not equal due to differences in the suffix.
- Alistair
> +static inline int ppc_inst_len(struct ppc_inst x)
> +{
> + return (ppc_inst_prefixed(x)) ? 8 : 4;
> +}
> +
> #endif /* _ASM_INST_H */
> diff --git a/arch/powerpc/include/asm/kprobes.h
> b/arch/powerpc/include/asm/kprobes.h index 66b3f2983b22..4fc0e15e23a5
> 100644
> --- a/arch/powerpc/include/asm/kprobes.h
> +++ b/arch/powerpc/include/asm/kprobes.h
> @@ -43,7 +43,7 @@ extern kprobe_opcode_t optprobe_template_ret[];
> extern kprobe_opcode_t optprobe_template_end[];
>
> /* Fixed instruction size for powerpc */
> -#define MAX_INSN_SIZE 1
> +#define MAX_INSN_SIZE 2
> #define MAX_OPTIMIZED_LENGTH sizeof(kprobe_opcode_t) /* 4 bytes */
> #define MAX_OPTINSN_SIZE (optprobe_template_end - optprobe_template_entry)
> #define RELATIVEJUMP_SIZE sizeof(kprobe_opcode_t) /* 4 bytes */
> diff --git a/arch/powerpc/include/asm/uaccess.h
> b/arch/powerpc/include/asm/uaccess.h index c0a35e4586a5..5a3f486ddf02
> 100644
> --- a/arch/powerpc/include/asm/uaccess.h
> +++ b/arch/powerpc/include/asm/uaccess.h
> @@ -105,11 +105,34 @@ 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)))
>
> -#define __get_user_instr(x, ptr) \
> - __get_user_nocheck((x).val, (u32 *)(ptr), sizeof(u32), true)
> +#define __get_user_instr(x, ptr) \
> +({ \
> + long __gui_ret = 0; \
> + unsigned int prefix, suffix; \
> + __gui_ret = __get_user(prefix, (unsigned int __user *)ptr); \
> + if (!__gui_ret && (prefix >> 26) == 1) { \
> + __gui_ret = __get_user(suffix, (unsigned int __user *)ptr + 1); \
> + (x) = ppc_inst_prefix(prefix, suffix); \
> + } else { \
> + (x) = ppc_inst(prefix); \
> + } \
> + __gui_ret; \
> +})
> +
> +#define __get_user_instr_inatomic(x, ptr) \
> +({ \
> + long __gui_ret = 0; \
> + unsigned int prefix, suffix; \
> + __gui_ret = __get_user_inatomic(prefix, (unsigned int __user *)ptr); \
> + if (!__gui_ret && (prefix >> 26) == 1) { \
> + __gui_ret = __get_user_inatomic(suffix, (unsigned int __user *)ptr +
> 1); \ + (x) = ppc_inst_prefix(prefix, suffix); \
> + } else { \
> + (x) = ppc_inst(prefix); \
> + } \
> + __gui_ret; \
> +})
>
> -#define __get_user_instr_inatomic(x, ptr) \
> - __get_user_nosleep((x).val, (u32 *)(ptr), sizeof(u32))
> extern long __put_user_bad(void);
>
> /*
> diff --git a/arch/powerpc/include/asm/uprobes.h
> b/arch/powerpc/include/asm/uprobes.h index 7e3b329ba2d3..5bf65f5d44a9
> 100644
> --- a/arch/powerpc/include/asm/uprobes.h
> +++ b/arch/powerpc/include/asm/uprobes.h
> @@ -15,7 +15,7 @@
>
> typedef ppc_opcode_t uprobe_opcode_t;
>
> -#define MAX_UINSN_BYTES 4
> +#define MAX_UINSN_BYTES 8
> #define UPROBE_XOL_SLOT_BYTES (MAX_UINSN_BYTES)
>
> /* The following alias is needed for reference from arch-agnostic code */
> diff --git a/arch/powerpc/kernel/optprobes.c
> b/arch/powerpc/kernel/optprobes.c index 684640b8fa2e..689daf430161 100644
> --- a/arch/powerpc/kernel/optprobes.c
> +++ b/arch/powerpc/kernel/optprobes.c
> @@ -159,38 +159,38 @@ void patch_imm32_load_insns(unsigned int val,
> kprobe_opcode_t *addr)
>
> /*
> * Generate instructions to load provided immediate 64-bit value
> - * to register 'r3' and patch these instructions at 'addr'.
> + * to register 'reg' and patch these instructions at 'addr'.
> */
> -void patch_imm64_load_insns(unsigned long val, kprobe_opcode_t *addr)
> +void patch_imm64_load_insns(unsigned long val, int reg, kprobe_opcode_t
> *addr) {
> - /* lis r3,(op)@highest */
> - patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ADDIS |
> ___PPC_RT(3) | + /* lis reg,(op)@highest */
> + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ADDIS |
> ___PPC_RT(reg) | ((val >> 48) & 0xffff)));
> addr++;
>
> - /* ori r3,r3,(op)@higher */
> - patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI |
> ___PPC_RA(3) | - ___PPC_RS(3) | ((val >> 32) & 0xffff)));
> + /* ori reg,reg,(op)@higher */
> + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI |
> ___PPC_RA(reg) | + ___PPC_RS(reg) | ((val >> 32) & 0xffff)));
> addr++;
>
> - /* rldicr r3,r3,32,31 */
> - patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_RLDICR |
> ___PPC_RA(3) | - ___PPC_RS(3) | __PPC_SH64(32) | __PPC_ME64(31)));
> + /* rldicr reg,reg,32,31 */
> + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_RLDICR |
> ___PPC_RA(reg) | + ___PPC_RS(reg) | __PPC_SH64(32) |
__PPC_ME64(31)));
> addr++;
>
> - /* oris r3,r3,(op)@h */
> - patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORIS |
> ___PPC_RA(3) | - ___PPC_RS(3) | ((val >> 16) & 0xffff)));
> + /* oris reg,reg,(op)@h */
> + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORIS |
> ___PPC_RA(reg) | + ___PPC_RS(reg) | ((val >> 16) & 0xffff)));
> addr++;
>
> - /* ori r3,r3,(op)@l */
> - patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI |
> ___PPC_RA(3) | - ___PPC_RS(3) | (val & 0xffff)));
> + /* ori reg,reg,(op)@l */
> + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI |
> ___PPC_RA(reg) | + ___PPC_RS(reg) | (val & 0xffff)));
> }
>
> int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct
> kprobe *p) {
> - struct ppc_inst branch_op_callback, branch_emulate_step;
> + struct ppc_inst branch_op_callback, branch_emulate_step, temp;
> kprobe_opcode_t *op_callback_addr, *emulate_step_addr, *buff;
> long b_offset;
> unsigned long nip, size;
> @@ -240,7 +240,7 @@ int arch_prepare_optimized_kprobe(struct
> optimized_kprobe *op, struct kprobe *p) * Fixup the template with
> instructions to:
> * 1. load the address of the actual probepoint
> */
> - patch_imm64_load_insns((unsigned long)op, buff + TMPL_OP_IDX);
> + patch_imm64_load_insns((unsigned long)op, 3, buff + TMPL_OP_IDX);
>
> /*
> * 2. branch to optimized_callback() and emulate_step()
> @@ -271,7 +271,11 @@ int arch_prepare_optimized_kprobe(struct
> optimized_kprobe *op, struct kprobe *p) /*
> * 3. load instruction to be emulated into relevant register, and
> */
> - patch_imm32_load_insns(*p->ainsn.insn, buff + TMPL_INSN_IDX);
> + 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);
>
> /*
> * 4. branch back from trampoline
> diff --git a/arch/powerpc/kernel/optprobes_head.S
> b/arch/powerpc/kernel/optprobes_head.S index cf383520843f..ff8ba4d3824d
> 100644
> --- a/arch/powerpc/kernel/optprobes_head.S
> +++ b/arch/powerpc/kernel/optprobes_head.S
> @@ -94,6 +94,9 @@ optprobe_template_insn:
> /* 2, Pass instruction to be emulated in r4 */
> nop
> nop
> + nop
> + nop
> + nop
>
> .global optprobe_template_call_emulate
> optprobe_template_call_emulate:
> diff --git a/arch/powerpc/kernel/trace/ftrace.c
> b/arch/powerpc/kernel/trace/ftrace.c index e78742613b36..16041a5c86d5
> 100644
> --- a/arch/powerpc/kernel/trace/ftrace.c
> +++ b/arch/powerpc/kernel/trace/ftrace.c
> @@ -41,11 +41,35 @@
> #define NUM_FTRACE_TRAMPS 8
> static unsigned long ftrace_tramps[NUM_FTRACE_TRAMPS];
>
> +#ifdef __powerpc64__
> static long
> probe_kernel_read_inst(struct ppc_inst *inst, const void *src)
> {
> - return probe_kernel_read((void *)inst, src, MCOUNT_INSN_SIZE);
> + u32 val, suffix = 0;
> + long err;
> +
> + err = probe_kernel_read((void *)&val,
> + src, sizeof(val));
> + if (err)
> + return err;
> +
> + if ((val >> 26) == 1)
> + err = probe_kernel_read((void *)&suffix,
> + src + 4, MCOUNT_INSN_SIZE);
> + if (err)
> + return err;
> +
> + *inst = ppc_inst_prefix(val, suffix);
> +
> + return 0;
> }
> +#else
> +static long
> +probe_kernel_read_inst(struct ppc_inst *inst, const void *src)
> +{
> + return probe_kernel_read((void *)inst, src, MCOUNT_INSN_SIZE)
> +}
> +#endif
>
> static struct ppc_inst
> ftrace_call_replace(unsigned long ip, unsigned long addr, int link)
> diff --git a/arch/powerpc/lib/code-patching.c
> b/arch/powerpc/lib/code-patching.c index c329ad657302..b4007e03d8fa 100644
> --- a/arch/powerpc/lib/code-patching.c
> +++ b/arch/powerpc/lib/code-patching.c
> @@ -24,12 +24,19 @@ static int __patch_instruction(struct ppc_inst
> *exec_addr, struct ppc_inst instr {
> int err = 0;
>
> - __put_user_asm(ppc_inst_val(instr), patch_addr, err, "stw");
> - if (err)
> - return err;
> -
> - asm ("dcbst 0, %0; sync; icbi 0,%1; sync; isync" :: "r" (patch_addr),
> - "r" (exec_addr));
> + if (!ppc_inst_prefixed(instr)) {
> + __put_user_asm(ppc_inst_val(instr), patch_addr, err, "stw");
> + if (err)
> + return err;
> + asm ("dcbst 0, %0; sync; icbi 0,%1; sync; isync" :: "r" (patch_addr),
> + "r" (exec_addr));
> + } else {
> + __put_user_asm((u64)ppc_inst_suffix(instr) << 32 | ppc_inst_val(instr),
> patch_addr, err, "std"); + 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/feature-fixups.c
> b/arch/powerpc/lib/feature-fixups.c index f00dd13b1c3c..5519cec83cc8 100644
> --- a/arch/powerpc/lib/feature-fixups.c
> +++ b/arch/powerpc/lib/feature-fixups.c
> @@ -84,12 +84,13 @@ static int patch_feature_section(unsigned long value,
> struct fixup_entry *fcur) src = alt_start;
> dest = start;
>
> - for (; src < alt_end; src++, dest++) {
> + for (; src < alt_end; src = (void *)src +
> ppc_inst_len(ppc_inst_read(src)), + (dest = (void *)dest +
> ppc_inst_len(ppc_inst_read(dest)))) { if (patch_alt_instruction(src, dest,
> alt_start, alt_end))
> return 1;
> }
>
> - for (; dest < end; dest++)
> + for (; dest < end; dest = (void *)dest +
> ppc_inst_len(ppc_inst(PPC_INST_NOP))) raw_patch_instruction(dest,
> ppc_inst(PPC_INST_NOP));
>
> return 0;
> diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
> index 52ddd3122dc8..8b285bf11218 100644
> --- a/arch/powerpc/lib/sstep.c
> +++ b/arch/powerpc/lib/sstep.c
> @@ -1169,10 +1169,12 @@ int analyse_instr(struct instruction_op *op, const
> struct pt_regs *regs, unsigned long int imm;
> unsigned long int val, val2;
> unsigned int mb, me, sh;
> - unsigned int word;
> + unsigned int word, suffix;
> long ival;
>
> word = ppc_inst_val(instr);
> + suffix = ppc_inst_suffix(instr);
> +
> op->type = COMPUTE;
>
> opcode = word >> 26;
> diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
> index 6f3bcdcfc9c7..b704aebb099a 100644
> --- a/arch/powerpc/xmon/xmon.c
> +++ b/arch/powerpc/xmon/xmon.c
> @@ -761,8 +761,8 @@ static int xmon_bpt(struct pt_regs *regs)
>
> /* Are we at the trap at bp->instr[1] for some bp? */
> bp = in_breakpoint_table(regs->nip, &offset);
> - if (bp != NULL && offset == 4) {
> - regs->nip = bp->address + 4;
> + if (bp != NULL && (offset == 4 || offset == 8)) {
> + regs->nip = bp->address + offset;
> atomic_dec(&bp->ref_count);
> return 1;
> }
> @@ -863,7 +863,7 @@ static struct bpt *in_breakpoint_table(unsigned long
> nip, unsigned long *offp) if (off >= sizeof(bpt_table))
> return NULL;
> *offp = off % BPT_SIZE;
> - if (*offp != 0 && *offp != 4)
> + if (*offp != 0 && *offp != 4 && *offp != 8)
> return NULL;
> return bpts + (off / BPT_SIZE);
> }
> diff --git a/arch/powerpc/xmon/xmon_bpts.S b/arch/powerpc/xmon/xmon_bpts.S
> index ebb2dbc70ca8..09058eb6abbd 100644
> --- a/arch/powerpc/xmon/xmon_bpts.S
> +++ b/arch/powerpc/xmon/xmon_bpts.S
> @@ -3,6 +3,8 @@
> #include <asm/asm-compat.h>
> #include "xmon_bpts.h"
>
> +/* Prefixed instructions can not cross 64 byte boundaries */
> +.align 6
> .global bpt_table
> bpt_table:
> - .space NBPTS * 8
> + .space NBPTS * 16
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 18/21] powerpc64: Add prefixed instructions to instruction data type
2020-04-06 9:52 ` Alistair Popple
@ 2020-04-06 10:25 ` Christophe Leroy
2020-04-06 11:13 ` Jordan Niethe
2020-04-08 18:11 ` Segher Boessenkool
2020-04-06 10:42 ` Jordan Niethe
1 sibling, 2 replies; 71+ messages in thread
From: Christophe Leroy @ 2020-04-06 10:25 UTC (permalink / raw)
To: Alistair Popple, Jordan Niethe; +Cc: bala24, linuxppc-dev, npiggin, dja
Le 06/04/2020 à 11:52, Alistair Popple a écrit :
[...]
>> @@ -32,14 +76,31 @@ static inline struct ppc_inst ppc_inst_swab(struct
>> ppc_inst x) return ppc_inst(swab32(ppc_inst_val(x)));
>> }
>>
>> +static inline u32 ppc_inst_val(struct ppc_inst x)
>> +{
>> + return x.val;
>> +}
>> +
>> static inline struct ppc_inst ppc_inst_read(const struct ppc_inst *ptr)
>> {
>> return *ptr;
>> }
>>
>> +static inline void ppc_inst_write(struct ppc_inst *ptr, struct ppc_inst x)
>> +{
>> + *ptr = x;
>> +}
>> +
>> +#endif /* __powerpc64__ */
>> +
>> static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
>> {
>> return !memcmp(&x, &y, sizeof(struct ppc_inst));
>> }
>
> Apologies for not picking this up earlier, I was hoping to get to the bottom
> of the issue I was seeing before you sent out v5. However the above definition
> of instruction equality does not seem correct because it does not consider the
> case when an instruction is not prefixed - a non-prefixed instruction should be
> considered equal if the first 32-bit opcode/value is the same. Something like:
>
> if (ppc_inst_prefixed(x) != ppc_inst_prefixed(y))
> return false;
> else if (ppc_inst_prefixed(x))
> return !memcmp(&x, &y, sizeof(struct ppc_inst));
Are we sure memcmp() is a good candidate for the comparison ? Can we do
simpler ? Especially, I understood a prefixed instruction is a 64 bits
properly aligned instruction, can we do a simple u64 compare ? Or is GCC
intelligent enough to do that without calling memcmp() function which is
heavy ?
> else
> return x.val == y.val;
>
> This was causing failures in ftrace_modify_code() as it would falsely detect
> two non-prefixed instructions as being not equal due to differences in the suffix.
>
Christophe
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 03/21] powerpc: Change calling convention for create_branch() et. al.
2020-04-06 8:09 ` [PATCH v5 03/21] powerpc: Change calling convention for create_branch() et. al Jordan Niethe
@ 2020-04-06 10:25 ` kbuild test robot
2020-04-07 6:10 ` Balamuruhan S
1 sibling, 0 replies; 71+ messages in thread
From: kbuild test robot @ 2020-04-06 10:25 UTC (permalink / raw)
To: Jordan Niethe
Cc: kbuild-all, Jordan Niethe, npiggin, bala24, alistair, linuxppc-dev, dja
[-- Attachment #1: Type: text/plain, Size: 3282 bytes --]
Hi Jordan,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on v5.6]
[also build test ERROR on next-20200406]
[cannot apply to powerpc/next kvm-ppc/kvm-ppc-next scottwood/next]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]
url: https://github.com/0day-ci/linux/commits/Jordan-Niethe/Initial-Prefixed-Instruction-support/20200406-165215
base: 7111951b8d4973bda27ff663f2cf18b663d15b48
config: powerpc-allnoconfig (attached as .config)
compiler: powerpc-linux-gcc (GCC) 9.3.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=9.3.0 make.cross ARCH=powerpc
If you fix the issue, kindly add following tag as appropriate
Reported-by: kbuild test robot <lkp@intel.com>
All errors (new ones prefixed by >>):
arch/powerpc/kernel/setup_32.c: In function 'machine_init':
>> arch/powerpc/kernel/setup_32.c:91:21: error: passing argument 1 of 'create_cond_branch' from incompatible pointer type [-Werror=incompatible-pointer-types]
91 | create_cond_branch(&insn, addr, branch_target(addr), 0x820000);
| ^~~~~
| |
| long unsigned int *
In file included from arch/powerpc/kernel/setup_32.c:42:
arch/powerpc/include/asm/code-patching.h:27:38: note: expected 'unsigned int *' but argument is of type 'long unsigned int *'
27 | int create_cond_branch(unsigned int *instr, const unsigned int *addr,
| ~~~~~~~~~~~~~~^~~~~
cc1: all warnings being treated as errors
vim +/create_cond_branch +91 arch/powerpc/kernel/setup_32.c
67
68 /*
69 * This is run before start_kernel(), the kernel has been relocated
70 * and we are running with enough of the MMU enabled to have our
71 * proper kernel virtual addresses
72 *
73 * We do the initial parsing of the flat device-tree and prepares
74 * for the MMU to be fully initialized.
75 */
76 notrace void __init machine_init(u64 dt_ptr)
77 {
78 unsigned int *addr = (unsigned int *)patch_site_addr(&patch__memset_nocache);
79 unsigned long insn;
80
81 /* Configure static keys first, now that we're relocated. */
82 setup_feature_keys();
83
84 early_ioremap_setup();
85
86 /* Enable early debugging if any specified (see udbg.h) */
87 udbg_early_init();
88
89 patch_instruction_site(&patch__memcpy_nocache, PPC_INST_NOP);
90
> 91 create_cond_branch(&insn, addr, branch_target(addr), 0x820000);
92 patch_instruction(addr, insn); /* replace b by bne cr0 */
93
94 /* Do some early initialization based on the flat device tree */
95 early_init_devtree(__va(dt_ptr));
96
97 early_init_mmu();
98
99 setup_kdump_trampoline();
100 }
101
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 6411 bytes --]
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 03/21] powerpc: Change calling convention for create_branch() et. al.
@ 2020-04-06 10:25 ` kbuild test robot
0 siblings, 0 replies; 71+ messages in thread
From: kbuild test robot @ 2020-04-06 10:25 UTC (permalink / raw)
To: kbuild-all
[-- Attachment #1: Type: text/plain, Size: 3363 bytes --]
Hi Jordan,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on v5.6]
[also build test ERROR on next-20200406]
[cannot apply to powerpc/next kvm-ppc/kvm-ppc-next scottwood/next]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]
url: https://github.com/0day-ci/linux/commits/Jordan-Niethe/Initial-Prefixed-Instruction-support/20200406-165215
base: 7111951b8d4973bda27ff663f2cf18b663d15b48
config: powerpc-allnoconfig (attached as .config)
compiler: powerpc-linux-gcc (GCC) 9.3.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=9.3.0 make.cross ARCH=powerpc
If you fix the issue, kindly add following tag as appropriate
Reported-by: kbuild test robot <lkp@intel.com>
All errors (new ones prefixed by >>):
arch/powerpc/kernel/setup_32.c: In function 'machine_init':
>> arch/powerpc/kernel/setup_32.c:91:21: error: passing argument 1 of 'create_cond_branch' from incompatible pointer type [-Werror=incompatible-pointer-types]
91 | create_cond_branch(&insn, addr, branch_target(addr), 0x820000);
| ^~~~~
| |
| long unsigned int *
In file included from arch/powerpc/kernel/setup_32.c:42:
arch/powerpc/include/asm/code-patching.h:27:38: note: expected 'unsigned int *' but argument is of type 'long unsigned int *'
27 | int create_cond_branch(unsigned int *instr, const unsigned int *addr,
| ~~~~~~~~~~~~~~^~~~~
cc1: all warnings being treated as errors
vim +/create_cond_branch +91 arch/powerpc/kernel/setup_32.c
67
68 /*
69 * This is run before start_kernel(), the kernel has been relocated
70 * and we are running with enough of the MMU enabled to have our
71 * proper kernel virtual addresses
72 *
73 * We do the initial parsing of the flat device-tree and prepares
74 * for the MMU to be fully initialized.
75 */
76 notrace void __init machine_init(u64 dt_ptr)
77 {
78 unsigned int *addr = (unsigned int *)patch_site_addr(&patch__memset_nocache);
79 unsigned long insn;
80
81 /* Configure static keys first, now that we're relocated. */
82 setup_feature_keys();
83
84 early_ioremap_setup();
85
86 /* Enable early debugging if any specified (see udbg.h) */
87 udbg_early_init();
88
89 patch_instruction_site(&patch__memcpy_nocache, PPC_INST_NOP);
90
> 91 create_cond_branch(&insn, addr, branch_target(addr), 0x820000);
92 patch_instruction(addr, insn); /* replace b by bne cr0 */
93
94 /* Do some early initialization based on the flat device tree */
95 early_init_devtree(__va(dt_ptr));
96
97 early_init_mmu();
98
99 setup_kdump_trampoline();
100 }
101
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org
[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 6411 bytes --]
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 09/21] powerpc: Use a datatype for instructions
2020-04-06 8:09 ` [PATCH v5 09/21] powerpc: Use a datatype for instructions Jordan Niethe
@ 2020-04-06 10:34 ` kbuild test robot
2020-04-06 10:35 ` kbuild test robot
2020-04-07 10:30 ` Balamuruhan S
2 siblings, 0 replies; 71+ messages in thread
From: kbuild test robot @ 2020-04-06 10:34 UTC (permalink / raw)
To: Jordan Niethe
Cc: kbuild-all, Jordan Niethe, npiggin, bala24, alistair, linuxppc-dev, dja
[-- Attachment #1: Type: text/plain, Size: 3907 bytes --]
Hi Jordan,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on v5.6]
[cannot apply to powerpc/next kvm-ppc/kvm-ppc-next scottwood/next next-20200406]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]
url: https://github.com/0day-ci/linux/commits/Jordan-Niethe/Initial-Prefixed-Instruction-support/20200406-165215
base: 7111951b8d4973bda27ff663f2cf18b663d15b48
config: powerpc-rhel-kconfig (attached as .config)
compiler: powerpc64le-linux-gcc (GCC) 9.3.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=9.3.0 make.cross ARCH=powerpc
If you fix the issue, kindly add following tag as appropriate
Reported-by: kbuild test robot <lkp@intel.com>
All errors (new ones prefixed by >>):
arch/powerpc/lib/feature-fixups.c: In function 'do_final_fixups':
>> arch/powerpc/lib/feature-fixups.c:404:25: error: passing argument 1 of 'raw_patch_instruction' from incompatible pointer type [-Werror=incompatible-pointer-types]
404 | raw_patch_instruction(dest, ppc_inst(*src));
| ^~~~
| |
| int *
In file included from arch/powerpc/lib/feature-fixups.c:18:
arch/powerpc/include/asm/code-patching.h:32:44: note: expected 'struct ppc_inst *' but argument is of type 'int *'
32 | int raw_patch_instruction(struct ppc_inst *addr, struct ppc_inst instr);
| ~~~~~~~~~~~~~~~~~^~~~
cc1: some warnings being treated as errors
vim +/raw_patch_instruction +404 arch/powerpc/lib/feature-fixups.c
2d1b2027626d51 Kumar Gala 2008-07-02 389
9402c684613163 Benjamin Herrenschmidt 2016-07-05 390 static void do_final_fixups(void)
d715e433b7ad19 Anton Blanchard 2011-11-14 391 {
d715e433b7ad19 Anton Blanchard 2011-11-14 392 #if defined(CONFIG_PPC64) && defined(CONFIG_RELOCATABLE)
d715e433b7ad19 Anton Blanchard 2011-11-14 393 int *src, *dest;
d715e433b7ad19 Anton Blanchard 2011-11-14 394 unsigned long length;
d715e433b7ad19 Anton Blanchard 2011-11-14 395
d715e433b7ad19 Anton Blanchard 2011-11-14 396 if (PHYSICAL_START == 0)
d715e433b7ad19 Anton Blanchard 2011-11-14 397 return;
d715e433b7ad19 Anton Blanchard 2011-11-14 398
d715e433b7ad19 Anton Blanchard 2011-11-14 399 src = (int *)(KERNELBASE + PHYSICAL_START);
d715e433b7ad19 Anton Blanchard 2011-11-14 400 dest = (int *)KERNELBASE;
d715e433b7ad19 Anton Blanchard 2011-11-14 401 length = (__end_interrupts - _stext) / sizeof(int);
d715e433b7ad19 Anton Blanchard 2011-11-14 402
d715e433b7ad19 Anton Blanchard 2011-11-14 403 while (length--) {
16f7ae823ee707 Jordan Niethe 2020-04-06 @404 raw_patch_instruction(dest, ppc_inst(*src));
d715e433b7ad19 Anton Blanchard 2011-11-14 405 src++;
d715e433b7ad19 Anton Blanchard 2011-11-14 406 dest++;
d715e433b7ad19 Anton Blanchard 2011-11-14 407 }
d715e433b7ad19 Anton Blanchard 2011-11-14 408 #endif
d715e433b7ad19 Anton Blanchard 2011-11-14 409 }
d715e433b7ad19 Anton Blanchard 2011-11-14 410
:::::: The code at line 404 was first introduced by commit
:::::: 16f7ae823ee70796c5ba2cc321b2c02f3dcfb816 powerpc: Use a macro for creating instructions from u32s
:::::: TO: Jordan Niethe <jniethe5@gmail.com>
:::::: CC: 0day robot <lkp@intel.com>
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 15331 bytes --]
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 09/21] powerpc: Use a datatype for instructions
@ 2020-04-06 10:34 ` kbuild test robot
0 siblings, 0 replies; 71+ messages in thread
From: kbuild test robot @ 2020-04-06 10:34 UTC (permalink / raw)
To: kbuild-all
[-- Attachment #1: Type: text/plain, Size: 3980 bytes --]
Hi Jordan,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on v5.6]
[cannot apply to powerpc/next kvm-ppc/kvm-ppc-next scottwood/next next-20200406]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]
url: https://github.com/0day-ci/linux/commits/Jordan-Niethe/Initial-Prefixed-Instruction-support/20200406-165215
base: 7111951b8d4973bda27ff663f2cf18b663d15b48
config: powerpc-rhel-kconfig (attached as .config)
compiler: powerpc64le-linux-gcc (GCC) 9.3.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=9.3.0 make.cross ARCH=powerpc
If you fix the issue, kindly add following tag as appropriate
Reported-by: kbuild test robot <lkp@intel.com>
All errors (new ones prefixed by >>):
arch/powerpc/lib/feature-fixups.c: In function 'do_final_fixups':
>> arch/powerpc/lib/feature-fixups.c:404:25: error: passing argument 1 of 'raw_patch_instruction' from incompatible pointer type [-Werror=incompatible-pointer-types]
404 | raw_patch_instruction(dest, ppc_inst(*src));
| ^~~~
| |
| int *
In file included from arch/powerpc/lib/feature-fixups.c:18:
arch/powerpc/include/asm/code-patching.h:32:44: note: expected 'struct ppc_inst *' but argument is of type 'int *'
32 | int raw_patch_instruction(struct ppc_inst *addr, struct ppc_inst instr);
| ~~~~~~~~~~~~~~~~~^~~~
cc1: some warnings being treated as errors
vim +/raw_patch_instruction +404 arch/powerpc/lib/feature-fixups.c
2d1b2027626d51 Kumar Gala 2008-07-02 389
9402c684613163 Benjamin Herrenschmidt 2016-07-05 390 static void do_final_fixups(void)
d715e433b7ad19 Anton Blanchard 2011-11-14 391 {
d715e433b7ad19 Anton Blanchard 2011-11-14 392 #if defined(CONFIG_PPC64) && defined(CONFIG_RELOCATABLE)
d715e433b7ad19 Anton Blanchard 2011-11-14 393 int *src, *dest;
d715e433b7ad19 Anton Blanchard 2011-11-14 394 unsigned long length;
d715e433b7ad19 Anton Blanchard 2011-11-14 395
d715e433b7ad19 Anton Blanchard 2011-11-14 396 if (PHYSICAL_START == 0)
d715e433b7ad19 Anton Blanchard 2011-11-14 397 return;
d715e433b7ad19 Anton Blanchard 2011-11-14 398
d715e433b7ad19 Anton Blanchard 2011-11-14 399 src = (int *)(KERNELBASE + PHYSICAL_START);
d715e433b7ad19 Anton Blanchard 2011-11-14 400 dest = (int *)KERNELBASE;
d715e433b7ad19 Anton Blanchard 2011-11-14 401 length = (__end_interrupts - _stext) / sizeof(int);
d715e433b7ad19 Anton Blanchard 2011-11-14 402
d715e433b7ad19 Anton Blanchard 2011-11-14 403 while (length--) {
16f7ae823ee707 Jordan Niethe 2020-04-06 @404 raw_patch_instruction(dest, ppc_inst(*src));
d715e433b7ad19 Anton Blanchard 2011-11-14 405 src++;
d715e433b7ad19 Anton Blanchard 2011-11-14 406 dest++;
d715e433b7ad19 Anton Blanchard 2011-11-14 407 }
d715e433b7ad19 Anton Blanchard 2011-11-14 408 #endif
d715e433b7ad19 Anton Blanchard 2011-11-14 409 }
d715e433b7ad19 Anton Blanchard 2011-11-14 410
:::::: The code at line 404 was first introduced by commit
:::::: 16f7ae823ee70796c5ba2cc321b2c02f3dcfb816 powerpc: Use a macro for creating instructions from u32s
:::::: TO: Jordan Niethe <jniethe5@gmail.com>
:::::: CC: 0day robot <lkp@intel.com>
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org
[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 15331 bytes --]
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 09/21] powerpc: Use a datatype for instructions
2020-04-06 8:09 ` [PATCH v5 09/21] powerpc: Use a datatype for instructions Jordan Niethe
@ 2020-04-06 10:35 ` kbuild test robot
2020-04-06 10:35 ` kbuild test robot
2020-04-07 10:30 ` Balamuruhan S
2 siblings, 0 replies; 71+ messages in thread
From: kbuild test robot @ 2020-04-06 10:35 UTC (permalink / raw)
To: Jordan Niethe
Cc: kbuild-all, Jordan Niethe, npiggin, bala24, alistair, linuxppc-dev, dja
[-- Attachment #1: Type: text/plain, Size: 11038 bytes --]
Hi Jordan,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on v5.6]
[cannot apply to powerpc/next kvm-ppc/kvm-ppc-next scottwood/next next-20200406]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]
url: https://github.com/0day-ci/linux/commits/Jordan-Niethe/Initial-Prefixed-Instruction-support/20200406-165215
base: 7111951b8d4973bda27ff663f2cf18b663d15b48
config: powerpc-allnoconfig (attached as .config)
compiler: powerpc-linux-gcc (GCC) 9.3.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=9.3.0 make.cross ARCH=powerpc
If you fix the issue, kindly add following tag as appropriate
Reported-by: kbuild test robot <lkp@intel.com>
All error/warnings (new ones prefixed by >>):
In file included from arch/powerpc/include/asm/asm-compat.h:6,
from arch/powerpc/include/asm/bitops.h:42,
from include/linux/bitops.h:29,
from include/linux/kernel.h:12,
from include/linux/list.h:9,
from include/linux/module.h:12,
from arch/powerpc/kernel/setup_32.c:6:
arch/powerpc/kernel/setup_32.c: In function 'machine_init':
>> arch/powerpc/include/asm/ppc-opcode.h:234:24: error: incompatible type for argument 2 of 'patch_instruction_site'
234 | #define PPC_INST_NOP 0x60000000
| ^~~~~~~~~~
| |
| int
>> arch/powerpc/kernel/setup_32.c:89:49: note: in expansion of macro 'PPC_INST_NOP'
89 | patch_instruction_site(&patch__memcpy_nocache, PPC_INST_NOP);
| ^~~~~~~~~~~~
In file included from arch/powerpc/kernel/setup_32.c:42:
arch/powerpc/include/asm/code-patching.h:39:69: note: expected 'struct ppc_inst' but argument is of type 'int'
39 | static inline int patch_instruction_site(s32 *site, struct ppc_inst instr)
| ~~~~~~~~~~~~~~~~^~~~~
>> arch/powerpc/kernel/setup_32.c:91:48: error: passing argument 1 of 'branch_target' from incompatible pointer type [-Werror=incompatible-pointer-types]
91 | create_cond_branch(&insn, addr, branch_target(addr), 0x820000);
| ^~~~
| |
| unsigned int *
In file included from arch/powerpc/kernel/setup_32.c:42:
arch/powerpc/include/asm/code-patching.h:63:52: note: expected 'const struct ppc_inst *' but argument is of type 'unsigned int *'
63 | unsigned long branch_target(const struct ppc_inst *instr);
| ~~~~~~~~~~~~~~~~~~~~~~~^~~~~
arch/powerpc/kernel/setup_32.c:91:28: error: passing argument 2 of 'create_cond_branch' from incompatible pointer type [-Werror=incompatible-pointer-types]
91 | create_cond_branch(&insn, addr, branch_target(addr), 0x820000);
| ^~~~
| |
| unsigned int *
In file included from arch/powerpc/kernel/setup_32.c:42:
arch/powerpc/include/asm/code-patching.h:28:71: note: expected 'const struct ppc_inst *' but argument is of type 'unsigned int *'
28 | int create_cond_branch(struct ppc_inst *instr, const struct ppc_inst *addr,
| ~~~~~~~~~~~~~~~~~~~~~~~^~~~
>> arch/powerpc/kernel/setup_32.c:92:20: error: passing argument 1 of 'patch_instruction' from incompatible pointer type [-Werror=incompatible-pointer-types]
92 | patch_instruction(addr, insn); /* replace b by bne cr0 */
| ^~~~
| |
| unsigned int *
In file included from arch/powerpc/kernel/setup_32.c:42:
arch/powerpc/include/asm/code-patching.h:31:40: note: expected 'struct ppc_inst *' but argument is of type 'unsigned int *'
31 | int patch_instruction(struct ppc_inst *addr, struct ppc_inst instr);
| ~~~~~~~~~~~~~~~~~^~~~
cc1: all warnings being treated as errors
vim +/patch_instruction_site +234 arch/powerpc/include/asm/ppc-opcode.h
9123c5ed45a583 Hongtao Jia 2013-04-28 193
16c57b3620d77e Kumar Gala 2009-02-10 194 /* sorted alphabetically */
95213959aefc94 Anshuman Khandual 2013-04-22 195 #define PPC_INST_BHRBE 0x7c00025c
95213959aefc94 Anshuman Khandual 2013-04-22 196 #define PPC_INST_CLRBHRB 0x7c00035c
07d2a628bc0008 Nicholas Piggin 2017-06-09 197 #define PPC_INST_COPY 0x7c20060c
8a649045e75a4b Chris Smart 2016-04-26 198 #define PPC_INST_CP_ABORT 0x7c00068c
e66ca3db5917f4 Matt Brown 2017-08-04 199 #define PPC_INST_DARN 0x7c0005e6
16c57b3620d77e Kumar Gala 2009-02-10 200 #define PPC_INST_DCBA 0x7c0005ec
16c57b3620d77e Kumar Gala 2009-02-10 201 #define PPC_INST_DCBA_MASK 0xfc0007fe
16c57b3620d77e Kumar Gala 2009-02-10 202 #define PPC_INST_DCBAL 0x7c2005ec
16c57b3620d77e Kumar Gala 2009-02-10 203 #define PPC_INST_DCBZL 0x7c2007ec
1afc149def25ac Tony Breeds 2012-10-02 204 #define PPC_INST_ICBT 0x7c00002c
edc424f8cd84bb Dan Streetman 2015-05-07 205 #define PPC_INST_ICSWX 0x7c00032d
edc424f8cd84bb Dan Streetman 2015-05-07 206 #define PPC_INST_ICSWEPX 0x7c00076d
16c57b3620d77e Kumar Gala 2009-02-10 207 #define PPC_INST_ISEL 0x7c00001e
16c57b3620d77e Kumar Gala 2009-02-10 208 #define PPC_INST_ISEL_MASK 0xfc00003e
864b9e6fd76489 Anton Blanchard 2010-02-10 209 #define PPC_INST_LDARX 0x7c0000a8
156d0e290e969c Naveen N. Rao 2016-06-22 210 #define PPC_INST_STDCX 0x7c0001ad
350779a29f11f8 Paul Mackerras 2017-08-30 211 #define PPC_INST_LQARX 0x7c000228
350779a29f11f8 Paul Mackerras 2017-08-30 212 #define PPC_INST_STQCX 0x7c00016d
16c57b3620d77e Kumar Gala 2009-02-10 213 #define PPC_INST_LSWI 0x7c0004aa
16c57b3620d77e Kumar Gala 2009-02-10 214 #define PPC_INST_LSWX 0x7c00042a
d6ccb1f55ddf51 Kumar Gala 2010-03-10 215 #define PPC_INST_LWARX 0x7c000028
156d0e290e969c Naveen N. Rao 2016-06-22 216 #define PPC_INST_STWCX 0x7c00012d
16c57b3620d77e Kumar Gala 2009-02-10 217 #define PPC_INST_LWSYNC 0x7c2004ac
9863c28a2af90a James Yang 2013-07-03 218 #define PPC_INST_SYNC 0x7c0004ac
9863c28a2af90a James Yang 2013-07-03 219 #define PPC_INST_SYNC_MASK 0xfc0007fe
ddc6cd0d70a6f9 Christophe Leroy 2016-05-17 220 #define PPC_INST_ISYNC 0x4c00012c
dfb432cb960bfc Michael Neuling 2009-04-29 221 #define PPC_INST_LXVD2X 0x7c000698
16c57b3620d77e Kumar Gala 2009-02-10 222 #define PPC_INST_MCRXR 0x7c000400
16c57b3620d77e Kumar Gala 2009-02-10 223 #define PPC_INST_MCRXR_MASK 0xfc0007fe
16c57b3620d77e Kumar Gala 2009-02-10 224 #define PPC_INST_MFSPR_PVR 0x7c1f42a6
178f358208ceb8 Anton Blanchard 2017-01-19 225 #define PPC_INST_MFSPR_PVR_MASK 0xfc1ffffe
e16c8765533a15 Andy Fleming 2011-12-08 226 #define PPC_INST_MFTMR 0x7c0002dc
16c57b3620d77e Kumar Gala 2009-02-10 227 #define PPC_INST_MSGSND 0x7c00019c
755563bc79c764 Paul Mackerras 2015-03-19 228 #define PPC_INST_MSGCLR 0x7c0001dc
6b3edefefa6752 Nicholas Piggin 2017-04-13 229 #define PPC_INST_MSGSYNC 0x7c0006ec
42d02b81f265b7 Ian Munsie 2012-11-14 230 #define PPC_INST_MSGSNDP 0x7c00011c
a9af97aa0a12c3 Nicholas Piggin 2017-06-13 231 #define PPC_INST_MSGCLRP 0x7c00015c
4bb3c7a0208fc1 Paul Mackerras 2018-03-21 232 #define PPC_INST_MTMSRD 0x7c000164
e16c8765533a15 Andy Fleming 2011-12-08 233 #define PPC_INST_MTTMR 0x7c0003dc
16c57b3620d77e Kumar Gala 2009-02-10 @234 #define PPC_INST_NOP 0x60000000
07d2a628bc0008 Nicholas Piggin 2017-06-09 235 #define PPC_INST_PASTE 0x7c20070d
16c57b3620d77e Kumar Gala 2009-02-10 236 #define PPC_INST_POPCNTB 0x7c0000f4
16c57b3620d77e Kumar Gala 2009-02-10 237 #define PPC_INST_POPCNTB_MASK 0xfc0007fe
b5f9b6665b70b4 Anton Blanchard 2010-12-07 238 #define PPC_INST_POPCNTD 0x7c0003f4
b5f9b6665b70b4 Anton Blanchard 2010-12-07 239 #define PPC_INST_POPCNTW 0x7c0002f4
4bb3c7a0208fc1 Paul Mackerras 2018-03-21 240 #define PPC_INST_RFEBB 0x4c000124
16c57b3620d77e Kumar Gala 2009-02-10 241 #define PPC_INST_RFCI 0x4c000066
16c57b3620d77e Kumar Gala 2009-02-10 242 #define PPC_INST_RFDI 0x4c00004e
4bb3c7a0208fc1 Paul Mackerras 2018-03-21 243 #define PPC_INST_RFID 0x4c000024
16c57b3620d77e Kumar Gala 2009-02-10 244 #define PPC_INST_RFMCI 0x4c00004c
cd99ddbea250ee Christophe Leroy 2018-01-12 245 #define PPC_INST_MFSPR 0x7c0002a6
efcac6589a277c Alexey Kardashevskiy 2011-03-02 246 #define PPC_INST_MFSPR_DSCR 0x7c1102a6
178f358208ceb8 Anton Blanchard 2017-01-19 247 #define PPC_INST_MFSPR_DSCR_MASK 0xfc1ffffe
efcac6589a277c Alexey Kardashevskiy 2011-03-02 248 #define PPC_INST_MTSPR_DSCR 0x7c1103a6
178f358208ceb8 Anton Blanchard 2017-01-19 249 #define PPC_INST_MTSPR_DSCR_MASK 0xfc1ffffe
73d2fb758e678c Anton Blanchard 2013-05-01 250 #define PPC_INST_MFSPR_DSCR_USER 0x7c0302a6
178f358208ceb8 Anton Blanchard 2017-01-19 251 #define PPC_INST_MFSPR_DSCR_USER_MASK 0xfc1ffffe
73d2fb758e678c Anton Blanchard 2013-05-01 252 #define PPC_INST_MTSPR_DSCR_USER 0x7c0303a6
178f358208ceb8 Anton Blanchard 2017-01-19 253 #define PPC_INST_MTSPR_DSCR_USER_MASK 0xfc1ffffe
6dd7a82cc54ebd Anton Blanchard 2016-07-01 254 #define PPC_INST_MFVSRD 0x7c000066
6dd7a82cc54ebd Anton Blanchard 2016-07-01 255 #define PPC_INST_MTVSRD 0x7c000166
d16952a629129c Christophe Leroy 2018-11-09 256 #define PPC_INST_SC 0x44000002
697d3899dcb4bc Paul Mackerras 2011-12-12 257 #define PPC_INST_SLBFEE 0x7c0007a7
09cf5bcb0c9355 Aneesh Kumar K.V 2016-07-13 258 #define PPC_INST_SLBIA 0x7c0003e4
16c57b3620d77e Kumar Gala 2009-02-10 259
:::::: The code at line 234 was first introduced by commit
:::::: 16c57b3620d77e0bc981da5ef32beae730512684 powerpc: Unify opcode definitions and support
:::::: TO: Kumar Gala <galak@kernel.crashing.org>
:::::: CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 6411 bytes --]
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 09/21] powerpc: Use a datatype for instructions
@ 2020-04-06 10:35 ` kbuild test robot
0 siblings, 0 replies; 71+ messages in thread
From: kbuild test robot @ 2020-04-06 10:35 UTC (permalink / raw)
To: kbuild-all
[-- Attachment #1: Type: text/plain, Size: 11193 bytes --]
Hi Jordan,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on v5.6]
[cannot apply to powerpc/next kvm-ppc/kvm-ppc-next scottwood/next next-20200406]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]
url: https://github.com/0day-ci/linux/commits/Jordan-Niethe/Initial-Prefixed-Instruction-support/20200406-165215
base: 7111951b8d4973bda27ff663f2cf18b663d15b48
config: powerpc-allnoconfig (attached as .config)
compiler: powerpc-linux-gcc (GCC) 9.3.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=9.3.0 make.cross ARCH=powerpc
If you fix the issue, kindly add following tag as appropriate
Reported-by: kbuild test robot <lkp@intel.com>
All error/warnings (new ones prefixed by >>):
In file included from arch/powerpc/include/asm/asm-compat.h:6,
from arch/powerpc/include/asm/bitops.h:42,
from include/linux/bitops.h:29,
from include/linux/kernel.h:12,
from include/linux/list.h:9,
from include/linux/module.h:12,
from arch/powerpc/kernel/setup_32.c:6:
arch/powerpc/kernel/setup_32.c: In function 'machine_init':
>> arch/powerpc/include/asm/ppc-opcode.h:234:24: error: incompatible type for argument 2 of 'patch_instruction_site'
234 | #define PPC_INST_NOP 0x60000000
| ^~~~~~~~~~
| |
| int
>> arch/powerpc/kernel/setup_32.c:89:49: note: in expansion of macro 'PPC_INST_NOP'
89 | patch_instruction_site(&patch__memcpy_nocache, PPC_INST_NOP);
| ^~~~~~~~~~~~
In file included from arch/powerpc/kernel/setup_32.c:42:
arch/powerpc/include/asm/code-patching.h:39:69: note: expected 'struct ppc_inst' but argument is of type 'int'
39 | static inline int patch_instruction_site(s32 *site, struct ppc_inst instr)
| ~~~~~~~~~~~~~~~~^~~~~
>> arch/powerpc/kernel/setup_32.c:91:48: error: passing argument 1 of 'branch_target' from incompatible pointer type [-Werror=incompatible-pointer-types]
91 | create_cond_branch(&insn, addr, branch_target(addr), 0x820000);
| ^~~~
| |
| unsigned int *
In file included from arch/powerpc/kernel/setup_32.c:42:
arch/powerpc/include/asm/code-patching.h:63:52: note: expected 'const struct ppc_inst *' but argument is of type 'unsigned int *'
63 | unsigned long branch_target(const struct ppc_inst *instr);
| ~~~~~~~~~~~~~~~~~~~~~~~^~~~~
arch/powerpc/kernel/setup_32.c:91:28: error: passing argument 2 of 'create_cond_branch' from incompatible pointer type [-Werror=incompatible-pointer-types]
91 | create_cond_branch(&insn, addr, branch_target(addr), 0x820000);
| ^~~~
| |
| unsigned int *
In file included from arch/powerpc/kernel/setup_32.c:42:
arch/powerpc/include/asm/code-patching.h:28:71: note: expected 'const struct ppc_inst *' but argument is of type 'unsigned int *'
28 | int create_cond_branch(struct ppc_inst *instr, const struct ppc_inst *addr,
| ~~~~~~~~~~~~~~~~~~~~~~~^~~~
>> arch/powerpc/kernel/setup_32.c:92:20: error: passing argument 1 of 'patch_instruction' from incompatible pointer type [-Werror=incompatible-pointer-types]
92 | patch_instruction(addr, insn); /* replace b by bne cr0 */
| ^~~~
| |
| unsigned int *
In file included from arch/powerpc/kernel/setup_32.c:42:
arch/powerpc/include/asm/code-patching.h:31:40: note: expected 'struct ppc_inst *' but argument is of type 'unsigned int *'
31 | int patch_instruction(struct ppc_inst *addr, struct ppc_inst instr);
| ~~~~~~~~~~~~~~~~~^~~~
cc1: all warnings being treated as errors
vim +/patch_instruction_site +234 arch/powerpc/include/asm/ppc-opcode.h
9123c5ed45a583 Hongtao Jia 2013-04-28 193
16c57b3620d77e Kumar Gala 2009-02-10 194 /* sorted alphabetically */
95213959aefc94 Anshuman Khandual 2013-04-22 195 #define PPC_INST_BHRBE 0x7c00025c
95213959aefc94 Anshuman Khandual 2013-04-22 196 #define PPC_INST_CLRBHRB 0x7c00035c
07d2a628bc0008 Nicholas Piggin 2017-06-09 197 #define PPC_INST_COPY 0x7c20060c
8a649045e75a4b Chris Smart 2016-04-26 198 #define PPC_INST_CP_ABORT 0x7c00068c
e66ca3db5917f4 Matt Brown 2017-08-04 199 #define PPC_INST_DARN 0x7c0005e6
16c57b3620d77e Kumar Gala 2009-02-10 200 #define PPC_INST_DCBA 0x7c0005ec
16c57b3620d77e Kumar Gala 2009-02-10 201 #define PPC_INST_DCBA_MASK 0xfc0007fe
16c57b3620d77e Kumar Gala 2009-02-10 202 #define PPC_INST_DCBAL 0x7c2005ec
16c57b3620d77e Kumar Gala 2009-02-10 203 #define PPC_INST_DCBZL 0x7c2007ec
1afc149def25ac Tony Breeds 2012-10-02 204 #define PPC_INST_ICBT 0x7c00002c
edc424f8cd84bb Dan Streetman 2015-05-07 205 #define PPC_INST_ICSWX 0x7c00032d
edc424f8cd84bb Dan Streetman 2015-05-07 206 #define PPC_INST_ICSWEPX 0x7c00076d
16c57b3620d77e Kumar Gala 2009-02-10 207 #define PPC_INST_ISEL 0x7c00001e
16c57b3620d77e Kumar Gala 2009-02-10 208 #define PPC_INST_ISEL_MASK 0xfc00003e
864b9e6fd76489 Anton Blanchard 2010-02-10 209 #define PPC_INST_LDARX 0x7c0000a8
156d0e290e969c Naveen N. Rao 2016-06-22 210 #define PPC_INST_STDCX 0x7c0001ad
350779a29f11f8 Paul Mackerras 2017-08-30 211 #define PPC_INST_LQARX 0x7c000228
350779a29f11f8 Paul Mackerras 2017-08-30 212 #define PPC_INST_STQCX 0x7c00016d
16c57b3620d77e Kumar Gala 2009-02-10 213 #define PPC_INST_LSWI 0x7c0004aa
16c57b3620d77e Kumar Gala 2009-02-10 214 #define PPC_INST_LSWX 0x7c00042a
d6ccb1f55ddf51 Kumar Gala 2010-03-10 215 #define PPC_INST_LWARX 0x7c000028
156d0e290e969c Naveen N. Rao 2016-06-22 216 #define PPC_INST_STWCX 0x7c00012d
16c57b3620d77e Kumar Gala 2009-02-10 217 #define PPC_INST_LWSYNC 0x7c2004ac
9863c28a2af90a James Yang 2013-07-03 218 #define PPC_INST_SYNC 0x7c0004ac
9863c28a2af90a James Yang 2013-07-03 219 #define PPC_INST_SYNC_MASK 0xfc0007fe
ddc6cd0d70a6f9 Christophe Leroy 2016-05-17 220 #define PPC_INST_ISYNC 0x4c00012c
dfb432cb960bfc Michael Neuling 2009-04-29 221 #define PPC_INST_LXVD2X 0x7c000698
16c57b3620d77e Kumar Gala 2009-02-10 222 #define PPC_INST_MCRXR 0x7c000400
16c57b3620d77e Kumar Gala 2009-02-10 223 #define PPC_INST_MCRXR_MASK 0xfc0007fe
16c57b3620d77e Kumar Gala 2009-02-10 224 #define PPC_INST_MFSPR_PVR 0x7c1f42a6
178f358208ceb8 Anton Blanchard 2017-01-19 225 #define PPC_INST_MFSPR_PVR_MASK 0xfc1ffffe
e16c8765533a15 Andy Fleming 2011-12-08 226 #define PPC_INST_MFTMR 0x7c0002dc
16c57b3620d77e Kumar Gala 2009-02-10 227 #define PPC_INST_MSGSND 0x7c00019c
755563bc79c764 Paul Mackerras 2015-03-19 228 #define PPC_INST_MSGCLR 0x7c0001dc
6b3edefefa6752 Nicholas Piggin 2017-04-13 229 #define PPC_INST_MSGSYNC 0x7c0006ec
42d02b81f265b7 Ian Munsie 2012-11-14 230 #define PPC_INST_MSGSNDP 0x7c00011c
a9af97aa0a12c3 Nicholas Piggin 2017-06-13 231 #define PPC_INST_MSGCLRP 0x7c00015c
4bb3c7a0208fc1 Paul Mackerras 2018-03-21 232 #define PPC_INST_MTMSRD 0x7c000164
e16c8765533a15 Andy Fleming 2011-12-08 233 #define PPC_INST_MTTMR 0x7c0003dc
16c57b3620d77e Kumar Gala 2009-02-10 @234 #define PPC_INST_NOP 0x60000000
07d2a628bc0008 Nicholas Piggin 2017-06-09 235 #define PPC_INST_PASTE 0x7c20070d
16c57b3620d77e Kumar Gala 2009-02-10 236 #define PPC_INST_POPCNTB 0x7c0000f4
16c57b3620d77e Kumar Gala 2009-02-10 237 #define PPC_INST_POPCNTB_MASK 0xfc0007fe
b5f9b6665b70b4 Anton Blanchard 2010-12-07 238 #define PPC_INST_POPCNTD 0x7c0003f4
b5f9b6665b70b4 Anton Blanchard 2010-12-07 239 #define PPC_INST_POPCNTW 0x7c0002f4
4bb3c7a0208fc1 Paul Mackerras 2018-03-21 240 #define PPC_INST_RFEBB 0x4c000124
16c57b3620d77e Kumar Gala 2009-02-10 241 #define PPC_INST_RFCI 0x4c000066
16c57b3620d77e Kumar Gala 2009-02-10 242 #define PPC_INST_RFDI 0x4c00004e
4bb3c7a0208fc1 Paul Mackerras 2018-03-21 243 #define PPC_INST_RFID 0x4c000024
16c57b3620d77e Kumar Gala 2009-02-10 244 #define PPC_INST_RFMCI 0x4c00004c
cd99ddbea250ee Christophe Leroy 2018-01-12 245 #define PPC_INST_MFSPR 0x7c0002a6
efcac6589a277c Alexey Kardashevskiy 2011-03-02 246 #define PPC_INST_MFSPR_DSCR 0x7c1102a6
178f358208ceb8 Anton Blanchard 2017-01-19 247 #define PPC_INST_MFSPR_DSCR_MASK 0xfc1ffffe
efcac6589a277c Alexey Kardashevskiy 2011-03-02 248 #define PPC_INST_MTSPR_DSCR 0x7c1103a6
178f358208ceb8 Anton Blanchard 2017-01-19 249 #define PPC_INST_MTSPR_DSCR_MASK 0xfc1ffffe
73d2fb758e678c Anton Blanchard 2013-05-01 250 #define PPC_INST_MFSPR_DSCR_USER 0x7c0302a6
178f358208ceb8 Anton Blanchard 2017-01-19 251 #define PPC_INST_MFSPR_DSCR_USER_MASK 0xfc1ffffe
73d2fb758e678c Anton Blanchard 2013-05-01 252 #define PPC_INST_MTSPR_DSCR_USER 0x7c0303a6
178f358208ceb8 Anton Blanchard 2017-01-19 253 #define PPC_INST_MTSPR_DSCR_USER_MASK 0xfc1ffffe
6dd7a82cc54ebd Anton Blanchard 2016-07-01 254 #define PPC_INST_MFVSRD 0x7c000066
6dd7a82cc54ebd Anton Blanchard 2016-07-01 255 #define PPC_INST_MTVSRD 0x7c000166
d16952a629129c Christophe Leroy 2018-11-09 256 #define PPC_INST_SC 0x44000002
697d3899dcb4bc Paul Mackerras 2011-12-12 257 #define PPC_INST_SLBFEE 0x7c0007a7
09cf5bcb0c9355 Aneesh Kumar K.V 2016-07-13 258 #define PPC_INST_SLBIA 0x7c0003e4
16c57b3620d77e Kumar Gala 2009-02-10 259
:::::: The code at line 234 was first introduced by commit
:::::: 16c57b3620d77e0bc981da5ef32beae730512684 powerpc: Unify opcode definitions and support
:::::: TO: Kumar Gala <galak@kernel.crashing.org>
:::::: CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org
[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 6411 bytes --]
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 18/21] powerpc64: Add prefixed instructions to instruction data type
2020-04-06 9:52 ` Alistair Popple
2020-04-06 10:25 ` Christophe Leroy
@ 2020-04-06 10:42 ` Jordan Niethe
2020-04-07 1:39 ` Alistair Popple
1 sibling, 1 reply; 71+ messages in thread
From: Jordan Niethe @ 2020-04-06 10:42 UTC (permalink / raw)
To: Alistair Popple; +Cc: npiggin, bala24, linuxppc-dev, dja
[-- Attachment #1: Type: text/plain, Size: 18341 bytes --]
On Mon, 6 Apr 2020, 7:52 pm Alistair Popple, <alistair@popple.id.au> wrote:
> > diff --git a/arch/powerpc/include/asm/inst.h
> > b/arch/powerpc/include/asm/inst.h index 70b37a35a91a..7e23e7146c66 100644
> > --- a/arch/powerpc/include/asm/inst.h
> > +++ b/arch/powerpc/include/asm/inst.h
> > @@ -8,23 +8,67 @@
> >
> > struct ppc_inst {
> > u32 val;
> > +#ifdef __powerpc64__
> > + u32 suffix;
> > +#endif /* __powerpc64__ */
> > } __packed;
> >
> > -#define ppc_inst(x) ((struct ppc_inst){ .val = x })
> > +static inline int ppc_inst_opcode(struct ppc_inst x)
> > +{
> > + return x.val >> 26;
> > +}
> >
> > static inline u32 ppc_inst_val(struct ppc_inst x)
> > {
> > return x.val;
> > }
> >
> > -static inline bool ppc_inst_len(struct ppc_inst x)
> > +#ifdef __powerpc64__
> > +#define ppc_inst(x) ((struct ppc_inst){ .val = (x), .suffix = 0xff })
> > +
> > +#define ppc_inst_prefix(x, y) ((struct ppc_inst){ .val = (x), .suffix =
> (y)
> > }) +
> > +static inline u32 ppc_inst_suffix(struct ppc_inst x)
> > {
> > - return sizeof(struct ppc_inst);
> > + return x.suffix;
> > }
> >
> > -static inline int ppc_inst_opcode(struct ppc_inst x)
> > +static inline bool ppc_inst_prefixed(struct ppc_inst x) {
> > + return ((ppc_inst_val(x) >> 26) == 1) && ppc_inst_suffix(x) !=
> 0xff;
> > +}
> > +
> > +static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
> > {
> > - return x.val >> 26;
> > + return ppc_inst_prefix(swab32(ppc_inst_val(x)),
> > + swab32(ppc_inst_suffix(x)));
> > +}
> > +
> > +static inline struct ppc_inst ppc_inst_read(const struct ppc_inst *ptr)
> > +{
> > + u32 val, suffix = 0xff;
> > + val = *(u32 *)ptr;
> > + if ((val >> 26) == 1)
> > + suffix = *((u32 *)ptr + 1);
> > + return ppc_inst_prefix(val, suffix);
> > +}
> > +
> > +static inline void ppc_inst_write(struct ppc_inst *ptr, struct ppc_inst
> x)
> > +{
> > + if (ppc_inst_prefixed(x)) {
> > + *(u32 *)ptr = x.val;
> > + *((u32 *)ptr + 1) = x.suffix;
> > + } else {
> > + *(u32 *)ptr = x.val;
> > + }
> > +}
> > +
> > +#else
> > +
> > +#define ppc_inst(x) ((struct ppc_inst){ .val = x })
> > +
> > +static inline bool ppc_inst_prefixed(ppc_inst x)
> > +{
> > + return 0;
> > }
> >
> > static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
> > @@ -32,14 +76,31 @@ static inline struct ppc_inst ppc_inst_swab(struct
> > ppc_inst x) return ppc_inst(swab32(ppc_inst_val(x)));
> > }
> >
> > +static inline u32 ppc_inst_val(struct ppc_inst x)
> > +{
> > + return x.val;
> > +}
> > +
> > static inline struct ppc_inst ppc_inst_read(const struct ppc_inst *ptr)
> > {
> > return *ptr;
> > }
> >
> > +static inline void ppc_inst_write(struct ppc_inst *ptr, struct ppc_inst
> x)
> > +{
> > + *ptr = x;
> > +}
> > +
> > +#endif /* __powerpc64__ */
> > +
> > static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
> > {
> > return !memcmp(&x, &y, sizeof(struct ppc_inst));
> > }
>
> Apologies for not picking this up earlier, I was hoping to get to the
> bottom
> of the issue I was seeing before you sent out v5. However the above
> definition
> of instruction equality does not seem correct because it does not consider
> the
> case when an instruction is not prefixed - a non-prefixed instruction
> should be
> considered equal if the first 32-bit opcode/value is the same. Something
> like:
>
> if (ppc_inst_prefixed(x) != ppc_inst_prefixed(y))
> return false;
> else if (ppc_inst_prefixed(x))
> return !memcmp(&x, &y, sizeof(struct ppc_inst));
> else
> return x.val == y.val;
>
> This was causing failures in ftrace_modify_code() as it would falsely
> detect
> two non-prefixed instructions as being not equal due to differences in the
> suffix.
>
Hm I was intending that non prefixed instructions would always have the
suffix set to the same value. If that's not happening, something must be
wrong with where the instructions are created.
>
> - Alistair
>
> > +static inline int ppc_inst_len(struct ppc_inst x)
> > +{
> > + return (ppc_inst_prefixed(x)) ? 8 : 4;
> > +}
> > +
> > #endif /* _ASM_INST_H */
> > diff --git a/arch/powerpc/include/asm/kprobes.h
> > b/arch/powerpc/include/asm/kprobes.h index 66b3f2983b22..4fc0e15e23a5
> > 100644
> > --- a/arch/powerpc/include/asm/kprobes.h
> > +++ b/arch/powerpc/include/asm/kprobes.h
> > @@ -43,7 +43,7 @@ extern kprobe_opcode_t optprobe_template_ret[];
> > extern kprobe_opcode_t optprobe_template_end[];
> >
> > /* Fixed instruction size for powerpc */
> > -#define MAX_INSN_SIZE 1
> > +#define MAX_INSN_SIZE 2
> > #define MAX_OPTIMIZED_LENGTH sizeof(kprobe_opcode_t) /* 4 bytes */
> > #define MAX_OPTINSN_SIZE (optprobe_template_end -
> optprobe_template_entry)
> > #define RELATIVEJUMP_SIZE sizeof(kprobe_opcode_t) /* 4 bytes */
> > diff --git a/arch/powerpc/include/asm/uaccess.h
> > b/arch/powerpc/include/asm/uaccess.h index c0a35e4586a5..5a3f486ddf02
> > 100644
> > --- a/arch/powerpc/include/asm/uaccess.h
> > +++ b/arch/powerpc/include/asm/uaccess.h
> > @@ -105,11 +105,34 @@ 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)))
> >
> > -#define __get_user_instr(x, ptr) \
> > - __get_user_nocheck((x).val, (u32 *)(ptr), sizeof(u32), true)
> > +#define __get_user_instr(x, ptr) \
> > +({ \
> > + long __gui_ret = 0; \
> > + unsigned int prefix, suffix; \
> > + __gui_ret = __get_user(prefix, (unsigned int __user *)ptr);
> \
> > + if (!__gui_ret && (prefix >> 26) == 1) { \
> > + __gui_ret = __get_user(suffix, (unsigned int __user *)ptr
> + 1); \
> > + (x) = ppc_inst_prefix(prefix, suffix); \
> > + } else { \
> > + (x) = ppc_inst(prefix); \
> > + } \
> > + __gui_ret; \
> > +})
> > +
> > +#define __get_user_instr_inatomic(x, ptr) \
> > +({ \
> > + long __gui_ret = 0; \
> > + unsigned int prefix, suffix; \
> > + __gui_ret = __get_user_inatomic(prefix, (unsigned int __user
> *)ptr); \
> > + if (!__gui_ret && (prefix >> 26) == 1) { \
> > + __gui_ret = __get_user_inatomic(suffix, (unsigned int
> __user *)ptr +
> > 1); \ + (x) = ppc_inst_prefix(prefix, suffix); \
> > + } else { \
> > + (x) = ppc_inst(prefix); \
> > + } \
> > + __gui_ret; \
> > +})
> >
> > -#define __get_user_instr_inatomic(x, ptr) \
> > - __get_user_nosleep((x).val, (u32 *)(ptr), sizeof(u32))
> > extern long __put_user_bad(void);
> >
> > /*
> > diff --git a/arch/powerpc/include/asm/uprobes.h
> > b/arch/powerpc/include/asm/uprobes.h index 7e3b329ba2d3..5bf65f5d44a9
> > 100644
> > --- a/arch/powerpc/include/asm/uprobes.h
> > +++ b/arch/powerpc/include/asm/uprobes.h
> > @@ -15,7 +15,7 @@
> >
> > typedef ppc_opcode_t uprobe_opcode_t;
> >
> > -#define MAX_UINSN_BYTES 4
> > +#define MAX_UINSN_BYTES 8
> > #define UPROBE_XOL_SLOT_BYTES (MAX_UINSN_BYTES)
> >
> > /* The following alias is needed for reference from arch-agnostic code
> */
> > diff --git a/arch/powerpc/kernel/optprobes.c
> > b/arch/powerpc/kernel/optprobes.c index 684640b8fa2e..689daf430161 100644
> > --- a/arch/powerpc/kernel/optprobes.c
> > +++ b/arch/powerpc/kernel/optprobes.c
> > @@ -159,38 +159,38 @@ void patch_imm32_load_insns(unsigned int val,
> > kprobe_opcode_t *addr)
> >
> > /*
> > * Generate instructions to load provided immediate 64-bit value
> > - * to register 'r3' and patch these instructions at 'addr'.
> > + * to register 'reg' and patch these instructions at 'addr'.
> > */
> > -void patch_imm64_load_insns(unsigned long val, kprobe_opcode_t *addr)
> > +void patch_imm64_load_insns(unsigned long val, int reg, kprobe_opcode_t
> > *addr) {
> > - /* lis r3,(op)@highest */
> > - patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ADDIS
> |
> > ___PPC_RT(3) | + /* lis reg,(op)@highest */
> > + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ADDIS
> |
> > ___PPC_RT(reg) | ((val >> 48) & 0xffff)));
> > addr++;
> >
> > - /* ori r3,r3,(op)@higher */
> > - patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI |
> > ___PPC_RA(3) | - ___PPC_RS(3) | ((val >> 32) &
> 0xffff)));
> > + /* ori reg,reg,(op)@higher */
> > + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI |
> > ___PPC_RA(reg) | + ___PPC_RS(reg) | ((val >> 32) &
> 0xffff)));
> > addr++;
> >
> > - /* rldicr r3,r3,32,31 */
> > - patch_instruction((struct ppc_inst *)addr,
> ppc_inst(PPC_INST_RLDICR |
> > ___PPC_RA(3) | - ___PPC_RS(3) | __PPC_SH64(32) |
> __PPC_ME64(31)));
> > + /* rldicr reg,reg,32,31 */
> > + patch_instruction((struct ppc_inst *)addr,
> ppc_inst(PPC_INST_RLDICR |
> > ___PPC_RA(reg) | + ___PPC_RS(reg) | __PPC_SH64(32)
> |
> __PPC_ME64(31)));
> > addr++;
> >
> > - /* oris r3,r3,(op)@h */
> > - patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORIS |
> > ___PPC_RA(3) | - ___PPC_RS(3) | ((val >> 16) &
> 0xffff)));
> > + /* oris reg,reg,(op)@h */
> > + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORIS |
> > ___PPC_RA(reg) | + ___PPC_RS(reg) | ((val >> 16) &
> 0xffff)));
> > addr++;
> >
> > - /* ori r3,r3,(op)@l */
> > - patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI |
> > ___PPC_RA(3) | - ___PPC_RS(3) | (val & 0xffff)));
> > + /* ori reg,reg,(op)@l */
> > + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI |
> > ___PPC_RA(reg) | + ___PPC_RS(reg) | (val &
> 0xffff)));
> > }
> >
> > int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct
> > kprobe *p) {
> > - struct ppc_inst branch_op_callback, branch_emulate_step;
> > + struct ppc_inst branch_op_callback, branch_emulate_step, temp;
> > kprobe_opcode_t *op_callback_addr, *emulate_step_addr, *buff;
> > long b_offset;
> > unsigned long nip, size;
> > @@ -240,7 +240,7 @@ int arch_prepare_optimized_kprobe(struct
> > optimized_kprobe *op, struct kprobe *p) * Fixup the template with
> > instructions to:
> > * 1. load the address of the actual probepoint
> > */
> > - patch_imm64_load_insns((unsigned long)op, buff + TMPL_OP_IDX);
> > + patch_imm64_load_insns((unsigned long)op, 3, buff + TMPL_OP_IDX);
> >
> > /*
> > * 2. branch to optimized_callback() and emulate_step()
> > @@ -271,7 +271,11 @@ int arch_prepare_optimized_kprobe(struct
> > optimized_kprobe *op, struct kprobe *p) /*
> > * 3. load instruction to be emulated into relevant register, and
> > */
> > - patch_imm32_load_insns(*p->ainsn.insn, buff + TMPL_INSN_IDX);
> > + 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);
> >
> > /*
> > * 4. branch back from trampoline
> > diff --git a/arch/powerpc/kernel/optprobes_head.S
> > b/arch/powerpc/kernel/optprobes_head.S index cf383520843f..ff8ba4d3824d
> > 100644
> > --- a/arch/powerpc/kernel/optprobes_head.S
> > +++ b/arch/powerpc/kernel/optprobes_head.S
> > @@ -94,6 +94,9 @@ optprobe_template_insn:
> > /* 2, Pass instruction to be emulated in r4 */
> > nop
> > nop
> > + nop
> > + nop
> > + nop
> >
> > .global optprobe_template_call_emulate
> > optprobe_template_call_emulate:
> > diff --git a/arch/powerpc/kernel/trace/ftrace.c
> > b/arch/powerpc/kernel/trace/ftrace.c index e78742613b36..16041a5c86d5
> > 100644
> > --- a/arch/powerpc/kernel/trace/ftrace.c
> > +++ b/arch/powerpc/kernel/trace/ftrace.c
> > @@ -41,11 +41,35 @@
> > #define NUM_FTRACE_TRAMPS 8
> > static unsigned long ftrace_tramps[NUM_FTRACE_TRAMPS];
> >
> > +#ifdef __powerpc64__
> > static long
> > probe_kernel_read_inst(struct ppc_inst *inst, const void *src)
> > {
> > - return probe_kernel_read((void *)inst, src, MCOUNT_INSN_SIZE);
> > + u32 val, suffix = 0;
> > + long err;
> > +
> > + err = probe_kernel_read((void *)&val,
> > + src, sizeof(val));
> > + if (err)
> > + return err;
> > +
> > + if ((val >> 26) == 1)
> > + err = probe_kernel_read((void *)&suffix,
> > + src + 4, MCOUNT_INSN_SIZE);
> > + if (err)
> > + return err;
> > +
> > + *inst = ppc_inst_prefix(val, suffix);
> > +
> > + return 0;
> > }
> > +#else
> > +static long
> > +probe_kernel_read_inst(struct ppc_inst *inst, const void *src)
> > +{
> > + return probe_kernel_read((void *)inst, src, MCOUNT_INSN_SIZE)
> > +}
> > +#endif
> >
> > static struct ppc_inst
> > ftrace_call_replace(unsigned long ip, unsigned long addr, int link)
> > diff --git a/arch/powerpc/lib/code-patching.c
> > b/arch/powerpc/lib/code-patching.c index c329ad657302..b4007e03d8fa
> 100644
> > --- a/arch/powerpc/lib/code-patching.c
> > +++ b/arch/powerpc/lib/code-patching.c
> > @@ -24,12 +24,19 @@ static int __patch_instruction(struct ppc_inst
> > *exec_addr, struct ppc_inst instr {
> > int err = 0;
> >
> > - __put_user_asm(ppc_inst_val(instr), patch_addr, err, "stw");
> > - if (err)
> > - return err;
> > -
> > - asm ("dcbst 0, %0; sync; icbi 0,%1; sync; isync" :: "r"
> (patch_addr),
> > - "r"
> (exec_addr));
> > + if (!ppc_inst_prefixed(instr)) {
> > + __put_user_asm(ppc_inst_val(instr), patch_addr, err,
> "stw");
> > + if (err)
> > + return err;
> > + asm ("dcbst 0, %0; sync; icbi 0,%1; sync; isync" :: "r"
> (patch_addr),
> > + "r"
> (exec_addr));
> > + } else {
> > + __put_user_asm((u64)ppc_inst_suffix(instr) << 32 |
> ppc_inst_val(instr),
> > patch_addr, err, "std"); + 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/feature-fixups.c
> > b/arch/powerpc/lib/feature-fixups.c index f00dd13b1c3c..5519cec83cc8
> 100644
> > --- a/arch/powerpc/lib/feature-fixups.c
> > +++ b/arch/powerpc/lib/feature-fixups.c
> > @@ -84,12 +84,13 @@ static int patch_feature_section(unsigned long value,
> > struct fixup_entry *fcur) src = alt_start;
> > dest = start;
> >
> > - for (; src < alt_end; src++, dest++) {
> > + for (; src < alt_end; src = (void *)src +
> > ppc_inst_len(ppc_inst_read(src)), + (dest = (void *)dest +
> > ppc_inst_len(ppc_inst_read(dest)))) { if (patch_alt_instruction(src,
> dest,
> > alt_start, alt_end))
> > return 1;
> > }
> >
> > - for (; dest < end; dest++)
> > + for (; dest < end; dest = (void *)dest +
> > ppc_inst_len(ppc_inst(PPC_INST_NOP))) raw_patch_instruction(dest,
> > ppc_inst(PPC_INST_NOP));
> >
> > return 0;
> > diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
> > index 52ddd3122dc8..8b285bf11218 100644
> > --- a/arch/powerpc/lib/sstep.c
> > +++ b/arch/powerpc/lib/sstep.c
> > @@ -1169,10 +1169,12 @@ int analyse_instr(struct instruction_op *op,
> const
> > struct pt_regs *regs, unsigned long int imm;
> > unsigned long int val, val2;
> > unsigned int mb, me, sh;
> > - unsigned int word;
> > + unsigned int word, suffix;
> > long ival;
> >
> > word = ppc_inst_val(instr);
> > + suffix = ppc_inst_suffix(instr);
> > +
> > op->type = COMPUTE;
> >
> > opcode = word >> 26;
> > diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
> > index 6f3bcdcfc9c7..b704aebb099a 100644
> > --- a/arch/powerpc/xmon/xmon.c
> > +++ b/arch/powerpc/xmon/xmon.c
> > @@ -761,8 +761,8 @@ static int xmon_bpt(struct pt_regs *regs)
> >
> > /* Are we at the trap at bp->instr[1] for some bp? */
> > bp = in_breakpoint_table(regs->nip, &offset);
> > - if (bp != NULL && offset == 4) {
> > - regs->nip = bp->address + 4;
> > + if (bp != NULL && (offset == 4 || offset == 8)) {
> > + regs->nip = bp->address + offset;
> > atomic_dec(&bp->ref_count);
> > return 1;
> > }
> > @@ -863,7 +863,7 @@ static struct bpt *in_breakpoint_table(unsigned long
> > nip, unsigned long *offp) if (off >= sizeof(bpt_table))
> > return NULL;
> > *offp = off % BPT_SIZE;
> > - if (*offp != 0 && *offp != 4)
> > + if (*offp != 0 && *offp != 4 && *offp != 8)
> > return NULL;
> > return bpts + (off / BPT_SIZE);
> > }
> > diff --git a/arch/powerpc/xmon/xmon_bpts.S
> b/arch/powerpc/xmon/xmon_bpts.S
> > index ebb2dbc70ca8..09058eb6abbd 100644
> > --- a/arch/powerpc/xmon/xmon_bpts.S
> > +++ b/arch/powerpc/xmon/xmon_bpts.S
> > @@ -3,6 +3,8 @@
> > #include <asm/asm-compat.h>
> > #include "xmon_bpts.h"
> >
> > +/* Prefixed instructions can not cross 64 byte boundaries */
> > +.align 6
> > .global bpt_table
> > bpt_table:
> > - .space NBPTS * 8
> > + .space NBPTS * 16
>
>
>
>
>
[-- Attachment #2: Type: text/html, Size: 23221 bytes --]
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 18/21] powerpc64: Add prefixed instructions to instruction data type
2020-04-06 8:09 ` [PATCH v5 18/21] powerpc64: Add prefixed instructions to instruction data type Jordan Niethe
@ 2020-04-06 11:04 ` kbuild test robot
2020-04-06 11:04 ` kbuild test robot
2020-04-13 12:04 ` Balamuruhan S
2 siblings, 0 replies; 71+ messages in thread
From: kbuild test robot @ 2020-04-06 11:04 UTC (permalink / raw)
To: Jordan Niethe
Cc: kbuild-all, Jordan Niethe, npiggin, bala24, alistair, linuxppc-dev, dja
[-- Attachment #1: Type: text/plain, Size: 14164 bytes --]
Hi Jordan,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on v5.6]
[cannot apply to powerpc/next kvm-ppc/kvm-ppc-next scottwood/next next-20200406]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]
url: https://github.com/0day-ci/linux/commits/Jordan-Niethe/Initial-Prefixed-Instruction-support/20200406-165215
base: 7111951b8d4973bda27ff663f2cf18b663d15b48
config: powerpc-allnoconfig (attached as .config)
compiler: powerpc-linux-gcc (GCC) 9.3.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=9.3.0 make.cross ARCH=powerpc
If you fix the issue, kindly add following tag as appropriate
Reported-by: kbuild test robot <lkp@intel.com>
All error/warnings (new ones prefixed by >>):
In file included from arch/powerpc/include/asm/sstep.h:5,
from arch/powerpc/kernel/align.c:26:
>> arch/powerpc/include/asm/inst.h:69:38: error: unknown type name 'ppc_inst'
69 | static inline bool ppc_inst_prefixed(ppc_inst x)
| ^~~~~~~~
>> arch/powerpc/include/asm/inst.h:79:19: error: redefinition of 'ppc_inst_val'
79 | static inline u32 ppc_inst_val(struct ppc_inst x)
| ^~~~~~~~~~~~
arch/powerpc/include/asm/inst.h:21:19: note: previous definition of 'ppc_inst_val' was here
21 | static inline u32 ppc_inst_val(struct ppc_inst x)
| ^~~~~~~~~~~~
arch/powerpc/include/asm/inst.h: In function 'ppc_inst_len':
>> arch/powerpc/include/asm/inst.h:103:10: error: implicit declaration of function 'ppc_inst_prefixed'; did you mean 'ppc_inst_write'? [-Werror=implicit-function-declaration]
103 | return (ppc_inst_prefixed(x)) ? 8 : 4;
| ^~~~~~~~~~~~~~~~~
| ppc_inst_write
In file included from include/linux/kernel.h:11,
from arch/powerpc/kernel/align.c:16:
arch/powerpc/kernel/align.c: In function 'fix_alignment':
>> arch/powerpc/include/asm/uaccess.h:115:9: error: implicit declaration of function 'ppc_inst_prefix'; did you mean 'ppc_inst_read'? [-Werror=implicit-function-declaration]
115 | (x) = ppc_inst_prefix(prefix, suffix); \
| ^~~~~~~~~~~~~~~
include/linux/compiler.h:78:42: note: in definition of macro 'unlikely'
78 | # define unlikely(x) __builtin_expect(!!(x), 0)
| ^
>> arch/powerpc/kernel/align.c:307:15: note: in expansion of macro '__get_user_instr'
307 | if (unlikely(__get_user_instr(instr, (void __user *)regs->nip)))
| ^~~~~~~~~~~~~~~~
>> arch/powerpc/include/asm/uaccess.h:115:9: error: incompatible types when assigning to type 'struct ppc_inst' from type 'int'
115 | (x) = ppc_inst_prefix(prefix, suffix); \
| ^~~~~~~~~~~~~~~
include/linux/compiler.h:78:42: note: in definition of macro 'unlikely'
78 | # define unlikely(x) __builtin_expect(!!(x), 0)
| ^
>> arch/powerpc/kernel/align.c:307:15: note: in expansion of macro '__get_user_instr'
307 | if (unlikely(__get_user_instr(instr, (void __user *)regs->nip)))
| ^~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
--
In file included from arch/powerpc/include/asm/code-patching.h:14,
from arch/powerpc/kernel/process.c:60:
>> arch/powerpc/include/asm/inst.h:69:38: error: unknown type name 'ppc_inst'
69 | static inline bool ppc_inst_prefixed(ppc_inst x)
| ^~~~~~~~
>> arch/powerpc/include/asm/inst.h:79:19: error: redefinition of 'ppc_inst_val'
79 | static inline u32 ppc_inst_val(struct ppc_inst x)
| ^~~~~~~~~~~~
arch/powerpc/include/asm/inst.h:21:19: note: previous definition of 'ppc_inst_val' was here
21 | static inline u32 ppc_inst_val(struct ppc_inst x)
| ^~~~~~~~~~~~
arch/powerpc/include/asm/inst.h: In function 'ppc_inst_len':
>> arch/powerpc/include/asm/inst.h:103:10: error: implicit declaration of function 'ppc_inst_prefixed'; did you mean 'ppc_inst_write'? [-Werror=implicit-function-declaration]
103 | return (ppc_inst_prefixed(x)) ? 8 : 4;
| ^~~~~~~~~~~~~~~~~
| ppc_inst_write
cc1: all warnings being treated as errors
--
In file included from arch/powerpc/include/asm/code-patching.h:14,
from arch/powerpc/kernel/setup_32.c:42:
>> arch/powerpc/include/asm/inst.h:69:38: error: unknown type name 'ppc_inst'
69 | static inline bool ppc_inst_prefixed(ppc_inst x)
| ^~~~~~~~
>> arch/powerpc/include/asm/inst.h:79:19: error: redefinition of 'ppc_inst_val'
79 | static inline u32 ppc_inst_val(struct ppc_inst x)
| ^~~~~~~~~~~~
arch/powerpc/include/asm/inst.h:21:19: note: previous definition of 'ppc_inst_val' was here
21 | static inline u32 ppc_inst_val(struct ppc_inst x)
| ^~~~~~~~~~~~
arch/powerpc/include/asm/inst.h: In function 'ppc_inst_len':
>> arch/powerpc/include/asm/inst.h:103:10: error: implicit declaration of function 'ppc_inst_prefixed'; did you mean 'ppc_inst_write'? [-Werror=implicit-function-declaration]
103 | return (ppc_inst_prefixed(x)) ? 8 : 4;
| ^~~~~~~~~~~~~~~~~
| ppc_inst_write
In file included from arch/powerpc/include/asm/asm-compat.h:6,
from arch/powerpc/include/asm/bitops.h:42,
from include/linux/bitops.h:29,
from include/linux/kernel.h:12,
from include/linux/list.h:9,
from include/linux/module.h:12,
from arch/powerpc/kernel/setup_32.c:6:
arch/powerpc/kernel/setup_32.c: In function 'machine_init':
arch/powerpc/include/asm/ppc-opcode.h:234:24: error: incompatible type for argument 2 of 'patch_instruction_site'
234 | #define PPC_INST_NOP 0x60000000
| ^~~~~~~~~~
| |
| int
arch/powerpc/kernel/setup_32.c:89:49: note: in expansion of macro 'PPC_INST_NOP'
89 | patch_instruction_site(&patch__memcpy_nocache, PPC_INST_NOP);
| ^~~~~~~~~~~~
In file included from arch/powerpc/kernel/setup_32.c:42:
arch/powerpc/include/asm/code-patching.h:39:69: note: expected 'struct ppc_inst' but argument is of type 'int'
39 | static inline int patch_instruction_site(s32 *site, struct ppc_inst instr)
| ~~~~~~~~~~~~~~~~^~~~~
arch/powerpc/kernel/setup_32.c:91:48: error: passing argument 1 of 'branch_target' from incompatible pointer type [-Werror=incompatible-pointer-types]
91 | create_cond_branch(&insn, addr, branch_target(addr), 0x820000);
| ^~~~
| |
| unsigned int *
In file included from arch/powerpc/kernel/setup_32.c:42:
arch/powerpc/include/asm/code-patching.h:63:52: note: expected 'const struct ppc_inst *' but argument is of type 'unsigned int *'
63 | unsigned long branch_target(const struct ppc_inst *instr);
| ~~~~~~~~~~~~~~~~~~~~~~~^~~~~
arch/powerpc/kernel/setup_32.c:91:28: error: passing argument 2 of 'create_cond_branch' from incompatible pointer type [-Werror=incompatible-pointer-types]
91 | create_cond_branch(&insn, addr, branch_target(addr), 0x820000);
| ^~~~
| |
| unsigned int *
In file included from arch/powerpc/kernel/setup_32.c:42:
arch/powerpc/include/asm/code-patching.h:28:71: note: expected 'const struct ppc_inst *' but argument is of type 'unsigned int *'
28 | int create_cond_branch(struct ppc_inst *instr, const struct ppc_inst *addr,
| ~~~~~~~~~~~~~~~~~~~~~~~^~~~
arch/powerpc/kernel/setup_32.c:92:20: error: passing argument 1 of 'patch_instruction' from incompatible pointer type [-Werror=incompatible-pointer-types]
92 | patch_instruction(addr, insn); /* replace b by bne cr0 */
| ^~~~
| |
| unsigned int *
In file included from arch/powerpc/kernel/setup_32.c:42:
arch/powerpc/include/asm/code-patching.h:31:40: note: expected 'struct ppc_inst *' but argument is of type 'unsigned int *'
31 | int patch_instruction(struct ppc_inst *addr, struct ppc_inst instr);
| ~~~~~~~~~~~~~~~~~^~~~
cc1: all warnings being treated as errors
--
In file included from arch/powerpc/include/asm/code-patching.h:14,
from arch/powerpc/include/asm/kprobes.h:24,
from include/linux/kprobes.h:30,
from arch/powerpc/lib/code-patching.c:7:
>> arch/powerpc/include/asm/inst.h:69:38: error: unknown type name 'ppc_inst'
69 | static inline bool ppc_inst_prefixed(ppc_inst x)
| ^~~~~~~~
>> arch/powerpc/include/asm/inst.h:79:19: error: redefinition of 'ppc_inst_val'
79 | static inline u32 ppc_inst_val(struct ppc_inst x)
| ^~~~~~~~~~~~
arch/powerpc/include/asm/inst.h:21:19: note: previous definition of 'ppc_inst_val' was here
21 | static inline u32 ppc_inst_val(struct ppc_inst x)
| ^~~~~~~~~~~~
arch/powerpc/include/asm/inst.h: In function 'ppc_inst_len':
>> arch/powerpc/include/asm/inst.h:103:10: error: implicit declaration of function 'ppc_inst_prefixed'; did you mean 'ppc_inst_write'? [-Werror=implicit-function-declaration]
103 | return (ppc_inst_prefixed(x)) ? 8 : 4;
| ^~~~~~~~~~~~~~~~~
| ppc_inst_write
In file included from include/linux/uaccess.h:11,
from arch/powerpc/include/asm/sections.h:7,
from include/linux/kallsyms.h:15,
from include/linux/ftrace.h:11,
from include/linux/kprobes.h:29,
from arch/powerpc/lib/code-patching.c:7:
arch/powerpc/lib/code-patching.c: In function '__patch_instruction':
>> arch/powerpc/lib/code-patching.c:34:23: error: implicit declaration of function 'ppc_inst_suffix'; did you mean 'ppc_inst_swab'? [-Werror=implicit-function-declaration]
34 | __put_user_asm((u64)ppc_inst_suffix(instr) << 32 | ppc_inst_val(instr), patch_addr, err, "std");
| ^~~~~~~~~~~~~~~
arch/powerpc/include/asm/uaccess.h:153:10: note: in definition of macro '__put_user_asm'
153 | : "r" (x), "b" (addr), "i" (-EFAULT), "0" (err))
| ^
cc1: all warnings being treated as errors
--
In file included from arch/powerpc/include/asm/code-patching.h:14,
from arch/powerpc/include/asm/kprobes.h:24,
from include/linux/kprobes.h:30,
from arch/powerpc/lib/sstep.c:8:
>> arch/powerpc/include/asm/inst.h:69:38: error: unknown type name 'ppc_inst'
69 | static inline bool ppc_inst_prefixed(ppc_inst x)
| ^~~~~~~~
>> arch/powerpc/include/asm/inst.h:79:19: error: redefinition of 'ppc_inst_val'
79 | static inline u32 ppc_inst_val(struct ppc_inst x)
| ^~~~~~~~~~~~
arch/powerpc/include/asm/inst.h:21:19: note: previous definition of 'ppc_inst_val' was here
21 | static inline u32 ppc_inst_val(struct ppc_inst x)
| ^~~~~~~~~~~~
arch/powerpc/include/asm/inst.h: In function 'ppc_inst_len':
>> arch/powerpc/include/asm/inst.h:103:10: error: implicit declaration of function 'ppc_inst_prefixed'; did you mean 'ppc_inst_write'? [-Werror=implicit-function-declaration]
103 | return (ppc_inst_prefixed(x)) ? 8 : 4;
| ^~~~~~~~~~~~~~~~~
| ppc_inst_write
arch/powerpc/lib/sstep.c: In function 'analyse_instr':
>> arch/powerpc/lib/sstep.c:1176:11: error: implicit declaration of function 'ppc_inst_suffix'; did you mean 'ppc_inst_swab'? [-Werror=implicit-function-declaration]
1176 | suffix = ppc_inst_suffix(instr);
| ^~~~~~~~~~~~~~~
| ppc_inst_swab
cc1: all warnings being treated as errors
vim +/ppc_inst +69 arch/powerpc/include/asm/inst.h
68
> 69 static inline bool ppc_inst_prefixed(ppc_inst x)
70 {
71 return 0;
72 }
73
74 static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
75 {
76 return ppc_inst(swab32(ppc_inst_val(x)));
77 }
78
> 79 static inline u32 ppc_inst_val(struct ppc_inst x)
80 {
81 return x.val;
82 }
83
84 static inline struct ppc_inst ppc_inst_read(const struct ppc_inst *ptr)
85 {
86 return *ptr;
87 }
88
89 static inline void ppc_inst_write(struct ppc_inst *ptr, struct ppc_inst x)
90 {
91 *ptr = x;
92 }
93
94 #endif /* __powerpc64__ */
95
96 static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
97 {
98 return !memcmp(&x, &y, sizeof(struct ppc_inst));
99 }
100
101 static inline int ppc_inst_len(struct ppc_inst x)
102 {
> 103 return (ppc_inst_prefixed(x)) ? 8 : 4;
104 }
105
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 6411 bytes --]
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 18/21] powerpc64: Add prefixed instructions to instruction data type
@ 2020-04-06 11:04 ` kbuild test robot
0 siblings, 0 replies; 71+ messages in thread
From: kbuild test robot @ 2020-04-06 11:04 UTC (permalink / raw)
To: kbuild-all
[-- Attachment #1: Type: text/plain, Size: 14415 bytes --]
Hi Jordan,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on v5.6]
[cannot apply to powerpc/next kvm-ppc/kvm-ppc-next scottwood/next next-20200406]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]
url: https://github.com/0day-ci/linux/commits/Jordan-Niethe/Initial-Prefixed-Instruction-support/20200406-165215
base: 7111951b8d4973bda27ff663f2cf18b663d15b48
config: powerpc-allnoconfig (attached as .config)
compiler: powerpc-linux-gcc (GCC) 9.3.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=9.3.0 make.cross ARCH=powerpc
If you fix the issue, kindly add following tag as appropriate
Reported-by: kbuild test robot <lkp@intel.com>
All error/warnings (new ones prefixed by >>):
In file included from arch/powerpc/include/asm/sstep.h:5,
from arch/powerpc/kernel/align.c:26:
>> arch/powerpc/include/asm/inst.h:69:38: error: unknown type name 'ppc_inst'
69 | static inline bool ppc_inst_prefixed(ppc_inst x)
| ^~~~~~~~
>> arch/powerpc/include/asm/inst.h:79:19: error: redefinition of 'ppc_inst_val'
79 | static inline u32 ppc_inst_val(struct ppc_inst x)
| ^~~~~~~~~~~~
arch/powerpc/include/asm/inst.h:21:19: note: previous definition of 'ppc_inst_val' was here
21 | static inline u32 ppc_inst_val(struct ppc_inst x)
| ^~~~~~~~~~~~
arch/powerpc/include/asm/inst.h: In function 'ppc_inst_len':
>> arch/powerpc/include/asm/inst.h:103:10: error: implicit declaration of function 'ppc_inst_prefixed'; did you mean 'ppc_inst_write'? [-Werror=implicit-function-declaration]
103 | return (ppc_inst_prefixed(x)) ? 8 : 4;
| ^~~~~~~~~~~~~~~~~
| ppc_inst_write
In file included from include/linux/kernel.h:11,
from arch/powerpc/kernel/align.c:16:
arch/powerpc/kernel/align.c: In function 'fix_alignment':
>> arch/powerpc/include/asm/uaccess.h:115:9: error: implicit declaration of function 'ppc_inst_prefix'; did you mean 'ppc_inst_read'? [-Werror=implicit-function-declaration]
115 | (x) = ppc_inst_prefix(prefix, suffix); \
| ^~~~~~~~~~~~~~~
include/linux/compiler.h:78:42: note: in definition of macro 'unlikely'
78 | # define unlikely(x) __builtin_expect(!!(x), 0)
| ^
>> arch/powerpc/kernel/align.c:307:15: note: in expansion of macro '__get_user_instr'
307 | if (unlikely(__get_user_instr(instr, (void __user *)regs->nip)))
| ^~~~~~~~~~~~~~~~
>> arch/powerpc/include/asm/uaccess.h:115:9: error: incompatible types when assigning to type 'struct ppc_inst' from type 'int'
115 | (x) = ppc_inst_prefix(prefix, suffix); \
| ^~~~~~~~~~~~~~~
include/linux/compiler.h:78:42: note: in definition of macro 'unlikely'
78 | # define unlikely(x) __builtin_expect(!!(x), 0)
| ^
>> arch/powerpc/kernel/align.c:307:15: note: in expansion of macro '__get_user_instr'
307 | if (unlikely(__get_user_instr(instr, (void __user *)regs->nip)))
| ^~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
--
In file included from arch/powerpc/include/asm/code-patching.h:14,
from arch/powerpc/kernel/process.c:60:
>> arch/powerpc/include/asm/inst.h:69:38: error: unknown type name 'ppc_inst'
69 | static inline bool ppc_inst_prefixed(ppc_inst x)
| ^~~~~~~~
>> arch/powerpc/include/asm/inst.h:79:19: error: redefinition of 'ppc_inst_val'
79 | static inline u32 ppc_inst_val(struct ppc_inst x)
| ^~~~~~~~~~~~
arch/powerpc/include/asm/inst.h:21:19: note: previous definition of 'ppc_inst_val' was here
21 | static inline u32 ppc_inst_val(struct ppc_inst x)
| ^~~~~~~~~~~~
arch/powerpc/include/asm/inst.h: In function 'ppc_inst_len':
>> arch/powerpc/include/asm/inst.h:103:10: error: implicit declaration of function 'ppc_inst_prefixed'; did you mean 'ppc_inst_write'? [-Werror=implicit-function-declaration]
103 | return (ppc_inst_prefixed(x)) ? 8 : 4;
| ^~~~~~~~~~~~~~~~~
| ppc_inst_write
cc1: all warnings being treated as errors
--
In file included from arch/powerpc/include/asm/code-patching.h:14,
from arch/powerpc/kernel/setup_32.c:42:
>> arch/powerpc/include/asm/inst.h:69:38: error: unknown type name 'ppc_inst'
69 | static inline bool ppc_inst_prefixed(ppc_inst x)
| ^~~~~~~~
>> arch/powerpc/include/asm/inst.h:79:19: error: redefinition of 'ppc_inst_val'
79 | static inline u32 ppc_inst_val(struct ppc_inst x)
| ^~~~~~~~~~~~
arch/powerpc/include/asm/inst.h:21:19: note: previous definition of 'ppc_inst_val' was here
21 | static inline u32 ppc_inst_val(struct ppc_inst x)
| ^~~~~~~~~~~~
arch/powerpc/include/asm/inst.h: In function 'ppc_inst_len':
>> arch/powerpc/include/asm/inst.h:103:10: error: implicit declaration of function 'ppc_inst_prefixed'; did you mean 'ppc_inst_write'? [-Werror=implicit-function-declaration]
103 | return (ppc_inst_prefixed(x)) ? 8 : 4;
| ^~~~~~~~~~~~~~~~~
| ppc_inst_write
In file included from arch/powerpc/include/asm/asm-compat.h:6,
from arch/powerpc/include/asm/bitops.h:42,
from include/linux/bitops.h:29,
from include/linux/kernel.h:12,
from include/linux/list.h:9,
from include/linux/module.h:12,
from arch/powerpc/kernel/setup_32.c:6:
arch/powerpc/kernel/setup_32.c: In function 'machine_init':
arch/powerpc/include/asm/ppc-opcode.h:234:24: error: incompatible type for argument 2 of 'patch_instruction_site'
234 | #define PPC_INST_NOP 0x60000000
| ^~~~~~~~~~
| |
| int
arch/powerpc/kernel/setup_32.c:89:49: note: in expansion of macro 'PPC_INST_NOP'
89 | patch_instruction_site(&patch__memcpy_nocache, PPC_INST_NOP);
| ^~~~~~~~~~~~
In file included from arch/powerpc/kernel/setup_32.c:42:
arch/powerpc/include/asm/code-patching.h:39:69: note: expected 'struct ppc_inst' but argument is of type 'int'
39 | static inline int patch_instruction_site(s32 *site, struct ppc_inst instr)
| ~~~~~~~~~~~~~~~~^~~~~
arch/powerpc/kernel/setup_32.c:91:48: error: passing argument 1 of 'branch_target' from incompatible pointer type [-Werror=incompatible-pointer-types]
91 | create_cond_branch(&insn, addr, branch_target(addr), 0x820000);
| ^~~~
| |
| unsigned int *
In file included from arch/powerpc/kernel/setup_32.c:42:
arch/powerpc/include/asm/code-patching.h:63:52: note: expected 'const struct ppc_inst *' but argument is of type 'unsigned int *'
63 | unsigned long branch_target(const struct ppc_inst *instr);
| ~~~~~~~~~~~~~~~~~~~~~~~^~~~~
arch/powerpc/kernel/setup_32.c:91:28: error: passing argument 2 of 'create_cond_branch' from incompatible pointer type [-Werror=incompatible-pointer-types]
91 | create_cond_branch(&insn, addr, branch_target(addr), 0x820000);
| ^~~~
| |
| unsigned int *
In file included from arch/powerpc/kernel/setup_32.c:42:
arch/powerpc/include/asm/code-patching.h:28:71: note: expected 'const struct ppc_inst *' but argument is of type 'unsigned int *'
28 | int create_cond_branch(struct ppc_inst *instr, const struct ppc_inst *addr,
| ~~~~~~~~~~~~~~~~~~~~~~~^~~~
arch/powerpc/kernel/setup_32.c:92:20: error: passing argument 1 of 'patch_instruction' from incompatible pointer type [-Werror=incompatible-pointer-types]
92 | patch_instruction(addr, insn); /* replace b by bne cr0 */
| ^~~~
| |
| unsigned int *
In file included from arch/powerpc/kernel/setup_32.c:42:
arch/powerpc/include/asm/code-patching.h:31:40: note: expected 'struct ppc_inst *' but argument is of type 'unsigned int *'
31 | int patch_instruction(struct ppc_inst *addr, struct ppc_inst instr);
| ~~~~~~~~~~~~~~~~~^~~~
cc1: all warnings being treated as errors
--
In file included from arch/powerpc/include/asm/code-patching.h:14,
from arch/powerpc/include/asm/kprobes.h:24,
from include/linux/kprobes.h:30,
from arch/powerpc/lib/code-patching.c:7:
>> arch/powerpc/include/asm/inst.h:69:38: error: unknown type name 'ppc_inst'
69 | static inline bool ppc_inst_prefixed(ppc_inst x)
| ^~~~~~~~
>> arch/powerpc/include/asm/inst.h:79:19: error: redefinition of 'ppc_inst_val'
79 | static inline u32 ppc_inst_val(struct ppc_inst x)
| ^~~~~~~~~~~~
arch/powerpc/include/asm/inst.h:21:19: note: previous definition of 'ppc_inst_val' was here
21 | static inline u32 ppc_inst_val(struct ppc_inst x)
| ^~~~~~~~~~~~
arch/powerpc/include/asm/inst.h: In function 'ppc_inst_len':
>> arch/powerpc/include/asm/inst.h:103:10: error: implicit declaration of function 'ppc_inst_prefixed'; did you mean 'ppc_inst_write'? [-Werror=implicit-function-declaration]
103 | return (ppc_inst_prefixed(x)) ? 8 : 4;
| ^~~~~~~~~~~~~~~~~
| ppc_inst_write
In file included from include/linux/uaccess.h:11,
from arch/powerpc/include/asm/sections.h:7,
from include/linux/kallsyms.h:15,
from include/linux/ftrace.h:11,
from include/linux/kprobes.h:29,
from arch/powerpc/lib/code-patching.c:7:
arch/powerpc/lib/code-patching.c: In function '__patch_instruction':
>> arch/powerpc/lib/code-patching.c:34:23: error: implicit declaration of function 'ppc_inst_suffix'; did you mean 'ppc_inst_swab'? [-Werror=implicit-function-declaration]
34 | __put_user_asm((u64)ppc_inst_suffix(instr) << 32 | ppc_inst_val(instr), patch_addr, err, "std");
| ^~~~~~~~~~~~~~~
arch/powerpc/include/asm/uaccess.h:153:10: note: in definition of macro '__put_user_asm'
153 | : "r" (x), "b" (addr), "i" (-EFAULT), "0" (err))
| ^
cc1: all warnings being treated as errors
--
In file included from arch/powerpc/include/asm/code-patching.h:14,
from arch/powerpc/include/asm/kprobes.h:24,
from include/linux/kprobes.h:30,
from arch/powerpc/lib/sstep.c:8:
>> arch/powerpc/include/asm/inst.h:69:38: error: unknown type name 'ppc_inst'
69 | static inline bool ppc_inst_prefixed(ppc_inst x)
| ^~~~~~~~
>> arch/powerpc/include/asm/inst.h:79:19: error: redefinition of 'ppc_inst_val'
79 | static inline u32 ppc_inst_val(struct ppc_inst x)
| ^~~~~~~~~~~~
arch/powerpc/include/asm/inst.h:21:19: note: previous definition of 'ppc_inst_val' was here
21 | static inline u32 ppc_inst_val(struct ppc_inst x)
| ^~~~~~~~~~~~
arch/powerpc/include/asm/inst.h: In function 'ppc_inst_len':
>> arch/powerpc/include/asm/inst.h:103:10: error: implicit declaration of function 'ppc_inst_prefixed'; did you mean 'ppc_inst_write'? [-Werror=implicit-function-declaration]
103 | return (ppc_inst_prefixed(x)) ? 8 : 4;
| ^~~~~~~~~~~~~~~~~
| ppc_inst_write
arch/powerpc/lib/sstep.c: In function 'analyse_instr':
>> arch/powerpc/lib/sstep.c:1176:11: error: implicit declaration of function 'ppc_inst_suffix'; did you mean 'ppc_inst_swab'? [-Werror=implicit-function-declaration]
1176 | suffix = ppc_inst_suffix(instr);
| ^~~~~~~~~~~~~~~
| ppc_inst_swab
cc1: all warnings being treated as errors
vim +/ppc_inst +69 arch/powerpc/include/asm/inst.h
68
> 69 static inline bool ppc_inst_prefixed(ppc_inst x)
70 {
71 return 0;
72 }
73
74 static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
75 {
76 return ppc_inst(swab32(ppc_inst_val(x)));
77 }
78
> 79 static inline u32 ppc_inst_val(struct ppc_inst x)
80 {
81 return x.val;
82 }
83
84 static inline struct ppc_inst ppc_inst_read(const struct ppc_inst *ptr)
85 {
86 return *ptr;
87 }
88
89 static inline void ppc_inst_write(struct ppc_inst *ptr, struct ppc_inst x)
90 {
91 *ptr = x;
92 }
93
94 #endif /* __powerpc64__ */
95
96 static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
97 {
98 return !memcmp(&x, &y, sizeof(struct ppc_inst));
99 }
100
101 static inline int ppc_inst_len(struct ppc_inst x)
102 {
> 103 return (ppc_inst_prefixed(x)) ? 8 : 4;
104 }
105
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org
[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 6411 bytes --]
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 18/21] powerpc64: Add prefixed instructions to instruction data type
2020-04-06 10:25 ` Christophe Leroy
@ 2020-04-06 11:13 ` Jordan Niethe
2020-04-08 18:11 ` Segher Boessenkool
1 sibling, 0 replies; 71+ messages in thread
From: Jordan Niethe @ 2020-04-06 11:13 UTC (permalink / raw)
To: Christophe Leroy
Cc: Alistair Popple, Nicholas Piggin, Balamuruhan S, linuxppc-dev,
Daniel Axtens
On Mon, Apr 6, 2020 at 8:25 PM Christophe Leroy <christophe.leroy@c-s.fr> wrote:
>
>
>
> Le 06/04/2020 à 11:52, Alistair Popple a écrit :
>
> [...]
>
> >> @@ -32,14 +76,31 @@ static inline struct ppc_inst ppc_inst_swab(struct
> >> ppc_inst x) return ppc_inst(swab32(ppc_inst_val(x)));
> >> }
> >>
> >> +static inline u32 ppc_inst_val(struct ppc_inst x)
> >> +{
> >> + return x.val;
> >> +}
> >> +
> >> static inline struct ppc_inst ppc_inst_read(const struct ppc_inst *ptr)
> >> {
> >> return *ptr;
> >> }
> >>
> >> +static inline void ppc_inst_write(struct ppc_inst *ptr, struct ppc_inst x)
> >> +{
> >> + *ptr = x;
> >> +}
> >> +
> >> +#endif /* __powerpc64__ */
> >> +
> >> static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
> >> {
> >> return !memcmp(&x, &y, sizeof(struct ppc_inst));
> >> }
> >
> > Apologies for not picking this up earlier, I was hoping to get to the bottom
> > of the issue I was seeing before you sent out v5. However the above definition
> > of instruction equality does not seem correct because it does not consider the
> > case when an instruction is not prefixed - a non-prefixed instruction should be
> > considered equal if the first 32-bit opcode/value is the same. Something like:
> >
> > if (ppc_inst_prefixed(x) != ppc_inst_prefixed(y))
> > return false;
> > else if (ppc_inst_prefixed(x))
> > return !memcmp(&x, &y, sizeof(struct ppc_inst));
>
> Are we sure memcmp() is a good candidate for the comparison ? Can we do
> simpler ? Especially, I understood a prefixed instruction is a 64 bits
> properly aligned instruction, can we do a simple u64 compare ? Or is GCC
> intelligent enough to do that without calling memcmp() function which is
> heavy ?
As it is GCC does call memcmp(). I'll try to make it simpler.
>
> > else
> > return x.val == y.val;
> >
> > This was causing failures in ftrace_modify_code() as it would falsely detect
> > two non-prefixed instructions as being not equal due to differences in the suffix.
> >
>
> Christophe
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 20/21] powerpc sstep: Add support for prefixed load/stores
2020-04-06 8:09 ` [PATCH v5 20/21] powerpc sstep: Add support for prefixed load/stores Jordan Niethe
@ 2020-04-06 11:29 ` kbuild test robot
0 siblings, 0 replies; 71+ messages in thread
From: kbuild test robot @ 2020-04-06 11:29 UTC (permalink / raw)
To: Jordan Niethe
Cc: kbuild-all, Jordan Niethe, npiggin, bala24, alistair, linuxppc-dev, dja
[-- Attachment #1: Type: text/plain, Size: 8286 bytes --]
Hi Jordan,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on v5.6]
[cannot apply to powerpc/next kvm-ppc/kvm-ppc-next scottwood/next next-20200406]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]
url: https://github.com/0day-ci/linux/commits/Jordan-Niethe/Initial-Prefixed-Instruction-support/20200406-165215
base: 7111951b8d4973bda27ff663f2cf18b663d15b48
config: powerpc-allnoconfig (attached as .config)
compiler: powerpc-linux-gcc (GCC) 9.3.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=9.3.0 make.cross ARCH=powerpc
If you fix the issue, kindly add following tag as appropriate
Reported-by: kbuild test robot <lkp@intel.com>
All errors (new ones prefixed by >>):
In file included from arch/powerpc/include/asm/code-patching.h:14,
from arch/powerpc/include/asm/kprobes.h:24,
from include/linux/kprobes.h:30,
from arch/powerpc/lib/sstep.c:8:
arch/powerpc/include/asm/inst.h:69:38: error: unknown type name 'ppc_inst'
69 | static inline bool ppc_inst_prefixed(ppc_inst x)
| ^~~~~~~~
arch/powerpc/include/asm/inst.h:79:19: error: redefinition of 'ppc_inst_val'
79 | static inline u32 ppc_inst_val(struct ppc_inst x)
| ^~~~~~~~~~~~
arch/powerpc/include/asm/inst.h:21:19: note: previous definition of 'ppc_inst_val' was here
21 | static inline u32 ppc_inst_val(struct ppc_inst x)
| ^~~~~~~~~~~~
arch/powerpc/include/asm/inst.h: In function 'ppc_inst_len':
arch/powerpc/include/asm/inst.h:103:10: error: implicit declaration of function 'ppc_inst_prefixed'; did you mean 'ppc_inst_write'? [-Werror=implicit-function-declaration]
103 | return (ppc_inst_prefixed(x)) ? 8 : 4;
| ^~~~~~~~~~~~~~~~~
| ppc_inst_write
arch/powerpc/lib/sstep.c: In function 'analyse_instr':
arch/powerpc/lib/sstep.c:1215:11: error: implicit declaration of function 'ppc_inst_suffix'; did you mean 'ppc_inst_swab'? [-Werror=implicit-function-declaration]
1215 | suffix = ppc_inst_suffix(instr);
| ^~~~~~~~~~~~~~~
| ppc_inst_swab
>> arch/powerpc/lib/sstep.c:1207:41: error: unused variable 'prefix_r' [-Werror=unused-variable]
1207 | unsigned int suffixopcode, prefixtype, prefix_r;
| ^~~~~~~~
>> arch/powerpc/lib/sstep.c:1207:29: error: unused variable 'prefixtype' [-Werror=unused-variable]
1207 | unsigned int suffixopcode, prefixtype, prefix_r;
| ^~~~~~~~~~
>> arch/powerpc/lib/sstep.c:1207:15: error: unused variable 'suffixopcode' [-Werror=unused-variable]
1207 | unsigned int suffixopcode, prefixtype, prefix_r;
| ^~~~~~~~~~~~
cc1: all warnings being treated as errors
vim +/prefix_r +1207 arch/powerpc/lib/sstep.c
1191
1192 /*
1193 * Decode an instruction, and return information about it in *op
1194 * without changing *regs.
1195 * Integer arithmetic and logical instructions, branches, and barrier
1196 * instructions can be emulated just using the information in *op.
1197 *
1198 * Return value is 1 if the instruction can be emulated just by
1199 * updating *regs with the information in *op, -1 if we need the
1200 * GPRs but *regs doesn't contain the full register set, or 0
1201 * otherwise.
1202 */
1203 int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
1204 struct ppc_inst instr)
1205 {
1206 unsigned int opcode, ra, rb, rc, rd, spr, u;
> 1207 unsigned int suffixopcode, prefixtype, prefix_r;
1208 unsigned long int imm;
1209 unsigned long int val, val2;
1210 unsigned int mb, me, sh;
1211 unsigned int word, suffix;
1212 long ival;
1213
1214 word = ppc_inst_val(instr);
1215 suffix = ppc_inst_suffix(instr);
1216
1217 op->type = COMPUTE;
1218
1219 opcode = word >> 26;
1220 switch (opcode) {
1221 case 16: /* bc */
1222 op->type = BRANCH;
1223 imm = (signed short)(word & 0xfffc);
1224 if ((word & 2) == 0)
1225 imm += regs->nip;
1226 op->val = truncate_if_32bit(regs->msr, imm);
1227 if (word & 1)
1228 op->type |= SETLK;
1229 if (branch_taken(word, regs, op))
1230 op->type |= BRTAKEN;
1231 return 1;
1232 #ifdef CONFIG_PPC64
1233 case 17: /* sc */
1234 if ((word & 0xfe2) == 2)
1235 op->type = SYSCALL;
1236 else
1237 op->type = UNKNOWN;
1238 return 0;
1239 #endif
1240 case 18: /* b */
1241 op->type = BRANCH | BRTAKEN;
1242 imm = word & 0x03fffffc;
1243 if (imm & 0x02000000)
1244 imm -= 0x04000000;
1245 if ((word & 2) == 0)
1246 imm += regs->nip;
1247 op->val = truncate_if_32bit(regs->msr, imm);
1248 if (word & 1)
1249 op->type |= SETLK;
1250 return 1;
1251 case 19:
1252 switch ((word >> 1) & 0x3ff) {
1253 case 0: /* mcrf */
1254 op->type = COMPUTE + SETCC;
1255 rd = 7 - ((word >> 23) & 0x7);
1256 ra = 7 - ((word >> 18) & 0x7);
1257 rd *= 4;
1258 ra *= 4;
1259 val = (regs->ccr >> ra) & 0xf;
1260 op->ccval = (regs->ccr & ~(0xfUL << rd)) | (val << rd);
1261 return 1;
1262
1263 case 16: /* bclr */
1264 case 528: /* bcctr */
1265 op->type = BRANCH;
1266 imm = (word & 0x400)? regs->ctr: regs->link;
1267 op->val = truncate_if_32bit(regs->msr, imm);
1268 if (word & 1)
1269 op->type |= SETLK;
1270 if (branch_taken(word, regs, op))
1271 op->type |= BRTAKEN;
1272 return 1;
1273
1274 case 18: /* rfid, scary */
1275 if (regs->msr & MSR_PR)
1276 goto priv;
1277 op->type = RFI;
1278 return 0;
1279
1280 case 150: /* isync */
1281 op->type = BARRIER | BARRIER_ISYNC;
1282 return 1;
1283
1284 case 33: /* crnor */
1285 case 129: /* crandc */
1286 case 193: /* crxor */
1287 case 225: /* crnand */
1288 case 257: /* crand */
1289 case 289: /* creqv */
1290 case 417: /* crorc */
1291 case 449: /* cror */
1292 op->type = COMPUTE + SETCC;
1293 ra = (word >> 16) & 0x1f;
1294 rb = (word >> 11) & 0x1f;
1295 rd = (word >> 21) & 0x1f;
1296 ra = (regs->ccr >> (31 - ra)) & 1;
1297 rb = (regs->ccr >> (31 - rb)) & 1;
1298 val = (word >> (6 + ra * 2 + rb)) & 1;
1299 op->ccval = (regs->ccr & ~(1UL << (31 - rd))) |
1300 (val << (31 - rd));
1301 return 1;
1302 }
1303 break;
1304 case 31:
1305 switch ((word >> 1) & 0x3ff) {
1306 case 598: /* sync */
1307 op->type = BARRIER + BARRIER_SYNC;
1308 #ifdef __powerpc64__
1309 switch ((word >> 21) & 3) {
1310 case 1: /* lwsync */
1311 op->type = BARRIER + BARRIER_LWSYNC;
1312 break;
1313 case 2: /* ptesync */
1314 op->type = BARRIER + BARRIER_PTESYNC;
1315 break;
1316 }
1317 #endif
1318 return 1;
1319
1320 case 854: /* eieio */
1321 op->type = BARRIER + BARRIER_EIEIO;
1322 return 1;
1323 }
1324 break;
1325 }
1326
1327 /* Following cases refer to regs->gpr[], so we need all regs */
1328 if (!FULL_REGS(regs))
1329 return -1;
1330
1331 rd = (word >> 21) & 0x1f;
1332 ra = (word >> 16) & 0x1f;
1333 rb = (word >> 11) & 0x1f;
1334 rc = (word >> 6) & 0x1f;
1335
1336 switch (opcode) {
1337 #ifdef __powerpc64__
1338 case 2: /* tdi */
1339 if (rd & trap_compare(regs->gpr[ra], (short) word))
1340 goto trap;
1341 return 1;
1342 #endif
1343 case 3: /* twi */
1344 if (rd & trap_compare((int)regs->gpr[ra], (short) word))
1345 goto trap;
1346 return 1;
1347
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 6411 bytes --]
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 20/21] powerpc sstep: Add support for prefixed load/stores
@ 2020-04-06 11:29 ` kbuild test robot
0 siblings, 0 replies; 71+ messages in thread
From: kbuild test robot @ 2020-04-06 11:29 UTC (permalink / raw)
To: kbuild-all
[-- Attachment #1: Type: text/plain, Size: 8510 bytes --]
Hi Jordan,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on v5.6]
[cannot apply to powerpc/next kvm-ppc/kvm-ppc-next scottwood/next next-20200406]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]
url: https://github.com/0day-ci/linux/commits/Jordan-Niethe/Initial-Prefixed-Instruction-support/20200406-165215
base: 7111951b8d4973bda27ff663f2cf18b663d15b48
config: powerpc-allnoconfig (attached as .config)
compiler: powerpc-linux-gcc (GCC) 9.3.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=9.3.0 make.cross ARCH=powerpc
If you fix the issue, kindly add following tag as appropriate
Reported-by: kbuild test robot <lkp@intel.com>
All errors (new ones prefixed by >>):
In file included from arch/powerpc/include/asm/code-patching.h:14,
from arch/powerpc/include/asm/kprobes.h:24,
from include/linux/kprobes.h:30,
from arch/powerpc/lib/sstep.c:8:
arch/powerpc/include/asm/inst.h:69:38: error: unknown type name 'ppc_inst'
69 | static inline bool ppc_inst_prefixed(ppc_inst x)
| ^~~~~~~~
arch/powerpc/include/asm/inst.h:79:19: error: redefinition of 'ppc_inst_val'
79 | static inline u32 ppc_inst_val(struct ppc_inst x)
| ^~~~~~~~~~~~
arch/powerpc/include/asm/inst.h:21:19: note: previous definition of 'ppc_inst_val' was here
21 | static inline u32 ppc_inst_val(struct ppc_inst x)
| ^~~~~~~~~~~~
arch/powerpc/include/asm/inst.h: In function 'ppc_inst_len':
arch/powerpc/include/asm/inst.h:103:10: error: implicit declaration of function 'ppc_inst_prefixed'; did you mean 'ppc_inst_write'? [-Werror=implicit-function-declaration]
103 | return (ppc_inst_prefixed(x)) ? 8 : 4;
| ^~~~~~~~~~~~~~~~~
| ppc_inst_write
arch/powerpc/lib/sstep.c: In function 'analyse_instr':
arch/powerpc/lib/sstep.c:1215:11: error: implicit declaration of function 'ppc_inst_suffix'; did you mean 'ppc_inst_swab'? [-Werror=implicit-function-declaration]
1215 | suffix = ppc_inst_suffix(instr);
| ^~~~~~~~~~~~~~~
| ppc_inst_swab
>> arch/powerpc/lib/sstep.c:1207:41: error: unused variable 'prefix_r' [-Werror=unused-variable]
1207 | unsigned int suffixopcode, prefixtype, prefix_r;
| ^~~~~~~~
>> arch/powerpc/lib/sstep.c:1207:29: error: unused variable 'prefixtype' [-Werror=unused-variable]
1207 | unsigned int suffixopcode, prefixtype, prefix_r;
| ^~~~~~~~~~
>> arch/powerpc/lib/sstep.c:1207:15: error: unused variable 'suffixopcode' [-Werror=unused-variable]
1207 | unsigned int suffixopcode, prefixtype, prefix_r;
| ^~~~~~~~~~~~
cc1: all warnings being treated as errors
vim +/prefix_r +1207 arch/powerpc/lib/sstep.c
1191
1192 /*
1193 * Decode an instruction, and return information about it in *op
1194 * without changing *regs.
1195 * Integer arithmetic and logical instructions, branches, and barrier
1196 * instructions can be emulated just using the information in *op.
1197 *
1198 * Return value is 1 if the instruction can be emulated just by
1199 * updating *regs with the information in *op, -1 if we need the
1200 * GPRs but *regs doesn't contain the full register set, or 0
1201 * otherwise.
1202 */
1203 int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
1204 struct ppc_inst instr)
1205 {
1206 unsigned int opcode, ra, rb, rc, rd, spr, u;
> 1207 unsigned int suffixopcode, prefixtype, prefix_r;
1208 unsigned long int imm;
1209 unsigned long int val, val2;
1210 unsigned int mb, me, sh;
1211 unsigned int word, suffix;
1212 long ival;
1213
1214 word = ppc_inst_val(instr);
1215 suffix = ppc_inst_suffix(instr);
1216
1217 op->type = COMPUTE;
1218
1219 opcode = word >> 26;
1220 switch (opcode) {
1221 case 16: /* bc */
1222 op->type = BRANCH;
1223 imm = (signed short)(word & 0xfffc);
1224 if ((word & 2) == 0)
1225 imm += regs->nip;
1226 op->val = truncate_if_32bit(regs->msr, imm);
1227 if (word & 1)
1228 op->type |= SETLK;
1229 if (branch_taken(word, regs, op))
1230 op->type |= BRTAKEN;
1231 return 1;
1232 #ifdef CONFIG_PPC64
1233 case 17: /* sc */
1234 if ((word & 0xfe2) == 2)
1235 op->type = SYSCALL;
1236 else
1237 op->type = UNKNOWN;
1238 return 0;
1239 #endif
1240 case 18: /* b */
1241 op->type = BRANCH | BRTAKEN;
1242 imm = word & 0x03fffffc;
1243 if (imm & 0x02000000)
1244 imm -= 0x04000000;
1245 if ((word & 2) == 0)
1246 imm += regs->nip;
1247 op->val = truncate_if_32bit(regs->msr, imm);
1248 if (word & 1)
1249 op->type |= SETLK;
1250 return 1;
1251 case 19:
1252 switch ((word >> 1) & 0x3ff) {
1253 case 0: /* mcrf */
1254 op->type = COMPUTE + SETCC;
1255 rd = 7 - ((word >> 23) & 0x7);
1256 ra = 7 - ((word >> 18) & 0x7);
1257 rd *= 4;
1258 ra *= 4;
1259 val = (regs->ccr >> ra) & 0xf;
1260 op->ccval = (regs->ccr & ~(0xfUL << rd)) | (val << rd);
1261 return 1;
1262
1263 case 16: /* bclr */
1264 case 528: /* bcctr */
1265 op->type = BRANCH;
1266 imm = (word & 0x400)? regs->ctr: regs->link;
1267 op->val = truncate_if_32bit(regs->msr, imm);
1268 if (word & 1)
1269 op->type |= SETLK;
1270 if (branch_taken(word, regs, op))
1271 op->type |= BRTAKEN;
1272 return 1;
1273
1274 case 18: /* rfid, scary */
1275 if (regs->msr & MSR_PR)
1276 goto priv;
1277 op->type = RFI;
1278 return 0;
1279
1280 case 150: /* isync */
1281 op->type = BARRIER | BARRIER_ISYNC;
1282 return 1;
1283
1284 case 33: /* crnor */
1285 case 129: /* crandc */
1286 case 193: /* crxor */
1287 case 225: /* crnand */
1288 case 257: /* crand */
1289 case 289: /* creqv */
1290 case 417: /* crorc */
1291 case 449: /* cror */
1292 op->type = COMPUTE + SETCC;
1293 ra = (word >> 16) & 0x1f;
1294 rb = (word >> 11) & 0x1f;
1295 rd = (word >> 21) & 0x1f;
1296 ra = (regs->ccr >> (31 - ra)) & 1;
1297 rb = (regs->ccr >> (31 - rb)) & 1;
1298 val = (word >> (6 + ra * 2 + rb)) & 1;
1299 op->ccval = (regs->ccr & ~(1UL << (31 - rd))) |
1300 (val << (31 - rd));
1301 return 1;
1302 }
1303 break;
1304 case 31:
1305 switch ((word >> 1) & 0x3ff) {
1306 case 598: /* sync */
1307 op->type = BARRIER + BARRIER_SYNC;
1308 #ifdef __powerpc64__
1309 switch ((word >> 21) & 3) {
1310 case 1: /* lwsync */
1311 op->type = BARRIER + BARRIER_LWSYNC;
1312 break;
1313 case 2: /* ptesync */
1314 op->type = BARRIER + BARRIER_PTESYNC;
1315 break;
1316 }
1317 #endif
1318 return 1;
1319
1320 case 854: /* eieio */
1321 op->type = BARRIER + BARRIER_EIEIO;
1322 return 1;
1323 }
1324 break;
1325 }
1326
1327 /* Following cases refer to regs->gpr[], so we need all regs */
1328 if (!FULL_REGS(regs))
1329 return -1;
1330
1331 rd = (word >> 21) & 0x1f;
1332 ra = (word >> 16) & 0x1f;
1333 rb = (word >> 11) & 0x1f;
1334 rc = (word >> 6) & 0x1f;
1335
1336 switch (opcode) {
1337 #ifdef __powerpc64__
1338 case 2: /* tdi */
1339 if (rd & trap_compare(regs->gpr[ra], (short) word))
1340 goto trap;
1341 return 1;
1342 #endif
1343 case 3: /* twi */
1344 if (rd & trap_compare((int)regs->gpr[ra], (short) word))
1345 goto trap;
1346 return 1;
1347
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org
[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 6411 bytes --]
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 18/21] powerpc64: Add prefixed instructions to instruction data type
2020-04-06 10:42 ` Jordan Niethe
@ 2020-04-07 1:39 ` Alistair Popple
0 siblings, 0 replies; 71+ messages in thread
From: Alistair Popple @ 2020-04-07 1:39 UTC (permalink / raw)
To: Jordan Niethe; +Cc: npiggin, bala24, linuxppc-dev, dja
On Monday, 6 April 2020 8:42:57 PM AEST Jordan Niethe wrote:
> On Mon, 6 Apr 2020, 7:52 pm Alistair Popple, <alistair@popple.id.au> wrote:
> > > diff --git a/arch/powerpc/include/asm/inst.h
> > > b/arch/powerpc/include/asm/inst.h index 70b37a35a91a..7e23e7146c66
> > > 100644
> > > --- a/arch/powerpc/include/asm/inst.h
> > > +++ b/arch/powerpc/include/asm/inst.h
> > > @@ -8,23 +8,67 @@
> > >
> > > struct ppc_inst {
> > >
> > > u32 val;
> > >
> > > +#ifdef __powerpc64__
> > > + u32 suffix;
> > > +#endif /* __powerpc64__ */
> > >
> > > } __packed;
> > >
> > > -#define ppc_inst(x) ((struct ppc_inst){ .val = x })
> > > +static inline int ppc_inst_opcode(struct ppc_inst x)
> > > +{
> > > + return x.val >> 26;
> > > +}
> > >
> > > static inline u32 ppc_inst_val(struct ppc_inst x)
> > > {
> > >
> > > return x.val;
> > >
> > > }
> > >
> > > -static inline bool ppc_inst_len(struct ppc_inst x)
> > > +#ifdef __powerpc64__
> > > +#define ppc_inst(x) ((struct ppc_inst){ .val = (x), .suffix = 0xff })
> > > +
> > > +#define ppc_inst_prefix(x, y) ((struct ppc_inst){ .val = (x), .suffix =
> >
> > (y)
> >
> > > }) +
> > > +static inline u32 ppc_inst_suffix(struct ppc_inst x)
> > >
> > > {
> > >
> > > - return sizeof(struct ppc_inst);
> > > + return x.suffix;
> > >
> > > }
> > >
> > > -static inline int ppc_inst_opcode(struct ppc_inst x)
> > > +static inline bool ppc_inst_prefixed(struct ppc_inst x) {
> > > + return ((ppc_inst_val(x) >> 26) == 1) && ppc_inst_suffix(x) !=
> >
> > 0xff;
> >
> > > +}
> > > +
> > > +static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
> > >
> > > {
> > >
> > > - return x.val >> 26;
> > > + return ppc_inst_prefix(swab32(ppc_inst_val(x)),
> > > + swab32(ppc_inst_suffix(x)));
> > > +}
> > > +
> > > +static inline struct ppc_inst ppc_inst_read(const struct ppc_inst *ptr)
> > > +{
> > > + u32 val, suffix = 0xff;
> > > + val = *(u32 *)ptr;
> > > + if ((val >> 26) == 1)
> > > + suffix = *((u32 *)ptr + 1);
> > > + return ppc_inst_prefix(val, suffix);
> > > +}
> > > +
> > > +static inline void ppc_inst_write(struct ppc_inst *ptr, struct ppc_inst
> >
> > x)
> >
> > > +{
> > > + if (ppc_inst_prefixed(x)) {
> > > + *(u32 *)ptr = x.val;
> > > + *((u32 *)ptr + 1) = x.suffix;
> > > + } else {
> > > + *(u32 *)ptr = x.val;
> > > + }
> > > +}
> > > +
> > > +#else
> > > +
> > > +#define ppc_inst(x) ((struct ppc_inst){ .val = x })
> > > +
> > > +static inline bool ppc_inst_prefixed(ppc_inst x)
> > > +{
> > > + return 0;
> > >
> > > }
> > >
> > > static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
> > >
> > > @@ -32,14 +76,31 @@ static inline struct ppc_inst ppc_inst_swab(struct
> > > ppc_inst x) return ppc_inst(swab32(ppc_inst_val(x)));
> > >
> > > }
> > >
> > > +static inline u32 ppc_inst_val(struct ppc_inst x)
> > > +{
> > > + return x.val;
> > > +}
> > > +
> > >
> > > static inline struct ppc_inst ppc_inst_read(const struct ppc_inst *ptr)
> > > {
> > >
> > > return *ptr;
> > >
> > > }
> > >
> > > +static inline void ppc_inst_write(struct ppc_inst *ptr, struct ppc_inst
> >
> > x)
> >
> > > +{
> > > + *ptr = x;
> > > +}
> > > +
> > > +#endif /* __powerpc64__ */
> > > +
> > >
> > > static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
> > > {
> > >
> > > return !memcmp(&x, &y, sizeof(struct ppc_inst));
> > >
> > > }
> >
> > Apologies for not picking this up earlier, I was hoping to get to the
> > bottom
> > of the issue I was seeing before you sent out v5. However the above
> > definition
> > of instruction equality does not seem correct because it does not consider
> > the
> > case when an instruction is not prefixed - a non-prefixed instruction
> > should be
> > considered equal if the first 32-bit opcode/value is the same. Something
> >
> > like:
> > if (ppc_inst_prefixed(x) != ppc_inst_prefixed(y))
> >
> > return false;
> >
> > else if (ppc_inst_prefixed(x))
> >
> > return !memcmp(&x, &y, sizeof(struct ppc_inst));
> >
> > else
> >
> > return x.val == y.val;
> >
> > This was causing failures in ftrace_modify_code() as it would falsely
> > detect
> > two non-prefixed instructions as being not equal due to differences in the
> > suffix.
>
> Hm I was intending that non prefixed instructions would always have the
> suffix set to the same value. If that's not happening, something must be
> wrong with where the instructions are created.
>
Ok, based on your comment I found the problem. Your last patch series defined
read_inst() in ftrace.c and ended that function with:
ppc_inst_write(p, inst);
return 0;
This is called from ftrace_modify_code(), where p is uninitialised. In the
last series ppc_inst_write() function would only write/initialise the suffix if
it was a prefixed instruction, hence leaving it uninitialised in this instance
which lead to the problems checking equality.
I suspect read_instr() should have finished with this instead:
*p = inst;
return 0;
However your new patch series replaces it with probe_kernel_read_inst() which
looks to do the right thing:
+ *inst = ppc_inst_prefix(val, suffix);
+
+ return 0;
As the suffix in *inst will always get written now, so my previous comment
appears invalid.
- Alistair
> > - Alistair
> >
> > > +static inline int ppc_inst_len(struct ppc_inst x)
> > > +{
> > > + return (ppc_inst_prefixed(x)) ? 8 : 4;
> > > +}
> > > +
> > >
> > > #endif /* _ASM_INST_H */
> > >
> > > diff --git a/arch/powerpc/include/asm/kprobes.h
> > > b/arch/powerpc/include/asm/kprobes.h index 66b3f2983b22..4fc0e15e23a5
> > > 100644
> > > --- a/arch/powerpc/include/asm/kprobes.h
> > > +++ b/arch/powerpc/include/asm/kprobes.h
> > > @@ -43,7 +43,7 @@ extern kprobe_opcode_t optprobe_template_ret[];
> > >
> > > extern kprobe_opcode_t optprobe_template_end[];
> > >
> > > /* Fixed instruction size for powerpc */
> > >
> > > -#define MAX_INSN_SIZE 1
> > > +#define MAX_INSN_SIZE 2
> > >
> > > #define MAX_OPTIMIZED_LENGTH sizeof(kprobe_opcode_t) /* 4 bytes */
> > > #define MAX_OPTINSN_SIZE (optprobe_template_end -
> >
> > optprobe_template_entry)
> >
> > > #define RELATIVEJUMP_SIZE sizeof(kprobe_opcode_t) /* 4 bytes */
> > >
> > > diff --git a/arch/powerpc/include/asm/uaccess.h
> > > b/arch/powerpc/include/asm/uaccess.h index c0a35e4586a5..5a3f486ddf02
> > > 100644
> > > --- a/arch/powerpc/include/asm/uaccess.h
> > > +++ b/arch/powerpc/include/asm/uaccess.h
> > > @@ -105,11 +105,34 @@ 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)))
> > >
> > > -#define __get_user_instr(x, ptr) \
> > > - __get_user_nocheck((x).val, (u32 *)(ptr), sizeof(u32), true)
> > > +#define __get_user_instr(x, ptr) \
> > > +({ \
> > > + long __gui_ret = 0; \
> > > + unsigned int prefix, suffix; \
> > > + __gui_ret = __get_user(prefix, (unsigned int __user *)ptr);
> > >
> > \
> > >
> > > + if (!__gui_ret && (prefix >> 26) == 1) { \
> > > + __gui_ret = __get_user(suffix, (unsigned int __user *)ptr
> >
> > + 1); \
> >
> > > + (x) = ppc_inst_prefix(prefix, suffix); \
> > > + } else { \
> > > + (x) = ppc_inst(prefix); \
> > > + } \
> > > + __gui_ret; \
> > > +})
> > > +
> > > +#define __get_user_instr_inatomic(x, ptr) \
> > > +({ \
> > > + long __gui_ret = 0; \
> > > + unsigned int prefix, suffix; \
> > > + __gui_ret = __get_user_inatomic(prefix, (unsigned int __user
> >
> > *)ptr); \
> >
> > > + if (!__gui_ret && (prefix >> 26) == 1) { \
> > > + __gui_ret = __get_user_inatomic(suffix, (unsigned int
> >
> > __user *)ptr +
> >
> > > 1); \ + (x) = ppc_inst_prefix(prefix, suffix); \
> > > + } else { \
> > > + (x) = ppc_inst(prefix); \
> > > + } \
> > > + __gui_ret; \
> > > +})
> > >
> > > -#define __get_user_instr_inatomic(x, ptr) \
> > > - __get_user_nosleep((x).val, (u32 *)(ptr), sizeof(u32))
> > >
> > > extern long __put_user_bad(void);
> > >
> > > /*
> > >
> > > diff --git a/arch/powerpc/include/asm/uprobes.h
> > > b/arch/powerpc/include/asm/uprobes.h index 7e3b329ba2d3..5bf65f5d44a9
> > > 100644
> > > --- a/arch/powerpc/include/asm/uprobes.h
> > > +++ b/arch/powerpc/include/asm/uprobes.h
> > > @@ -15,7 +15,7 @@
> > >
> > > typedef ppc_opcode_t uprobe_opcode_t;
> > >
> > > -#define MAX_UINSN_BYTES 4
> > > +#define MAX_UINSN_BYTES 8
> > >
> > > #define UPROBE_XOL_SLOT_BYTES (MAX_UINSN_BYTES)
> > >
> > > /* The following alias is needed for reference from arch-agnostic code
> >
> > */
> >
> > > diff --git a/arch/powerpc/kernel/optprobes.c
> > > b/arch/powerpc/kernel/optprobes.c index 684640b8fa2e..689daf430161
> > > 100644
> > > --- a/arch/powerpc/kernel/optprobes.c
> > > +++ b/arch/powerpc/kernel/optprobes.c
> > > @@ -159,38 +159,38 @@ void patch_imm32_load_insns(unsigned int val,
> > > kprobe_opcode_t *addr)
> > >
> > > /*
> > >
> > > * Generate instructions to load provided immediate 64-bit value
> > >
> > > - * to register 'r3' and patch these instructions at 'addr'.
> > > + * to register 'reg' and patch these instructions at 'addr'.
> > >
> > > */
> > >
> > > -void patch_imm64_load_insns(unsigned long val, kprobe_opcode_t *addr)
> > > +void patch_imm64_load_insns(unsigned long val, int reg, kprobe_opcode_t
> > > *addr) {
> > > - /* lis r3,(op)@highest */
> > > - patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ADDIS
> > >
> > > ___PPC_RT(3) | + /* lis reg,(op)@highest */
> > > + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ADDIS
> > >
> > > ___PPC_RT(reg) | ((val >> 48) & 0xffff)));
> > >
> > > addr++;
> > >
> > > - /* ori r3,r3,(op)@higher */
> > > - patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI |
> > > ___PPC_RA(3) | - ___PPC_RS(3) | ((val >> 32) &
> >
> > 0xffff)));
> >
> > > + /* ori reg,reg,(op)@higher */
> > > + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI |
> > > ___PPC_RA(reg) | + ___PPC_RS(reg) | ((val >> 32) &
> >
> > 0xffff)));
> >
> > > addr++;
> > >
> > > - /* rldicr r3,r3,32,31 */
> > > - patch_instruction((struct ppc_inst *)addr,
> >
> > ppc_inst(PPC_INST_RLDICR |
> >
> > > ___PPC_RA(3) | - ___PPC_RS(3) | __PPC_SH64(32) |
> >
> > __PPC_ME64(31)));
> >
> > > + /* rldicr reg,reg,32,31 */
> > > + patch_instruction((struct ppc_inst *)addr,
> >
> > ppc_inst(PPC_INST_RLDICR |
> >
> > > ___PPC_RA(reg) | + ___PPC_RS(reg) | __PPC_SH64(32)
> >
> > __PPC_ME64(31)));
> >
> > > addr++;
> > >
> > > - /* oris r3,r3,(op)@h */
> > > - patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORIS
> > > |
> > > ___PPC_RA(3) | - ___PPC_RS(3) | ((val >> 16) &
> >
> > 0xffff)));
> >
> > > + /* oris reg,reg,(op)@h */
> > > + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORIS
> > > |
> > > ___PPC_RA(reg) | + ___PPC_RS(reg) | ((val >> 16) &
> >
> > 0xffff)));
> >
> > > addr++;
> > >
> > > - /* ori r3,r3,(op)@l */
> > > - patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI |
> > > ___PPC_RA(3) | - ___PPC_RS(3) | (val & 0xffff)));
> > > + /* ori reg,reg,(op)@l */
> > > + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI |
> > > ___PPC_RA(reg) | + ___PPC_RS(reg) | (val &
> >
> > 0xffff)));
> >
> > > }
> > >
> > > int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct
> > >
> > > kprobe *p) {
> > > - struct ppc_inst branch_op_callback, branch_emulate_step;
> > > + struct ppc_inst branch_op_callback, branch_emulate_step, temp;
> > >
> > > kprobe_opcode_t *op_callback_addr, *emulate_step_addr, *buff;
> > > long b_offset;
> > > unsigned long nip, size;
> > >
> > > @@ -240,7 +240,7 @@ int arch_prepare_optimized_kprobe(struct
> > > optimized_kprobe *op, struct kprobe *p) * Fixup the template with
> > >
> > > instructions to:
> > > * 1. load the address of the actual probepoint
> > > */
> > >
> > > - patch_imm64_load_insns((unsigned long)op, buff + TMPL_OP_IDX);
> > > + patch_imm64_load_insns((unsigned long)op, 3, buff + TMPL_OP_IDX);
> > >
> > > /*
> > >
> > > * 2. branch to optimized_callback() and emulate_step()
> > >
> > > @@ -271,7 +271,11 @@ int arch_prepare_optimized_kprobe(struct
> > > optimized_kprobe *op, struct kprobe *p) /*
> > >
> > > * 3. load instruction to be emulated into relevant register, and
> > > */
> > >
> > > - patch_imm32_load_insns(*p->ainsn.insn, buff + TMPL_INSN_IDX);
> > > + 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);
> > >
> > > /*
> > >
> > > * 4. branch back from trampoline
> > >
> > > diff --git a/arch/powerpc/kernel/optprobes_head.S
> > > b/arch/powerpc/kernel/optprobes_head.S index cf383520843f..ff8ba4d3824d
> > > 100644
> > > --- a/arch/powerpc/kernel/optprobes_head.S
> > > +++ b/arch/powerpc/kernel/optprobes_head.S
> > >
> > > @@ -94,6 +94,9 @@ optprobe_template_insn:
> > > /* 2, Pass instruction to be emulated in r4 */
> > > nop
> > > nop
> > >
> > > + nop
> > > + nop
> > > + nop
> > >
> > > .global optprobe_template_call_emulate
> > >
> > > optprobe_template_call_emulate:
> > > diff --git a/arch/powerpc/kernel/trace/ftrace.c
> > > b/arch/powerpc/kernel/trace/ftrace.c index e78742613b36..16041a5c86d5
> > > 100644
> > > --- a/arch/powerpc/kernel/trace/ftrace.c
> > > +++ b/arch/powerpc/kernel/trace/ftrace.c
> > > @@ -41,11 +41,35 @@
> > >
> > > #define NUM_FTRACE_TRAMPS 8
> > > static unsigned long ftrace_tramps[NUM_FTRACE_TRAMPS];
> > >
> > > +#ifdef __powerpc64__
> > >
> > > static long
> > > probe_kernel_read_inst(struct ppc_inst *inst, const void *src)
> > > {
> > >
> > > - return probe_kernel_read((void *)inst, src, MCOUNT_INSN_SIZE);
> > > + u32 val, suffix = 0;
> > > + long err;
> > > +
> > > + err = probe_kernel_read((void *)&val,
> > > + src, sizeof(val));
> > > + if (err)
> > > + return err;
> > > +
> > > + if ((val >> 26) == 1)
> > > + err = probe_kernel_read((void *)&suffix,
> > > + src + 4, MCOUNT_INSN_SIZE);
> > > + if (err)
> > > + return err;
> > > +
> > > + *inst = ppc_inst_prefix(val, suffix);
> > > +
> > > + return 0;
> > >
> > > }
> > >
> > > +#else
> > > +static long
> > > +probe_kernel_read_inst(struct ppc_inst *inst, const void *src)
> > > +{
> > > + return probe_kernel_read((void *)inst, src, MCOUNT_INSN_SIZE)
> > > +}
> > > +#endif
> > >
> > > static struct ppc_inst
> > > ftrace_call_replace(unsigned long ip, unsigned long addr, int link)
> > >
> > > diff --git a/arch/powerpc/lib/code-patching.c
> > > b/arch/powerpc/lib/code-patching.c index c329ad657302..b4007e03d8fa
> >
> > 100644
> >
> > > --- a/arch/powerpc/lib/code-patching.c
> > > +++ b/arch/powerpc/lib/code-patching.c
> > > @@ -24,12 +24,19 @@ static int __patch_instruction(struct ppc_inst
> > > *exec_addr, struct ppc_inst instr {
> > >
> > > int err = 0;
> > >
> > > - __put_user_asm(ppc_inst_val(instr), patch_addr, err, "stw");
> > > - if (err)
> > > - return err;
> > > -
> > > - asm ("dcbst 0, %0; sync; icbi 0,%1; sync; isync" :: "r"
> >
> > (patch_addr),
> >
> > > - "r"
> >
> > (exec_addr));
> >
> > > + if (!ppc_inst_prefixed(instr)) {
> > > + __put_user_asm(ppc_inst_val(instr), patch_addr, err,
> >
> > "stw");
> >
> > > + if (err)
> > > + return err;
> > > + asm ("dcbst 0, %0; sync; icbi 0,%1; sync; isync" :: "r"
> >
> > (patch_addr),
> >
> > > + "r"
> >
> > (exec_addr));
> >
> > > + } else {
> > > + __put_user_asm((u64)ppc_inst_suffix(instr) << 32 |
> >
> > ppc_inst_val(instr),
> >
> > > patch_addr, err, "std"); + 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/feature-fixups.c
> > > b/arch/powerpc/lib/feature-fixups.c index f00dd13b1c3c..5519cec83cc8
> >
> > 100644
> >
> > > --- a/arch/powerpc/lib/feature-fixups.c
> > > +++ b/arch/powerpc/lib/feature-fixups.c
> > > @@ -84,12 +84,13 @@ static int patch_feature_section(unsigned long
> > > value,
> > > struct fixup_entry *fcur) src = alt_start;
> > >
> > > dest = start;
> > >
> > > - for (; src < alt_end; src++, dest++) {
> > > + for (; src < alt_end; src = (void *)src +
> > > ppc_inst_len(ppc_inst_read(src)), + (dest = (void *)dest +
> > > ppc_inst_len(ppc_inst_read(dest)))) { if (patch_alt_instruction(src,
> >
> > dest,
> >
> > > alt_start, alt_end))
> > >
> > > return 1;
> > >
> > > }
> > >
> > > - for (; dest < end; dest++)
> > > + for (; dest < end; dest = (void *)dest +
> > > ppc_inst_len(ppc_inst(PPC_INST_NOP))) raw_patch_instruction(dest,
> > > ppc_inst(PPC_INST_NOP));
> > >
> > > return 0;
> > >
> > > diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
> > > index 52ddd3122dc8..8b285bf11218 100644
> > > --- a/arch/powerpc/lib/sstep.c
> > > +++ b/arch/powerpc/lib/sstep.c
> > > @@ -1169,10 +1169,12 @@ int analyse_instr(struct instruction_op *op,
> >
> > const
> >
> > > struct pt_regs *regs, unsigned long int imm;
> > >
> > > unsigned long int val, val2;
> > > unsigned int mb, me, sh;
> > >
> > > - unsigned int word;
> > > + unsigned int word, suffix;
> > >
> > > long ival;
> > >
> > > word = ppc_inst_val(instr);
> > >
> > > + suffix = ppc_inst_suffix(instr);
> > > +
> > >
> > > op->type = COMPUTE;
> > >
> > > opcode = word >> 26;
> > >
> > > diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
> > > index 6f3bcdcfc9c7..b704aebb099a 100644
> > > --- a/arch/powerpc/xmon/xmon.c
> > > +++ b/arch/powerpc/xmon/xmon.c
> > > @@ -761,8 +761,8 @@ static int xmon_bpt(struct pt_regs *regs)
> > >
> > > /* Are we at the trap at bp->instr[1] for some bp? */
> > > bp = in_breakpoint_table(regs->nip, &offset);
> > >
> > > - if (bp != NULL && offset == 4) {
> > > - regs->nip = bp->address + 4;
> > > + if (bp != NULL && (offset == 4 || offset == 8)) {
> > > + regs->nip = bp->address + offset;
> > >
> > > atomic_dec(&bp->ref_count);
> > > return 1;
> > >
> > > }
> > >
> > > @@ -863,7 +863,7 @@ static struct bpt *in_breakpoint_table(unsigned long
> > > nip, unsigned long *offp) if (off >= sizeof(bpt_table))
> > >
> > > return NULL;
> > >
> > > *offp = off % BPT_SIZE;
> > >
> > > - if (*offp != 0 && *offp != 4)
> > > + if (*offp != 0 && *offp != 4 && *offp != 8)
> > >
> > > return NULL;
> > >
> > > return bpts + (off / BPT_SIZE);
> > >
> > > }
> > >
> > > diff --git a/arch/powerpc/xmon/xmon_bpts.S
> >
> > b/arch/powerpc/xmon/xmon_bpts.S
> >
> > > index ebb2dbc70ca8..09058eb6abbd 100644
> > > --- a/arch/powerpc/xmon/xmon_bpts.S
> > > +++ b/arch/powerpc/xmon/xmon_bpts.S
> > > @@ -3,6 +3,8 @@
> > >
> > > #include <asm/asm-compat.h>
> > > #include "xmon_bpts.h"
> > >
> > > +/* Prefixed instructions can not cross 64 byte boundaries */
> > > +.align 6
> > >
> > > .global bpt_table
> > >
> > > bpt_table:
> > > - .space NBPTS * 8
> > > + .space NBPTS * 16
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 03/21] powerpc: Change calling convention for create_branch() et. al.
2020-04-06 8:09 ` [PATCH v5 03/21] powerpc: Change calling convention for create_branch() et. al Jordan Niethe
2020-04-06 10:25 ` kbuild test robot
@ 2020-04-07 6:10 ` Balamuruhan S
2020-04-07 6:35 ` Jordan Niethe
1 sibling, 1 reply; 71+ messages in thread
From: Balamuruhan S @ 2020-04-07 6:10 UTC (permalink / raw)
To: Jordan Niethe, linuxppc-dev; +Cc: alistair, dja, npiggin
On Mon, 2020-04-06 at 18:09 +1000, Jordan Niethe wrote:
> create_branch(), create_cond_branch() and translate_branch() return the
> instruction that they create, or return 0 to signal an error. Seperate
s/seperate/separate
> these concerns in preparation for an instruction type that is not just
> an unsigned int. Fill the created instruction to a pointer passed as
> the first parameter to the function and use a non-zero return value to
> signify an error.
>
> Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> ---
> v5: New to series
> ---
> arch/powerpc/include/asm/code-patching.h | 12 +-
> arch/powerpc/kernel/optprobes.c | 24 ++--
> arch/powerpc/kernel/setup_32.c | 2 +-
> arch/powerpc/kernel/trace/ftrace.c | 24 ++--
> arch/powerpc/lib/code-patching.c | 133 +++++++++++++----------
> arch/powerpc/lib/feature-fixups.c | 5 +-
> 6 files changed, 117 insertions(+), 83 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/code-patching.h
> b/arch/powerpc/include/asm/code-patching.h
> index 898b54262881..351dda7215b6 100644
> --- a/arch/powerpc/include/asm/code-patching.h
> +++ b/arch/powerpc/include/asm/code-patching.h
> @@ -22,10 +22,10 @@
> #define BRANCH_ABSOLUTE 0x2
>
> bool is_offset_in_branch_range(long offset);
> -unsigned int create_branch(const unsigned int *addr,
> - unsigned long target, int flags);
> -unsigned int create_cond_branch(const unsigned int *addr,
> - unsigned long target, int flags);
> +int create_branch(unsigned int *instr, const unsigned int *addr,
> + unsigned long target, int flags);
> +int create_cond_branch(unsigned int *instr, const unsigned int *addr,
> + unsigned long target, int flags);
> int patch_branch(unsigned int *addr, unsigned long target, int flags);
> int patch_instruction(unsigned int *addr, unsigned int instr);
> int raw_patch_instruction(unsigned int *addr, unsigned int instr);
> @@ -60,8 +60,8 @@ int instr_is_relative_branch(unsigned int instr);
> int instr_is_relative_link_branch(unsigned int instr);
> int instr_is_branch_to_addr(const unsigned int *instr, unsigned long addr);
> unsigned long branch_target(const unsigned int *instr);
> -unsigned int translate_branch(const unsigned int *dest,
> - const unsigned int *src);
> +int translate_branch(unsigned int *instr, const unsigned int *dest,
> + const unsigned int *src);
> extern bool is_conditional_branch(unsigned int instr);
> #ifdef CONFIG_PPC_BOOK3E_64
> void __patch_exception(int exc, unsigned long addr);
> diff --git a/arch/powerpc/kernel/optprobes.c
> b/arch/powerpc/kernel/optprobes.c
> index 024f7aad1952..445b3dad82dc 100644
> --- a/arch/powerpc/kernel/optprobes.c
> +++ b/arch/powerpc/kernel/optprobes.c
> @@ -251,15 +251,17 @@ int arch_prepare_optimized_kprobe(struct
> optimized_kprobe *op, struct kprobe *p)
> goto error;
> }
>
> - branch_op_callback = create_branch((unsigned int *)buff +
> TMPL_CALL_HDLR_IDX,
> - (unsigned long)op_callback_addr,
> - BRANCH_SET_LINK);
> + rc = create_branch(&branch_op_callback,
> + (unsigned int *)buff + TMPL_CALL_HDLR_IDX,
> + (unsigned long)op_callback_addr,
> + BRANCH_SET_LINK);
>
> - branch_emulate_step = create_branch((unsigned int *)buff +
> TMPL_EMULATE_IDX,
> - (unsigned long)emulate_step_addr,
> - BRANCH_SET_LINK);
> + rc |= create_branch(&branch_emulate_step,
> + (unsigned int *)buff + TMPL_EMULATE_IDX,
> + (unsigned long)emulate_step_addr,
> + BRANCH_SET_LINK);
>
> - if (!branch_op_callback || !branch_emulate_step)
> + if (rc)
> goto error;
>
> patch_instruction(buff + TMPL_CALL_HDLR_IDX, branch_op_callback);
> @@ -305,6 +307,7 @@ int arch_check_optimized_kprobe(struct optimized_kprobe
> *op)
>
> void arch_optimize_kprobes(struct list_head *oplist)
> {
> + unsigned int instr;
> struct optimized_kprobe *op;
> struct optimized_kprobe *tmp;
>
> @@ -315,9 +318,10 @@ void arch_optimize_kprobes(struct list_head *oplist)
> */
> memcpy(op->optinsn.copied_insn, op->kp.addr,
> RELATIVEJUMP_SIZE);
> - patch_instruction(op->kp.addr,
> - create_branch((unsigned int *)op->kp.addr,
> - (unsigned long)op->optinsn.insn, 0));
> + create_branch(&instr,
> + (unsigned int *)op->kp.addr,
> + (unsigned long)op->optinsn.insn, 0);
> + patch_instruction(op->kp.addr, instr);
> list_del_init(&op->list);
> }
> }
> diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
> index 5b49b26eb154..c1bdd462c5c0 100644
> --- a/arch/powerpc/kernel/setup_32.c
> +++ b/arch/powerpc/kernel/setup_32.c
> @@ -88,7 +88,7 @@ notrace void __init machine_init(u64 dt_ptr)
>
> patch_instruction_site(&patch__memcpy_nocache, PPC_INST_NOP);
>
> - insn = create_cond_branch(addr, branch_target(addr), 0x820000);
> + create_cond_branch(&insn, addr, branch_target(addr), 0x820000);
> patch_instruction(addr, insn); /* replace b by bne cr0 */
>
> /* Do some early initialization based on the flat device tree */
> diff --git a/arch/powerpc/kernel/trace/ftrace.c
> b/arch/powerpc/kernel/trace/ftrace.c
> index 7ea0ca044b65..4dcb379133f8 100644
> --- a/arch/powerpc/kernel/trace/ftrace.c
> +++ b/arch/powerpc/kernel/trace/ftrace.c
> @@ -48,7 +48,7 @@ ftrace_call_replace(unsigned long ip, unsigned long addr,
> int link)
> addr = ppc_function_entry((void *)addr);
>
> /* if (link) set op to 'bl' else 'b' */
> - op = create_branch((unsigned int *)ip, addr, link ? 1 : 0);
> + create_branch(&op, (unsigned int *)ip, addr, link ? 1 : 0);
>
> return op;
> }
> @@ -89,10 +89,11 @@ ftrace_modify_code(unsigned long ip, unsigned int old,
> unsigned int new)
> */
> static int test_24bit_addr(unsigned long ip, unsigned long addr)
> {
> + unsigned int op;
> addr = ppc_function_entry((void *)addr);
>
> /* use the create_branch to verify that this offset can be branched */
> - return create_branch((unsigned int *)ip, addr, 0);
> + return create_branch(&op, (unsigned int *)ip, addr, 0) == 0;
> }
>
> static int is_bl_op(unsigned int op)
> @@ -287,6 +288,7 @@ __ftrace_make_nop(struct module *mod,
> static unsigned long find_ftrace_tramp(unsigned long ip)
> {
> int i;
> + unsigned int instr;
>
> /*
> * We have the compiler generated long_branch tramps at the end
> @@ -295,7 +297,8 @@ static unsigned long find_ftrace_tramp(unsigned long ip)
> for (i = NUM_FTRACE_TRAMPS - 1; i >= 0; i--)
> if (!ftrace_tramps[i])
> continue;
> - else if (create_branch((void *)ip, ftrace_tramps[i], 0))
> + else if (create_branch(&instr, (void *)ip,
> + ftrace_tramps[i], 0) == 0)
> return ftrace_tramps[i];
>
> return 0;
> @@ -324,6 +327,7 @@ static int setup_mcount_compiler_tramp(unsigned long
> tramp)
> {
> int i, op;
> unsigned long ptr;
> + unsigned int instr;
> static unsigned long ftrace_plt_tramps[NUM_FTRACE_TRAMPS];
>
> /* Is this a known long jump tramp? */
> @@ -366,7 +370,7 @@ static int setup_mcount_compiler_tramp(unsigned long
> tramp)
> #else
> ptr = ppc_global_function_entry((void *)ftrace_caller);
> #endif
> - if (!create_branch((void *)tramp, ptr, 0)) {
> + if (create_branch(&instr, (void *)tramp, ptr, 0)) {
> pr_debug("%ps is not reachable from existing mcount tramp\n",
> (void *)ptr);
> return -1;
> @@ -511,6 +515,7 @@ static int
> __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
> {
> unsigned int op[2];
> + unsigned int instr;
> void *ip = (void *)rec->ip;
> unsigned long entry, ptr, tramp;
> struct module *mod = rec->arch.mod;
> @@ -557,7 +562,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long
> addr)
> }
>
> /* Ensure branch is within 24 bits */
> - if (!create_branch(ip, tramp, BRANCH_SET_LINK)) {
> + if (create_branch(&instr, ip, tramp, BRANCH_SET_LINK)) {
> pr_err("Branch out of range\n");
> return -EINVAL;
> }
> @@ -574,6 +579,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long
> addr)
> static int
> __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
> {
> + int err;
> unsigned int op;
> unsigned long ip = rec->ip;
>
> @@ -594,9 +600,9 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long
> addr)
> }
>
> /* create the branch to the trampoline */
> - op = create_branch((unsigned int *)ip,
> - rec->arch.mod->arch.tramp, BRANCH_SET_LINK);
> - if (!op) {
> + err = create_branch(&op, (unsigned int *)ip,
> + rec->arch.mod->arch.tramp, BRANCH_SET_LINK);
> + if (!err) {
should this be `if (err)` as per your new changes ?
> pr_err("REL24 out of range!\n");
> return -EINVAL;
> }
> @@ -776,7 +782,7 @@ __ftrace_modify_call(struct dyn_ftrace *rec, unsigned
> long old_addr,
> }
>
> /* Ensure branch is within 24 bits */
> - if (!create_branch((unsigned int *)ip, tramp, BRANCH_SET_LINK)) {
> + if (create_branch(&op, (unsigned int *)ip, tramp, BRANCH_SET_LINK)) {
> pr_err("Branch out of range\n");
> return -EINVAL;
> }
> diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-
> patching.c
> index 3345f039a876..4af564aeedf1 100644
> --- a/arch/powerpc/lib/code-patching.c
> +++ b/arch/powerpc/lib/code-patching.c
> @@ -196,7 +196,10 @@ NOKPROBE_SYMBOL(patch_instruction);
>
> int patch_branch(unsigned int *addr, unsigned long target, int flags)
> {
> - return patch_instruction(addr, create_branch(addr, target, flags));
> + unsigned int instr;
> +
> + create_branch(&instr, addr, target, flags);
> + return patch_instruction(addr, instr);
> }
>
> bool is_offset_in_branch_range(long offset)
> @@ -243,30 +246,30 @@ bool is_conditional_branch(unsigned int instr)
> }
> NOKPROBE_SYMBOL(is_conditional_branch);
>
> -unsigned int create_branch(const unsigned int *addr,
> - unsigned long target, int flags)
> +int create_branch(unsigned int *instr,
> + const unsigned int *addr,
> + unsigned long target, int flags)
> {
> - unsigned int instruction;
> long offset;
>
> + *instr = 0;
> offset = target;
> if (! (flags & BRANCH_ABSOLUTE))
> offset = offset - (unsigned long)addr;
>
> /* Check we can represent the target in the instruction format */
> if (!is_offset_in_branch_range(offset))
> - return 0;
> + return 1;
>
> /* Mask out the flags and target, so they don't step on each other. */
> - instruction = 0x48000000 | (flags & 0x3) | (offset & 0x03FFFFFC);
> + *instr = 0x48000000 | (flags & 0x3) | (offset & 0x03FFFFFC);
>
> - return instruction;
> + return 0;
> }
>
> -unsigned int create_cond_branch(const unsigned int *addr,
> - unsigned long target, int flags)
> +int create_cond_branch(unsigned int *instr, const unsigned int *addr,
> + unsigned long target, int flags)
> {
> - unsigned int instruction;
> long offset;
>
> offset = target;
> @@ -275,12 +278,12 @@ unsigned int create_cond_branch(const unsigned int
> *addr,
>
> /* Check we can represent the target in the instruction format */
> if (offset < -0x8000 || offset > 0x7FFF || offset & 0x3)
> - return 0;
> + return 1;
>
> /* Mask out the flags and target, so they don't step on each other. */
> - instruction = 0x40000000 | (flags & 0x3FF0003) | (offset & 0xFFFC);
> + *instr = 0x40000000 | (flags & 0x3FF0003) | (offset & 0xFFFC);
>
> - return instruction;
> + return 0;
> }
>
> static unsigned int branch_opcode(unsigned int instr)
> @@ -361,18 +364,18 @@ int instr_is_branch_to_addr(const unsigned int *instr,
> unsigned long addr)
> return 0;
> }
>
> -unsigned int translate_branch(const unsigned int *dest, const unsigned int
> *src)
> +int translate_branch(unsigned int *instr, const unsigned int *dest, const
> unsigned int *src)
> {
> unsigned long target;
>
> target = branch_target(src);
>
> if (instr_is_branch_iform(*src))
> - return create_branch(dest, target, *src);
> + return create_branch(instr, dest, target, *src);
> else if (instr_is_branch_bform(*src))
> - return create_cond_branch(dest, target, *src);
> + return create_cond_branch(instr, dest, target, *src);
>
> - return 0;
> + return 1;
> }
>
> #ifdef CONFIG_PPC_BOOK3E_64
> @@ -403,6 +406,7 @@ static void __init test_trampoline(void)
>
> static void __init test_branch_iform(void)
> {
> + int err;
> unsigned int instr;
> unsigned long addr;
>
> @@ -443,35 +447,35 @@ static void __init test_branch_iform(void)
> check(instr_is_branch_to_addr(&instr, addr - 0x2000000));
>
> /* Branch to self, with link */
> - instr = create_branch(&instr, addr, BRANCH_SET_LINK);
> + err = create_branch(&instr, &instr, addr, BRANCH_SET_LINK);
> check(instr_is_branch_to_addr(&instr, addr));
>
> /* Branch to self - 0x100, with link */
> - instr = create_branch(&instr, addr - 0x100, BRANCH_SET_LINK);
> + err = create_branch(&instr, &instr, addr - 0x100, BRANCH_SET_LINK);
> check(instr_is_branch_to_addr(&instr, addr - 0x100));
>
> /* Branch to self + 0x100, no link */
> - instr = create_branch(&instr, addr + 0x100, 0);
> + err = create_branch(&instr, &instr, addr + 0x100, 0);
> check(instr_is_branch_to_addr(&instr, addr + 0x100));
>
> /* Maximum relative negative offset, - 32 MB */
> - instr = create_branch(&instr, addr - 0x2000000, BRANCH_SET_LINK);
> + err = create_branch(&instr, &instr, addr - 0x2000000, BRANCH_SET_LINK);
> check(instr_is_branch_to_addr(&instr, addr - 0x2000000));
>
> /* Out of range relative negative offset, - 32 MB + 4*/
> - instr = create_branch(&instr, addr - 0x2000004, BRANCH_SET_LINK);
> - check(instr == 0);
> + err = create_branch(&instr, &instr, addr - 0x2000004, BRANCH_SET_LINK);
> + check(err);
>
> /* Out of range relative positive offset, + 32 MB */
> - instr = create_branch(&instr, addr + 0x2000000, BRANCH_SET_LINK);
> - check(instr == 0);
> + err = create_branch(&instr, &instr, addr + 0x2000000, BRANCH_SET_LINK);
> + check(err);
>
> /* Unaligned target */
> - instr = create_branch(&instr, addr + 3, BRANCH_SET_LINK);
> - check(instr == 0);
> + err = create_branch(&instr, &instr, addr + 3, BRANCH_SET_LINK);
> + check(err);
>
> /* Check flags are masked correctly */
> - instr = create_branch(&instr, addr, 0xFFFFFFFC);
> + err = create_branch(&instr, &instr, addr, 0xFFFFFFFC);
> check(instr_is_branch_to_addr(&instr, addr));
> check(instr == 0x48000000);
> }
> @@ -480,16 +484,19 @@ static void __init test_create_function_call(void)
> {
> unsigned int *iptr;
> unsigned long dest;
> + unsigned int instr;
>
> /* Check we can create a function call */
> iptr = (unsigned int *)ppc_function_entry(test_trampoline);
> dest = ppc_function_entry(test_create_function_call);
> - patch_instruction(iptr, create_branch(iptr, dest, BRANCH_SET_LINK));
> + create_branch(&instr, iptr, dest, BRANCH_SET_LINK);
> + patch_instruction(iptr, instr);
Are we sure that `create_branch()` would always succeed here to do
patch_instruction() ?
> check(instr_is_branch_to_addr(iptr, dest));
> }
>
> static void __init test_branch_bform(void)
> {
> + int err;
> unsigned long addr;
> unsigned int *iptr, instr, flags;
>
> @@ -525,35 +532,35 @@ static void __init test_branch_bform(void)
> flags = 0x3ff000 | BRANCH_SET_LINK;
>
> /* Branch to self */
> - instr = create_cond_branch(iptr, addr, flags);
> + err = create_cond_branch(&instr, iptr, addr, flags);
> check(instr_is_branch_to_addr(&instr, addr));
>
> /* Branch to self - 0x100 */
> - instr = create_cond_branch(iptr, addr - 0x100, flags);
> + err = create_cond_branch(&instr, iptr, addr - 0x100, flags);
> check(instr_is_branch_to_addr(&instr, addr - 0x100));
>
> /* Branch to self + 0x100 */
> - instr = create_cond_branch(iptr, addr + 0x100, flags);
> + err = create_cond_branch(&instr, iptr, addr + 0x100, flags);
> check(instr_is_branch_to_addr(&instr, addr + 0x100));
>
> /* Maximum relative negative offset, - 32 KB */
> - instr = create_cond_branch(iptr, addr - 0x8000, flags);
> + err = create_cond_branch(&instr, iptr, addr - 0x8000, flags);
> check(instr_is_branch_to_addr(&instr, addr - 0x8000));
>
> /* Out of range relative negative offset, - 32 KB + 4*/
> - instr = create_cond_branch(iptr, addr - 0x8004, flags);
> - check(instr == 0);
> + err = create_cond_branch(&instr, iptr, addr - 0x8004, flags);
> + check(err);
>
> /* Out of range relative positive offset, + 32 KB */
> - instr = create_cond_branch(iptr, addr + 0x8000, flags);
> - check(instr == 0);
> + err = create_cond_branch(&instr, iptr, addr + 0x8000, flags);
> + check(err);
>
> /* Unaligned target */
> - instr = create_cond_branch(iptr, addr + 3, flags);
> - check(instr == 0);
> + err = create_cond_branch(&instr, iptr, addr + 3, flags);
> + check(err);
>
> /* Check flags are masked correctly */
> - instr = create_cond_branch(iptr, addr, 0xFFFFFFFC);
> + err = create_cond_branch(&instr, iptr, addr, 0xFFFFFFFC);
> check(instr_is_branch_to_addr(&instr, addr));
> check(instr == 0x43FF0000);
> }
> @@ -562,6 +569,7 @@ static void __init test_translate_branch(void)
> {
> unsigned long addr;
> unsigned int *p, *q;
> + unsigned int instr;
> void *buf;
>
> buf = vmalloc(PAGE_ALIGN(0x2000000 + 1));
> @@ -575,7 +583,8 @@ static void __init test_translate_branch(void)
> patch_branch(p, addr, 0);
> check(instr_is_branch_to_addr(p, addr));
> q = p + 1;
> - patch_instruction(q, translate_branch(q, p));
> + translate_branch(&instr, q, p);
> + patch_instruction(q, instr);
same here and elsewhere in similar such places where we do patch_instruction()
-- Bala
> check(instr_is_branch_to_addr(q, addr));
>
> /* Maximum negative case, move b . to addr + 32 MB */
> @@ -583,7 +592,8 @@ static void __init test_translate_branch(void)
> addr = (unsigned long)p;
> patch_branch(p, addr, 0);
> q = buf + 0x2000000;
> - patch_instruction(q, translate_branch(q, p));
> + translate_branch(&instr, q, p);
> + patch_instruction(q, instr);
> check(instr_is_branch_to_addr(p, addr));
> check(instr_is_branch_to_addr(q, addr));
> check(*q == 0x4a000000);
> @@ -593,7 +603,8 @@ static void __init test_translate_branch(void)
> addr = (unsigned long)p;
> patch_branch(p, addr, 0);
> q = buf + 4;
> - patch_instruction(q, translate_branch(q, p));
> + translate_branch(&instr, q, p);
> + patch_instruction(q, instr);
> check(instr_is_branch_to_addr(p, addr));
> check(instr_is_branch_to_addr(q, addr));
> check(*q == 0x49fffffc);
> @@ -603,7 +614,8 @@ static void __init test_translate_branch(void)
> addr = 0x1000000 + (unsigned long)buf;
> patch_branch(p, addr, BRANCH_SET_LINK);
> q = buf + 0x1400000;
> - patch_instruction(q, translate_branch(q, p));
> + translate_branch(&instr, q, p);
> + patch_instruction(q, instr);
> check(instr_is_branch_to_addr(p, addr));
> check(instr_is_branch_to_addr(q, addr));
>
> @@ -612,7 +624,8 @@ static void __init test_translate_branch(void)
> addr = 0x2000000 + (unsigned long)buf;
> patch_branch(p, addr, 0);
> q = buf + 4;
> - patch_instruction(q, translate_branch(q, p));
> + translate_branch(&instr, q, p);
> + patch_instruction(q, instr);
> check(instr_is_branch_to_addr(p, addr));
> check(instr_is_branch_to_addr(q, addr));
>
> @@ -622,18 +635,22 @@ static void __init test_translate_branch(void)
> /* Simple case, branch to self moved a little */
> p = buf;
> addr = (unsigned long)p;
> - patch_instruction(p, create_cond_branch(p, addr, 0));
> + create_cond_branch(&instr, p, addr, 0);
> + patch_instruction(p, instr);
> check(instr_is_branch_to_addr(p, addr));
> q = p + 1;
> - patch_instruction(q, translate_branch(q, p));
> + translate_branch(&instr, q, p);
> + patch_instruction(q, instr);
> check(instr_is_branch_to_addr(q, addr));
>
> /* Maximum negative case, move b . to addr + 32 KB */
> p = buf;
> addr = (unsigned long)p;
> - patch_instruction(p, create_cond_branch(p, addr, 0xFFFFFFFC));
> + create_cond_branch(&instr, p, addr, 0xFFFFFFFC);
> + patch_instruction(p, instr);
> q = buf + 0x8000;
> - patch_instruction(q, translate_branch(q, p));
> + translate_branch(&instr, q, p);
> + patch_instruction(q, instr);
> check(instr_is_branch_to_addr(p, addr));
> check(instr_is_branch_to_addr(q, addr));
> check(*q == 0x43ff8000);
> @@ -641,9 +658,11 @@ static void __init test_translate_branch(void)
> /* Maximum positive case, move x to x - 32 KB + 4 */
> p = buf + 0x8000;
> addr = (unsigned long)p;
> - patch_instruction(p, create_cond_branch(p, addr, 0xFFFFFFFC));
> + create_cond_branch(&instr, p, addr, 0xFFFFFFFC);
> + patch_instruction(p, instr);
> q = buf + 4;
> - patch_instruction(q, translate_branch(q, p));
> + translate_branch(&instr, q, p);
> + patch_instruction(q, instr);
> check(instr_is_branch_to_addr(p, addr));
> check(instr_is_branch_to_addr(q, addr));
> check(*q == 0x43ff7ffc);
> @@ -651,18 +670,22 @@ static void __init test_translate_branch(void)
> /* Jump to x + 12 KB moved to x + 20 KB */
> p = buf;
> addr = 0x3000 + (unsigned long)buf;
> - patch_instruction(p, create_cond_branch(p, addr, BRANCH_SET_LINK));
> + create_cond_branch(&instr, p, addr, BRANCH_SET_LINK);
> + patch_instruction(p, instr);
> q = buf + 0x5000;
> - patch_instruction(q, translate_branch(q, p));
> + translate_branch(&instr, q, p);
> + patch_instruction(q, instr);
> check(instr_is_branch_to_addr(p, addr));
> check(instr_is_branch_to_addr(q, addr));
>
> /* Jump to x + 8 KB moved to x - 8 KB + 4 */
> p = buf + 0x2000;
> addr = 0x4000 + (unsigned long)buf;
> - patch_instruction(p, create_cond_branch(p, addr, 0));
> + create_cond_branch(&instr, p, addr, 0);
> + patch_instruction(p, instr);
> q = buf + 4;
> - patch_instruction(q, translate_branch(q, p));
> + translate_branch(&instr, q, p);
> + patch_instruction(q, instr);
> check(instr_is_branch_to_addr(p, addr));
> check(instr_is_branch_to_addr(q, addr));
>
> diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-
> fixups.c
> index 4ba634b89ce5..b129d7b4e7dd 100644
> --- a/arch/powerpc/lib/feature-fixups.c
> +++ b/arch/powerpc/lib/feature-fixups.c
> @@ -44,6 +44,7 @@ static unsigned int *calc_addr(struct fixup_entry *fcur,
> long offset)
> static int patch_alt_instruction(unsigned int *src, unsigned int *dest,
> unsigned int *alt_start, unsigned int
> *alt_end)
> {
> + int err;
> unsigned int instr;
>
> instr = *src;
> @@ -53,8 +54,8 @@ static int patch_alt_instruction(unsigned int *src,
> unsigned int *dest,
>
> /* Branch within the section doesn't need translating */
> if (target < alt_start || target > alt_end) {
> - instr = translate_branch(dest, src);
> - if (!instr)
> + err = translate_branch(&instr, dest, src);
> + if (err)
> return 1;
> }
> }
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 03/21] powerpc: Change calling convention for create_branch() et. al.
2020-04-07 6:10 ` Balamuruhan S
@ 2020-04-07 6:35 ` Jordan Niethe
2020-04-07 6:59 ` Balamuruhan S
0 siblings, 1 reply; 71+ messages in thread
From: Jordan Niethe @ 2020-04-07 6:35 UTC (permalink / raw)
To: Balamuruhan S
Cc: Alistair Popple, Nicholas Piggin, linuxppc-dev, Daniel Axtens
On Tue, Apr 7, 2020 at 4:10 PM Balamuruhan S <bala24@linux.ibm.com> wrote:
>
> On Mon, 2020-04-06 at 18:09 +1000, Jordan Niethe wrote:
> > create_branch(), create_cond_branch() and translate_branch() return the
> > instruction that they create, or return 0 to signal an error. Seperate
>
> s/seperate/separate
thanks.
>
> > these concerns in preparation for an instruction type that is not just
> > an unsigned int. Fill the created instruction to a pointer passed as
> > the first parameter to the function and use a non-zero return value to
> > signify an error.
> >
> > Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> > ---
> > v5: New to series
> > ---
> > arch/powerpc/include/asm/code-patching.h | 12 +-
> > arch/powerpc/kernel/optprobes.c | 24 ++--
> > arch/powerpc/kernel/setup_32.c | 2 +-
> > arch/powerpc/kernel/trace/ftrace.c | 24 ++--
> > arch/powerpc/lib/code-patching.c | 133 +++++++++++++----------
> > arch/powerpc/lib/feature-fixups.c | 5 +-
> > 6 files changed, 117 insertions(+), 83 deletions(-)
> >
> > diff --git a/arch/powerpc/include/asm/code-patching.h
> > b/arch/powerpc/include/asm/code-patching.h
> > index 898b54262881..351dda7215b6 100644
> > --- a/arch/powerpc/include/asm/code-patching.h
> > +++ b/arch/powerpc/include/asm/code-patching.h
> > @@ -22,10 +22,10 @@
> > #define BRANCH_ABSOLUTE 0x2
> >
> > bool is_offset_in_branch_range(long offset);
> > -unsigned int create_branch(const unsigned int *addr,
> > - unsigned long target, int flags);
> > -unsigned int create_cond_branch(const unsigned int *addr,
> > - unsigned long target, int flags);
> > +int create_branch(unsigned int *instr, const unsigned int *addr,
> > + unsigned long target, int flags);
> > +int create_cond_branch(unsigned int *instr, const unsigned int *addr,
> > + unsigned long target, int flags);
> > int patch_branch(unsigned int *addr, unsigned long target, int flags);
> > int patch_instruction(unsigned int *addr, unsigned int instr);
> > int raw_patch_instruction(unsigned int *addr, unsigned int instr);
> > @@ -60,8 +60,8 @@ int instr_is_relative_branch(unsigned int instr);
> > int instr_is_relative_link_branch(unsigned int instr);
> > int instr_is_branch_to_addr(const unsigned int *instr, unsigned long addr);
> > unsigned long branch_target(const unsigned int *instr);
> > -unsigned int translate_branch(const unsigned int *dest,
> > - const unsigned int *src);
> > +int translate_branch(unsigned int *instr, const unsigned int *dest,
> > + const unsigned int *src);
> > extern bool is_conditional_branch(unsigned int instr);
> > #ifdef CONFIG_PPC_BOOK3E_64
> > void __patch_exception(int exc, unsigned long addr);
> > diff --git a/arch/powerpc/kernel/optprobes.c
> > b/arch/powerpc/kernel/optprobes.c
> > index 024f7aad1952..445b3dad82dc 100644
> > --- a/arch/powerpc/kernel/optprobes.c
> > +++ b/arch/powerpc/kernel/optprobes.c
> > @@ -251,15 +251,17 @@ int arch_prepare_optimized_kprobe(struct
> > optimized_kprobe *op, struct kprobe *p)
> > goto error;
> > }
> >
> > - branch_op_callback = create_branch((unsigned int *)buff +
> > TMPL_CALL_HDLR_IDX,
> > - (unsigned long)op_callback_addr,
> > - BRANCH_SET_LINK);
> > + rc = create_branch(&branch_op_callback,
> > + (unsigned int *)buff + TMPL_CALL_HDLR_IDX,
> > + (unsigned long)op_callback_addr,
> > + BRANCH_SET_LINK);
> >
> > - branch_emulate_step = create_branch((unsigned int *)buff +
> > TMPL_EMULATE_IDX,
> > - (unsigned long)emulate_step_addr,
> > - BRANCH_SET_LINK);
> > + rc |= create_branch(&branch_emulate_step,
> > + (unsigned int *)buff + TMPL_EMULATE_IDX,
> > + (unsigned long)emulate_step_addr,
> > + BRANCH_SET_LINK);
> >
> > - if (!branch_op_callback || !branch_emulate_step)
> > + if (rc)
> > goto error;
> >
> > patch_instruction(buff + TMPL_CALL_HDLR_IDX, branch_op_callback);
> > @@ -305,6 +307,7 @@ int arch_check_optimized_kprobe(struct optimized_kprobe
> > *op)
> >
> > void arch_optimize_kprobes(struct list_head *oplist)
> > {
> > + unsigned int instr;
> > struct optimized_kprobe *op;
> > struct optimized_kprobe *tmp;
> >
> > @@ -315,9 +318,10 @@ void arch_optimize_kprobes(struct list_head *oplist)
> > */
> > memcpy(op->optinsn.copied_insn, op->kp.addr,
> > RELATIVEJUMP_SIZE);
> > - patch_instruction(op->kp.addr,
> > - create_branch((unsigned int *)op->kp.addr,
> > - (unsigned long)op->optinsn.insn, 0));
> > + create_branch(&instr,
> > + (unsigned int *)op->kp.addr,
> > + (unsigned long)op->optinsn.insn, 0);
> > + patch_instruction(op->kp.addr, instr);
> > list_del_init(&op->list);
> > }
> > }
> > diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
> > index 5b49b26eb154..c1bdd462c5c0 100644
> > --- a/arch/powerpc/kernel/setup_32.c
> > +++ b/arch/powerpc/kernel/setup_32.c
> > @@ -88,7 +88,7 @@ notrace void __init machine_init(u64 dt_ptr)
> >
> > patch_instruction_site(&patch__memcpy_nocache, PPC_INST_NOP);
> >
> > - insn = create_cond_branch(addr, branch_target(addr), 0x820000);
> > + create_cond_branch(&insn, addr, branch_target(addr), 0x820000);
> > patch_instruction(addr, insn); /* replace b by bne cr0 */
> >
> > /* Do some early initialization based on the flat device tree */
> > diff --git a/arch/powerpc/kernel/trace/ftrace.c
> > b/arch/powerpc/kernel/trace/ftrace.c
> > index 7ea0ca044b65..4dcb379133f8 100644
> > --- a/arch/powerpc/kernel/trace/ftrace.c
> > +++ b/arch/powerpc/kernel/trace/ftrace.c
> > @@ -48,7 +48,7 @@ ftrace_call_replace(unsigned long ip, unsigned long addr,
> > int link)
> > addr = ppc_function_entry((void *)addr);
> >
> > /* if (link) set op to 'bl' else 'b' */
> > - op = create_branch((unsigned int *)ip, addr, link ? 1 : 0);
> > + create_branch(&op, (unsigned int *)ip, addr, link ? 1 : 0);
> >
> > return op;
> > }
> > @@ -89,10 +89,11 @@ ftrace_modify_code(unsigned long ip, unsigned int old,
> > unsigned int new)
> > */
> > static int test_24bit_addr(unsigned long ip, unsigned long addr)
> > {
> > + unsigned int op;
> > addr = ppc_function_entry((void *)addr);
> >
> > /* use the create_branch to verify that this offset can be branched */
> > - return create_branch((unsigned int *)ip, addr, 0);
> > + return create_branch(&op, (unsigned int *)ip, addr, 0) == 0;
> > }
> >
> > static int is_bl_op(unsigned int op)
> > @@ -287,6 +288,7 @@ __ftrace_make_nop(struct module *mod,
> > static unsigned long find_ftrace_tramp(unsigned long ip)
> > {
> > int i;
> > + unsigned int instr;
> >
> > /*
> > * We have the compiler generated long_branch tramps at the end
> > @@ -295,7 +297,8 @@ static unsigned long find_ftrace_tramp(unsigned long ip)
> > for (i = NUM_FTRACE_TRAMPS - 1; i >= 0; i--)
> > if (!ftrace_tramps[i])
> > continue;
> > - else if (create_branch((void *)ip, ftrace_tramps[i], 0))
> > + else if (create_branch(&instr, (void *)ip,
> > + ftrace_tramps[i], 0) == 0)
> > return ftrace_tramps[i];
> >
> > return 0;
> > @@ -324,6 +327,7 @@ static int setup_mcount_compiler_tramp(unsigned long
> > tramp)
> > {
> > int i, op;
> > unsigned long ptr;
> > + unsigned int instr;
> > static unsigned long ftrace_plt_tramps[NUM_FTRACE_TRAMPS];
> >
> > /* Is this a known long jump tramp? */
> > @@ -366,7 +370,7 @@ static int setup_mcount_compiler_tramp(unsigned long
> > tramp)
> > #else
> > ptr = ppc_global_function_entry((void *)ftrace_caller);
> > #endif
> > - if (!create_branch((void *)tramp, ptr, 0)) {
> > + if (create_branch(&instr, (void *)tramp, ptr, 0)) {
> > pr_debug("%ps is not reachable from existing mcount tramp\n",
> > (void *)ptr);
> > return -1;
> > @@ -511,6 +515,7 @@ static int
> > __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
> > {
> > unsigned int op[2];
> > + unsigned int instr;
> > void *ip = (void *)rec->ip;
> > unsigned long entry, ptr, tramp;
> > struct module *mod = rec->arch.mod;
> > @@ -557,7 +562,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long
> > addr)
> > }
> >
> > /* Ensure branch is within 24 bits */
> > - if (!create_branch(ip, tramp, BRANCH_SET_LINK)) {
> > + if (create_branch(&instr, ip, tramp, BRANCH_SET_LINK)) {
> > pr_err("Branch out of range\n");
> > return -EINVAL;
> > }
> > @@ -574,6 +579,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long
> > addr)
> > static int
> > __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
> > {
> > + int err;
> > unsigned int op;
> > unsigned long ip = rec->ip;
> >
> > @@ -594,9 +600,9 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long
> > addr)
> > }
> >
> > /* create the branch to the trampoline */
> > - op = create_branch((unsigned int *)ip,
> > - rec->arch.mod->arch.tramp, BRANCH_SET_LINK);
> > - if (!op) {
> > + err = create_branch(&op, (unsigned int *)ip,
> > + rec->arch.mod->arch.tramp, BRANCH_SET_LINK);
> > + if (!err) {
>
>
> should this be `if (err)` as per your new changes ?
You are right.
>
>
> > pr_err("REL24 out of range!\n");
> > return -EINVAL;
> > }
> > @@ -776,7 +782,7 @@ __ftrace_modify_call(struct dyn_ftrace *rec, unsigned
> > long old_addr,
> > }
> >
> > /* Ensure branch is within 24 bits */
> > - if (!create_branch((unsigned int *)ip, tramp, BRANCH_SET_LINK)) {
> > + if (create_branch(&op, (unsigned int *)ip, tramp, BRANCH_SET_LINK)) {
> > pr_err("Branch out of range\n");
> > return -EINVAL;
> > }
> > diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-
> > patching.c
> > index 3345f039a876..4af564aeedf1 100644
> > --- a/arch/powerpc/lib/code-patching.c
> > +++ b/arch/powerpc/lib/code-patching.c
> > @@ -196,7 +196,10 @@ NOKPROBE_SYMBOL(patch_instruction);
> >
> > int patch_branch(unsigned int *addr, unsigned long target, int flags)
> > {
> > - return patch_instruction(addr, create_branch(addr, target, flags));
> > + unsigned int instr;
> > +
> > + create_branch(&instr, addr, target, flags);
> > + return patch_instruction(addr, instr);
> > }
> >
> > bool is_offset_in_branch_range(long offset)
> > @@ -243,30 +246,30 @@ bool is_conditional_branch(unsigned int instr)
> > }
> > NOKPROBE_SYMBOL(is_conditional_branch);
> >
> > -unsigned int create_branch(const unsigned int *addr,
> > - unsigned long target, int flags)
> > +int create_branch(unsigned int *instr,
> > + const unsigned int *addr,
> > + unsigned long target, int flags)
> > {
> > - unsigned int instruction;
> > long offset;
> >
> > + *instr = 0;
> > offset = target;
> > if (! (flags & BRANCH_ABSOLUTE))
> > offset = offset - (unsigned long)addr;
> >
> > /* Check we can represent the target in the instruction format */
> > if (!is_offset_in_branch_range(offset))
> > - return 0;
> > + return 1;
> >
> > /* Mask out the flags and target, so they don't step on each other. */
> > - instruction = 0x48000000 | (flags & 0x3) | (offset & 0x03FFFFFC);
> > + *instr = 0x48000000 | (flags & 0x3) | (offset & 0x03FFFFFC);
> >
> > - return instruction;
> > + return 0;
> > }
> >
> > -unsigned int create_cond_branch(const unsigned int *addr,
> > - unsigned long target, int flags)
> > +int create_cond_branch(unsigned int *instr, const unsigned int *addr,
> > + unsigned long target, int flags)
> > {
> > - unsigned int instruction;
> > long offset;
> >
> > offset = target;
> > @@ -275,12 +278,12 @@ unsigned int create_cond_branch(const unsigned int
> > *addr,
> >
> > /* Check we can represent the target in the instruction format */
> > if (offset < -0x8000 || offset > 0x7FFF || offset & 0x3)
> > - return 0;
> > + return 1;
> >
> > /* Mask out the flags and target, so they don't step on each other. */
> > - instruction = 0x40000000 | (flags & 0x3FF0003) | (offset & 0xFFFC);
> > + *instr = 0x40000000 | (flags & 0x3FF0003) | (offset & 0xFFFC);
> >
> > - return instruction;
> > + return 0;
> > }
> >
> > static unsigned int branch_opcode(unsigned int instr)
> > @@ -361,18 +364,18 @@ int instr_is_branch_to_addr(const unsigned int *instr,
> > unsigned long addr)
> > return 0;
> > }
> >
> > -unsigned int translate_branch(const unsigned int *dest, const unsigned int
> > *src)
> > +int translate_branch(unsigned int *instr, const unsigned int *dest, const
> > unsigned int *src)
> > {
> > unsigned long target;
> >
> > target = branch_target(src);
> >
> > if (instr_is_branch_iform(*src))
> > - return create_branch(dest, target, *src);
> > + return create_branch(instr, dest, target, *src);
> > else if (instr_is_branch_bform(*src))
> > - return create_cond_branch(dest, target, *src);
> > + return create_cond_branch(instr, dest, target, *src);
> >
> > - return 0;
> > + return 1;
> > }
> >
> > #ifdef CONFIG_PPC_BOOK3E_64
> > @@ -403,6 +406,7 @@ static void __init test_trampoline(void)
> >
> > static void __init test_branch_iform(void)
> > {
> > + int err;
> > unsigned int instr;
> > unsigned long addr;
> >
> > @@ -443,35 +447,35 @@ static void __init test_branch_iform(void)
> > check(instr_is_branch_to_addr(&instr, addr - 0x2000000));
> >
> > /* Branch to self, with link */
> > - instr = create_branch(&instr, addr, BRANCH_SET_LINK);
> > + err = create_branch(&instr, &instr, addr, BRANCH_SET_LINK);
> > check(instr_is_branch_to_addr(&instr, addr));
> >
> > /* Branch to self - 0x100, with link */
> > - instr = create_branch(&instr, addr - 0x100, BRANCH_SET_LINK);
> > + err = create_branch(&instr, &instr, addr - 0x100, BRANCH_SET_LINK);
> > check(instr_is_branch_to_addr(&instr, addr - 0x100));
> >
> > /* Branch to self + 0x100, no link */
> > - instr = create_branch(&instr, addr + 0x100, 0);
> > + err = create_branch(&instr, &instr, addr + 0x100, 0);
> > check(instr_is_branch_to_addr(&instr, addr + 0x100));
> >
> > /* Maximum relative negative offset, - 32 MB */
> > - instr = create_branch(&instr, addr - 0x2000000, BRANCH_SET_LINK);
> > + err = create_branch(&instr, &instr, addr - 0x2000000, BRANCH_SET_LINK);
> > check(instr_is_branch_to_addr(&instr, addr - 0x2000000));
> >
> > /* Out of range relative negative offset, - 32 MB + 4*/
> > - instr = create_branch(&instr, addr - 0x2000004, BRANCH_SET_LINK);
> > - check(instr == 0);
> > + err = create_branch(&instr, &instr, addr - 0x2000004, BRANCH_SET_LINK);
> > + check(err);
> >
> > /* Out of range relative positive offset, + 32 MB */
> > - instr = create_branch(&instr, addr + 0x2000000, BRANCH_SET_LINK);
> > - check(instr == 0);
> > + err = create_branch(&instr, &instr, addr + 0x2000000, BRANCH_SET_LINK);
> > + check(err);
> >
> > /* Unaligned target */
> > - instr = create_branch(&instr, addr + 3, BRANCH_SET_LINK);
> > - check(instr == 0);
> > + err = create_branch(&instr, &instr, addr + 3, BRANCH_SET_LINK);
> > + check(err);
> >
> > /* Check flags are masked correctly */
> > - instr = create_branch(&instr, addr, 0xFFFFFFFC);
> > + err = create_branch(&instr, &instr, addr, 0xFFFFFFFC);
> > check(instr_is_branch_to_addr(&instr, addr));
> > check(instr == 0x48000000);
> > }
> > @@ -480,16 +484,19 @@ static void __init test_create_function_call(void)
> > {
> > unsigned int *iptr;
> > unsigned long dest;
> > + unsigned int instr;
> >
> > /* Check we can create a function call */
> > iptr = (unsigned int *)ppc_function_entry(test_trampoline);
> > dest = ppc_function_entry(test_create_function_call);
> > - patch_instruction(iptr, create_branch(iptr, dest, BRANCH_SET_LINK));
> > + create_branch(&instr, iptr, dest, BRANCH_SET_LINK);
> > + patch_instruction(iptr, instr);
>
>
> Are we sure that `create_branch()` would always succeed here to do
> patch_instruction() ?
>
>
> > check(instr_is_branch_to_addr(iptr, dest));
> > }
> >
> > static void __init test_branch_bform(void)
> > {
> > + int err;
> > unsigned long addr;
> > unsigned int *iptr, instr, flags;
> >
> > @@ -525,35 +532,35 @@ static void __init test_branch_bform(void)
> > flags = 0x3ff000 | BRANCH_SET_LINK;
> >
> > /* Branch to self */
> > - instr = create_cond_branch(iptr, addr, flags);
> > + err = create_cond_branch(&instr, iptr, addr, flags);
> > check(instr_is_branch_to_addr(&instr, addr));
> >
> > /* Branch to self - 0x100 */
> > - instr = create_cond_branch(iptr, addr - 0x100, flags);
> > + err = create_cond_branch(&instr, iptr, addr - 0x100, flags);
> > check(instr_is_branch_to_addr(&instr, addr - 0x100));
> >
> > /* Branch to self + 0x100 */
> > - instr = create_cond_branch(iptr, addr + 0x100, flags);
> > + err = create_cond_branch(&instr, iptr, addr + 0x100, flags);
> > check(instr_is_branch_to_addr(&instr, addr + 0x100));
> >
> > /* Maximum relative negative offset, - 32 KB */
> > - instr = create_cond_branch(iptr, addr - 0x8000, flags);
> > + err = create_cond_branch(&instr, iptr, addr - 0x8000, flags);
> > check(instr_is_branch_to_addr(&instr, addr - 0x8000));
> >
> > /* Out of range relative negative offset, - 32 KB + 4*/
> > - instr = create_cond_branch(iptr, addr - 0x8004, flags);
> > - check(instr == 0);
> > + err = create_cond_branch(&instr, iptr, addr - 0x8004, flags);
> > + check(err);
> >
> > /* Out of range relative positive offset, + 32 KB */
> > - instr = create_cond_branch(iptr, addr + 0x8000, flags);
> > - check(instr == 0);
> > + err = create_cond_branch(&instr, iptr, addr + 0x8000, flags);
> > + check(err);
> >
> > /* Unaligned target */
> > - instr = create_cond_branch(iptr, addr + 3, flags);
> > - check(instr == 0);
> > + err = create_cond_branch(&instr, iptr, addr + 3, flags);
> > + check(err);
> >
> > /* Check flags are masked correctly */
> > - instr = create_cond_branch(iptr, addr, 0xFFFFFFFC);
> > + err = create_cond_branch(&instr, iptr, addr, 0xFFFFFFFC);
> > check(instr_is_branch_to_addr(&instr, addr));
> > check(instr == 0x43FF0000);
> > }
> > @@ -562,6 +569,7 @@ static void __init test_translate_branch(void)
> > {
> > unsigned long addr;
> > unsigned int *p, *q;
> > + unsigned int instr;
> > void *buf;
> >
> > buf = vmalloc(PAGE_ALIGN(0x2000000 + 1));
> > @@ -575,7 +583,8 @@ static void __init test_translate_branch(void)
> > patch_branch(p, addr, 0);
> > check(instr_is_branch_to_addr(p, addr));
> > q = p + 1;
> > - patch_instruction(q, translate_branch(q, p));
> > + translate_branch(&instr, q, p);
> > + patch_instruction(q, instr);
>
>
> same here and elsewhere in similar such places where we do patch_instruction()
I figured that if the existing code was not checking the return then
we probably did not need to add a check.
>
> -- Bala
>
> > check(instr_is_branch_to_addr(q, addr));
> >
> > /* Maximum negative case, move b . to addr + 32 MB */
> > @@ -583,7 +592,8 @@ static void __init test_translate_branch(void)
> > addr = (unsigned long)p;
> > patch_branch(p, addr, 0);
> > q = buf + 0x2000000;
> > - patch_instruction(q, translate_branch(q, p));
> > + translate_branch(&instr, q, p);
> > + patch_instruction(q, instr);
> > check(instr_is_branch_to_addr(p, addr));
> > check(instr_is_branch_to_addr(q, addr));
> > check(*q == 0x4a000000);
> > @@ -593,7 +603,8 @@ static void __init test_translate_branch(void)
> > addr = (unsigned long)p;
> > patch_branch(p, addr, 0);
> > q = buf + 4;
> > - patch_instruction(q, translate_branch(q, p));
> > + translate_branch(&instr, q, p);
> > + patch_instruction(q, instr);
> > check(instr_is_branch_to_addr(p, addr));
> > check(instr_is_branch_to_addr(q, addr));
> > check(*q == 0x49fffffc);
> > @@ -603,7 +614,8 @@ static void __init test_translate_branch(void)
> > addr = 0x1000000 + (unsigned long)buf;
> > patch_branch(p, addr, BRANCH_SET_LINK);
> > q = buf + 0x1400000;
> > - patch_instruction(q, translate_branch(q, p));
> > + translate_branch(&instr, q, p);
> > + patch_instruction(q, instr);
> > check(instr_is_branch_to_addr(p, addr));
> > check(instr_is_branch_to_addr(q, addr));
> >
> > @@ -612,7 +624,8 @@ static void __init test_translate_branch(void)
> > addr = 0x2000000 + (unsigned long)buf;
> > patch_branch(p, addr, 0);
> > q = buf + 4;
> > - patch_instruction(q, translate_branch(q, p));
> > + translate_branch(&instr, q, p);
> > + patch_instruction(q, instr);
> > check(instr_is_branch_to_addr(p, addr));
> > check(instr_is_branch_to_addr(q, addr));
> >
> > @@ -622,18 +635,22 @@ static void __init test_translate_branch(void)
> > /* Simple case, branch to self moved a little */
> > p = buf;
> > addr = (unsigned long)p;
> > - patch_instruction(p, create_cond_branch(p, addr, 0));
> > + create_cond_branch(&instr, p, addr, 0);
> > + patch_instruction(p, instr);
> > check(instr_is_branch_to_addr(p, addr));
> > q = p + 1;
> > - patch_instruction(q, translate_branch(q, p));
> > + translate_branch(&instr, q, p);
> > + patch_instruction(q, instr);
> > check(instr_is_branch_to_addr(q, addr));
> >
> > /* Maximum negative case, move b . to addr + 32 KB */
> > p = buf;
> > addr = (unsigned long)p;
> > - patch_instruction(p, create_cond_branch(p, addr, 0xFFFFFFFC));
> > + create_cond_branch(&instr, p, addr, 0xFFFFFFFC);
> > + patch_instruction(p, instr);
> > q = buf + 0x8000;
> > - patch_instruction(q, translate_branch(q, p));
> > + translate_branch(&instr, q, p);
> > + patch_instruction(q, instr);
> > check(instr_is_branch_to_addr(p, addr));
> > check(instr_is_branch_to_addr(q, addr));
> > check(*q == 0x43ff8000);
> > @@ -641,9 +658,11 @@ static void __init test_translate_branch(void)
> > /* Maximum positive case, move x to x - 32 KB + 4 */
> > p = buf + 0x8000;
> > addr = (unsigned long)p;
> > - patch_instruction(p, create_cond_branch(p, addr, 0xFFFFFFFC));
> > + create_cond_branch(&instr, p, addr, 0xFFFFFFFC);
> > + patch_instruction(p, instr);
> > q = buf + 4;
> > - patch_instruction(q, translate_branch(q, p));
> > + translate_branch(&instr, q, p);
> > + patch_instruction(q, instr);
> > check(instr_is_branch_to_addr(p, addr));
> > check(instr_is_branch_to_addr(q, addr));
> > check(*q == 0x43ff7ffc);
> > @@ -651,18 +670,22 @@ static void __init test_translate_branch(void)
> > /* Jump to x + 12 KB moved to x + 20 KB */
> > p = buf;
> > addr = 0x3000 + (unsigned long)buf;
> > - patch_instruction(p, create_cond_branch(p, addr, BRANCH_SET_LINK));
> > + create_cond_branch(&instr, p, addr, BRANCH_SET_LINK);
> > + patch_instruction(p, instr);
> > q = buf + 0x5000;
> > - patch_instruction(q, translate_branch(q, p));
> > + translate_branch(&instr, q, p);
> > + patch_instruction(q, instr);
> > check(instr_is_branch_to_addr(p, addr));
> > check(instr_is_branch_to_addr(q, addr));
> >
> > /* Jump to x + 8 KB moved to x - 8 KB + 4 */
> > p = buf + 0x2000;
> > addr = 0x4000 + (unsigned long)buf;
> > - patch_instruction(p, create_cond_branch(p, addr, 0));
> > + create_cond_branch(&instr, p, addr, 0);
> > + patch_instruction(p, instr);
> > q = buf + 4;
> > - patch_instruction(q, translate_branch(q, p));
> > + translate_branch(&instr, q, p);
> > + patch_instruction(q, instr);
> > check(instr_is_branch_to_addr(p, addr));
> > check(instr_is_branch_to_addr(q, addr));
> >
> > diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-
> > fixups.c
> > index 4ba634b89ce5..b129d7b4e7dd 100644
> > --- a/arch/powerpc/lib/feature-fixups.c
> > +++ b/arch/powerpc/lib/feature-fixups.c
> > @@ -44,6 +44,7 @@ static unsigned int *calc_addr(struct fixup_entry *fcur,
> > long offset)
> > static int patch_alt_instruction(unsigned int *src, unsigned int *dest,
> > unsigned int *alt_start, unsigned int
> > *alt_end)
> > {
> > + int err;
> > unsigned int instr;
> >
> > instr = *src;
> > @@ -53,8 +54,8 @@ static int patch_alt_instruction(unsigned int *src,
> > unsigned int *dest,
> >
> > /* Branch within the section doesn't need translating */
> > if (target < alt_start || target > alt_end) {
> > - instr = translate_branch(dest, src);
> > - if (!instr)
> > + err = translate_branch(&instr, dest, src);
> > + if (err)
> > return 1;
> > }
> > }
>
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 04/21] powerpc: Use a macro for creating instructions from u32s
2020-04-06 8:09 ` [PATCH v5 04/21] powerpc: Use a macro for creating instructions from u32s Jordan Niethe
@ 2020-04-07 6:40 ` Balamuruhan S
2020-04-07 8:27 ` Jordan Niethe
0 siblings, 1 reply; 71+ messages in thread
From: Balamuruhan S @ 2020-04-07 6:40 UTC (permalink / raw)
To: Jordan Niethe, linuxppc-dev; +Cc: alistair, npiggin, dja
On Mon, 2020-04-06 at 18:09 +1000, Jordan Niethe wrote:
> In preparation for instructions having a more complex data type start
> using a macro, ppc_inst(), for making an instruction out of a u32. A
> macro is used so that instructions can be used as initializer elements.
> Currently this does nothing, but it will allow for creating a data type
> that can represent prefixed instructions.
>
> Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> ---
> v4: New to series
> v5: - Rename PPC_INST() -> ppc_inst().
> - Use on epapr_paravirt.c, kgdb.c
> ---
> arch/powerpc/include/asm/code-patching.h | 3 +-
> arch/powerpc/include/asm/inst.h | 11 +++++
> arch/powerpc/kernel/align.c | 1 +
> arch/powerpc/kernel/epapr_paravirt.c | 5 ++-
> arch/powerpc/kernel/hw_breakpoint.c | 3 +-
> arch/powerpc/kernel/jump_label.c | 3 +-
> arch/powerpc/kernel/kgdb.c | 5 ++-
> arch/powerpc/kernel/kprobes.c | 5 ++-
> arch/powerpc/kernel/module_64.c | 3 +-
> arch/powerpc/kernel/optprobes.c | 31 ++++++-------
> arch/powerpc/kernel/security.c | 9 ++--
> arch/powerpc/kernel/trace/ftrace.c | 25 ++++++-----
> arch/powerpc/kernel/uprobes.c | 1 +
> arch/powerpc/kvm/emulate_loadstore.c | 2 +-
> arch/powerpc/lib/code-patching.c | 57 ++++++++++++------------
> arch/powerpc/lib/feature-fixups.c | 39 ++++++++--------
> arch/powerpc/lib/test_emulate_step.c | 39 ++++++++--------
> arch/powerpc/xmon/xmon.c | 7 +--
> 18 files changed, 138 insertions(+), 111 deletions(-)
> create mode 100644 arch/powerpc/include/asm/inst.h
>
> diff --git a/arch/powerpc/include/asm/code-patching.h
> b/arch/powerpc/include/asm/code-patching.h
> index 351dda7215b6..48e021957ee5 100644
> --- a/arch/powerpc/include/asm/code-patching.h
> +++ b/arch/powerpc/include/asm/code-patching.h
> @@ -11,6 +11,7 @@
> #include <linux/string.h>
> #include <linux/kallsyms.h>
> #include <asm/asm-compat.h>
> +#include <asm/inst.h>
>
> /* Flags for create_branch:
> * "b" == create_branch(addr, target, 0);
> @@ -48,7 +49,7 @@ static inline int patch_branch_site(s32 *site, unsigned
> long target, int flags)
> static inline int modify_instruction(unsigned int *addr, unsigned int clr,
> unsigned int set)
> {
> - return patch_instruction(addr, (*addr & ~clr) | set);
> + return patch_instruction(addr, ppc_inst((*addr & ~clr) | set));
> }
>
> static inline int modify_instruction_site(s32 *site, unsigned int clr,
> unsigned int set)
> diff --git a/arch/powerpc/include/asm/inst.h
> b/arch/powerpc/include/asm/inst.h
> new file mode 100644
> index 000000000000..5298ba33b6e5
> --- /dev/null
> +++ b/arch/powerpc/include/asm/inst.h
> @@ -0,0 +1,11 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +#ifndef _ASM_INST_H
> +#define _ASM_INST_H
> +
> +/*
> + * Instruction data type for POWER
> + */
> +
> +#define ppc_inst(x) (x)
> +
> +#endif /* _ASM_INST_H */
> diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
> index 92045ed64976..86e9bf62f18c 100644
> --- a/arch/powerpc/kernel/align.c
> +++ b/arch/powerpc/kernel/align.c
> @@ -24,6 +24,7 @@
> #include <asm/disassemble.h>
> #include <asm/cpu_has_feature.h>
> #include <asm/sstep.h>
> +#include <asm/inst.h>
>
> struct aligninfo {
> unsigned char len;
> diff --git a/arch/powerpc/kernel/epapr_paravirt.c
> b/arch/powerpc/kernel/epapr_paravirt.c
> index 9d32158ce36f..c53e863fb484 100644
> --- a/arch/powerpc/kernel/epapr_paravirt.c
> +++ b/arch/powerpc/kernel/epapr_paravirt.c
> @@ -11,6 +11,7 @@
> #include <asm/cacheflush.h>
> #include <asm/code-patching.h>
> #include <asm/machdep.h>
> +#include <asm/inst.h>
>
> #if !defined(CONFIG_64BIT) || defined(CONFIG_PPC_BOOK3E_64)
> extern void epapr_ev_idle(void);
> @@ -37,9 +38,9 @@ static int __init early_init_dt_scan_epapr(unsigned long
> node,
>
> for (i = 0; i < (len / 4); i++) {
> u32 inst = be32_to_cpu(insts[i]);
> - patch_instruction(epapr_hypercall_start + i, inst);
> + patch_instruction(epapr_hypercall_start + i, ppc_inst(inst));
> #if !defined(CONFIG_64BIT) || defined(CONFIG_PPC_BOOK3E_64)
> - patch_instruction(epapr_ev_idle_start + i, inst);
> + patch_instruction(epapr_ev_idle_start + i, ppc_inst(inst));
can we do it once while assigning inst ?
u32 inst = ppc_inst(be32_to_cpu(insts[i]));
-- Bala
> #endif
> }
>
> diff --git a/arch/powerpc/kernel/hw_breakpoint.c
> b/arch/powerpc/kernel/hw_breakpoint.c
> index 2462cd7c565c..79f51f182a83 100644
> --- a/arch/powerpc/kernel/hw_breakpoint.c
> +++ b/arch/powerpc/kernel/hw_breakpoint.c
> @@ -24,6 +24,7 @@
> #include <asm/debug.h>
> #include <asm/debugfs.h>
> #include <asm/hvcall.h>
> +#include <asm/inst.h>
> #include <linux/uaccess.h>
>
> /*
> @@ -243,7 +244,7 @@ dar_range_overlaps(unsigned long dar, int size, struct
> arch_hw_breakpoint *info)
> static bool stepping_handler(struct pt_regs *regs, struct perf_event *bp,
> struct arch_hw_breakpoint *info)
> {
> - unsigned int instr = 0;
> + unsigned int instr = ppc_inst(0);
> int ret, type, size;
> struct instruction_op op;
> unsigned long addr = info->address;
> diff --git a/arch/powerpc/kernel/jump_label.c
> b/arch/powerpc/kernel/jump_label.c
> index ca37702bde97..daa4afce7ec8 100644
> --- a/arch/powerpc/kernel/jump_label.c
> +++ b/arch/powerpc/kernel/jump_label.c
> @@ -6,6 +6,7 @@
> #include <linux/kernel.h>
> #include <linux/jump_label.h>
> #include <asm/code-patching.h>
> +#include <asm/inst.h>
>
> void arch_jump_label_transform(struct jump_entry *entry,
> enum jump_label_type type)
> @@ -15,5 +16,5 @@ void arch_jump_label_transform(struct jump_entry *entry,
> if (type == JUMP_LABEL_JMP)
> patch_branch(addr, entry->target, 0);
> else
> - patch_instruction(addr, PPC_INST_NOP);
> + patch_instruction(addr, ppc_inst(PPC_INST_NOP));
> }
> diff --git a/arch/powerpc/kernel/kgdb.c b/arch/powerpc/kernel/kgdb.c
> index 7dd55eb1259d..a6b38a19133f 100644
> --- a/arch/powerpc/kernel/kgdb.c
> +++ b/arch/powerpc/kernel/kgdb.c
> @@ -26,6 +26,7 @@
> #include <asm/debug.h>
> #include <asm/code-patching.h>
> #include <linux/slab.h>
> +#include <asm/inst.h>
>
> /*
> * This table contains the mapping between PowerPC hardware trap types, and
> @@ -424,7 +425,7 @@ int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
> if (err)
> return err;
>
> - err = patch_instruction(addr, BREAK_INSTR);
> + err = patch_instruction(addr, ppc_inst(BREAK_INSTR));
> if (err)
> return -EFAULT;
>
> @@ -439,7 +440,7 @@ int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
> unsigned int instr = *(unsigned int *)bpt->saved_instr;
> unsigned int *addr = (unsigned int *)bpt->bpt_addr;
>
> - err = patch_instruction(addr, instr);
> + err = patch_instruction(addr, ppc_inst(instr));
> if (err)
> return -EFAULT;
>
> diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
> index 2d27ec4feee4..a1a3686f41c6 100644
> --- a/arch/powerpc/kernel/kprobes.c
> +++ b/arch/powerpc/kernel/kprobes.c
> @@ -23,6 +23,7 @@
> #include <asm/cacheflush.h>
> #include <asm/sstep.h>
> #include <asm/sections.h>
> +#include <asm/inst.h>
> #include <linux/uaccess.h>
>
> DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
> @@ -138,13 +139,13 @@ NOKPROBE_SYMBOL(arch_prepare_kprobe);
>
> void arch_arm_kprobe(struct kprobe *p)
> {
> - patch_instruction(p->addr, BREAKPOINT_INSTRUCTION);
> + patch_instruction(p->addr, ppc_inst(BREAKPOINT_INSTRUCTION));
> }
> NOKPROBE_SYMBOL(arch_arm_kprobe);
>
> void arch_disarm_kprobe(struct kprobe *p)
> {
> - patch_instruction(p->addr, p->opcode);
> + patch_instruction(p->addr, ppc_inst(p->opcode));
> }
> NOKPROBE_SYMBOL(arch_disarm_kprobe);
>
> diff --git a/arch/powerpc/kernel/module_64.c
> b/arch/powerpc/kernel/module_64.c
> index 007606a48fd9..7fd6b29edcb2 100644
> --- a/arch/powerpc/kernel/module_64.c
> +++ b/arch/powerpc/kernel/module_64.c
> @@ -20,6 +20,7 @@
> #include <linux/sort.h>
> #include <asm/setup.h>
> #include <asm/sections.h>
> +#include <asm/inst.h>
>
> /* FIXME: We don't do .init separately. To do this, we'd need to have
> a separate r2 value in the init and core section, and stub between
> @@ -506,7 +507,7 @@ static int restore_r2(const char *name, u32 *instruction,
> struct module *me)
> * "link" branches and they don't return, so they don't need the r2
> * restore afterwards.
> */
> - if (!instr_is_relative_link_branch(*prev_insn))
> + if (!instr_is_relative_link_branch(ppc_inst(*prev_insn)))
> return 1;
>
> if (*instruction != PPC_INST_NOP) {
> diff --git a/arch/powerpc/kernel/optprobes.c
> b/arch/powerpc/kernel/optprobes.c
> index 445b3dad82dc..3b33ebf18859 100644
> --- a/arch/powerpc/kernel/optprobes.c
> +++ b/arch/powerpc/kernel/optprobes.c
> @@ -16,6 +16,7 @@
> #include <asm/code-patching.h>
> #include <asm/sstep.h>
> #include <asm/ppc-opcode.h>
> +#include <asm/inst.h>
>
> #define TMPL_CALL_HDLR_IDX \
> (optprobe_template_call_handler - optprobe_template_entry)
> @@ -147,13 +148,13 @@ void arch_remove_optimized_kprobe(struct
> optimized_kprobe *op)
> void patch_imm32_load_insns(unsigned int val, kprobe_opcode_t *addr)
> {
> /* addis r4,0,(insn)@h */
> - patch_instruction(addr, PPC_INST_ADDIS | ___PPC_RT(4) |
> - ((val >> 16) & 0xffff));
> + patch_instruction(addr, ppc_inst(PPC_INST_ADDIS | ___PPC_RT(4) |
> + ((val >> 16) & 0xffff)));
> addr++;
>
> /* ori r4,r4,(insn)@l */
> - patch_instruction(addr, PPC_INST_ORI | ___PPC_RA(4) |
> - ___PPC_RS(4) | (val & 0xffff));
> + patch_instruction(addr, ppc_inst(PPC_INST_ORI | ___PPC_RA(4) |
> + ___PPC_RS(4) | (val & 0xffff)));
> }
>
> /*
> @@ -163,28 +164,28 @@ void patch_imm32_load_insns(unsigned int val,
> kprobe_opcode_t *addr)
> void patch_imm64_load_insns(unsigned long val, kprobe_opcode_t *addr)
> {
> /* lis r3,(op)@highest */
> - patch_instruction(addr, PPC_INST_ADDIS | ___PPC_RT(3) |
> - ((val >> 48) & 0xffff));
> + patch_instruction(addr, ppc_inst(PPC_INST_ADDIS | ___PPC_RT(3) |
> + ((val >> 48) & 0xffff)));
> addr++;
>
> /* ori r3,r3,(op)@higher */
> - patch_instruction(addr, PPC_INST_ORI | ___PPC_RA(3) |
> - ___PPC_RS(3) | ((val >> 32) & 0xffff));
> + patch_instruction(addr, ppc_inst(PPC_INST_ORI | ___PPC_RA(3) |
> + ___PPC_RS(3) | ((val >> 32) & 0xffff)));
> addr++;
>
> /* rldicr r3,r3,32,31 */
> - patch_instruction(addr, PPC_INST_RLDICR | ___PPC_RA(3) |
> - ___PPC_RS(3) | __PPC_SH64(32) | __PPC_ME64(31));
> + patch_instruction(addr, ppc_inst(PPC_INST_RLDICR | ___PPC_RA(3) |
> + ___PPC_RS(3) | __PPC_SH64(32) | __PPC_ME64(31)));
> addr++;
>
> /* oris r3,r3,(op)@h */
> - patch_instruction(addr, PPC_INST_ORIS | ___PPC_RA(3) |
> - ___PPC_RS(3) | ((val >> 16) & 0xffff));
> + patch_instruction(addr, ppc_inst(PPC_INST_ORIS | ___PPC_RA(3) |
> + ___PPC_RS(3) | ((val >> 16) & 0xffff)));
> addr++;
>
> /* ori r3,r3,(op)@l */
> - patch_instruction(addr, PPC_INST_ORI | ___PPC_RA(3) |
> - ___PPC_RS(3) | (val & 0xffff));
> + patch_instruction(addr, ppc_inst(PPC_INST_ORI | ___PPC_RA(3) |
> + ___PPC_RS(3) | (val & 0xffff)));
> }
>
> int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe
> *p)
> @@ -230,7 +231,7 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe
> *op, struct kprobe *p)
> size = (TMPL_END_IDX * sizeof(kprobe_opcode_t)) / sizeof(int);
> pr_devel("Copying template to %p, size %lu\n", buff, size);
> for (i = 0; i < size; i++) {
> - rc = patch_instruction(buff + i, *(optprobe_template_entry +
> i));
> + rc = patch_instruction(buff + i,
> ppc_inst(*(optprobe_template_entry + i)));
> if (rc < 0)
> goto error;
> }
> diff --git a/arch/powerpc/kernel/security.c b/arch/powerpc/kernel/security.c
> index bd70f5be1c27..81a288b1a603 100644
> --- a/arch/powerpc/kernel/security.c
> +++ b/arch/powerpc/kernel/security.c
> @@ -14,6 +14,7 @@
> #include <asm/debugfs.h>
> #include <asm/security_features.h>
> #include <asm/setup.h>
> +#include <asm/inst.h>
>
>
> u64 powerpc_security_features __read_mostly = SEC_FTR_DEFAULT;
> @@ -403,9 +404,9 @@ static void toggle_count_cache_flush(bool enable)
> enable = false;
>
> if (!enable) {
> - patch_instruction_site(&patch__call_flush_count_cache,
> PPC_INST_NOP);
> + patch_instruction_site(&patch__call_flush_count_cache,
> ppc_inst(PPC_INST_NOP));
> #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
> - patch_instruction_site(&patch__call_kvm_flush_link_stack,
> PPC_INST_NOP);
> + patch_instruction_site(&patch__call_kvm_flush_link_stack,
> ppc_inst(PPC_INST_NOP));
> #endif
> pr_info("link-stack-flush: software flush disabled.\n");
> link_stack_flush_enabled = false;
> @@ -428,7 +429,7 @@ static void toggle_count_cache_flush(bool enable)
>
> // If we just need to flush the link stack, patch an early return
> if (!security_ftr_enabled(SEC_FTR_FLUSH_COUNT_CACHE)) {
> - patch_instruction_site(&patch__flush_link_stack_return,
> PPC_INST_BLR);
> + patch_instruction_site(&patch__flush_link_stack_return,
> ppc_inst(PPC_INST_BLR));
> no_count_cache_flush();
> return;
> }
> @@ -439,7 +440,7 @@ static void toggle_count_cache_flush(bool enable)
> return;
> }
>
> - patch_instruction_site(&patch__flush_count_cache_return, PPC_INST_BLR);
> + patch_instruction_site(&patch__flush_count_cache_return,
> ppc_inst(PPC_INST_BLR));
> count_cache_flush_type = COUNT_CACHE_FLUSH_HW;
> pr_info("count-cache-flush: hardware assisted flush sequence
> enabled\n");
> }
> diff --git a/arch/powerpc/kernel/trace/ftrace.c
> b/arch/powerpc/kernel/trace/ftrace.c
> index 4dcb379133f8..47233e671c18 100644
> --- a/arch/powerpc/kernel/trace/ftrace.c
> +++ b/arch/powerpc/kernel/trace/ftrace.c
> @@ -27,6 +27,7 @@
> #include <asm/code-patching.h>
> #include <asm/ftrace.h>
> #include <asm/syscall.h>
> +#include <asm/inst.h>
>
>
> #ifdef CONFIG_DYNAMIC_FTRACE
> @@ -161,7 +162,7 @@ __ftrace_make_nop(struct module *mod,
>
> #ifdef CONFIG_MPROFILE_KERNEL
> /* When using -mkernel_profile there is no load to jump over */
> - pop = PPC_INST_NOP;
> + pop = ppc_inst(PPC_INST_NOP);
>
> if (probe_kernel_read(&op, (void *)(ip - 4), 4)) {
> pr_err("Fetching instruction at %lx failed.\n", ip - 4);
> @@ -169,7 +170,7 @@ __ftrace_make_nop(struct module *mod,
> }
>
> /* We expect either a mflr r0, or a std r0, LRSAVE(r1) */
> - if (op != PPC_INST_MFLR && op != PPC_INST_STD_LR) {
> + if (op != ppc_inst(PPC_INST_MFLR) && op != ppc_inst(PPC_INST_STD_LR)) {
> pr_err("Unexpected instruction %08x around bl _mcount\n", op);
> return -EINVAL;
> }
> @@ -188,7 +189,7 @@ __ftrace_make_nop(struct module *mod,
> * Use a b +8 to jump over the load.
> */
>
> - pop = PPC_INST_BRANCH | 8; /* b +8 */
> + pop = ppc_inst(PPC_INST_BRANCH | 8); /* b +8 */
>
> /*
> * Check what is in the next instruction. We can see ld r2,40(r1), but
> @@ -199,7 +200,7 @@ __ftrace_make_nop(struct module *mod,
> return -EFAULT;
> }
>
> - if (op != PPC_INST_LD_TOC) {
> + if (op != ppc_inst(PPC_INST_LD_TOC)) {
> pr_err("Expected %08x found %08x\n", PPC_INST_LD_TOC, op);
> return -EINVAL;
> }
> @@ -275,7 +276,7 @@ __ftrace_make_nop(struct module *mod,
> return -EINVAL;
> }
>
> - op = PPC_INST_NOP;
> + op = ppc_inst(PPC_INST_NOP);
>
> if (patch_instruction((unsigned int *)ip, op))
> return -EPERM;
> @@ -420,7 +421,7 @@ static int __ftrace_make_nop_kernel(struct dyn_ftrace
> *rec, unsigned long addr)
> }
> }
>
> - if (patch_instruction((unsigned int *)ip, PPC_INST_NOP)) {
> + if (patch_instruction((unsigned int *)ip, ppc_inst(PPC_INST_NOP))) {
> pr_err("Patching NOP failed.\n");
> return -EPERM;
> }
> @@ -442,7 +443,7 @@ int ftrace_make_nop(struct module *mod,
> if (test_24bit_addr(ip, addr)) {
> /* within range */
> old = ftrace_call_replace(ip, addr, 1);
> - new = PPC_INST_NOP;
> + new = ppc_inst(PPC_INST_NOP);
> return ftrace_modify_code(ip, old, new);
> } else if (core_kernel_text(ip))
> return __ftrace_make_nop_kernel(rec, addr);
> @@ -496,7 +497,7 @@ expected_nop_sequence(void *ip, unsigned int op0,
> unsigned int op1)
> * The load offset is different depending on the ABI. For simplicity
> * just mask it out when doing the compare.
> */
> - if ((op0 != 0x48000008) || ((op1 & 0xffff0000) != 0xe8410000))
> + if ((op0 != ppc_inst(0x48000008)) || ((op1 & 0xffff0000) !=
> 0xe8410000))
> return 0;
> return 1;
> }
> @@ -505,7 +506,7 @@ static int
> expected_nop_sequence(void *ip, unsigned int op0, unsigned int op1)
> {
> /* look for patched "NOP" on ppc64 with -mprofile-kernel */
> - if (op0 != PPC_INST_NOP)
> + if (op0 != ppc_inst(PPC_INST_NOP))
> return 0;
> return 1;
> }
> @@ -588,7 +589,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long
> addr)
> return -EFAULT;
>
> /* It should be pointing to a nop */
> - if (op != PPC_INST_NOP) {
> + if (op != ppc_inst(PPC_INST_NOP)) {
> pr_err("Expected NOP but have %x\n", op);
> return -EINVAL;
> }
> @@ -645,7 +646,7 @@ static int __ftrace_make_call_kernel(struct dyn_ftrace
> *rec, unsigned long addr)
> return -EFAULT;
> }
>
> - if (op != PPC_INST_NOP) {
> + if (op != ppc_inst(PPC_INST_NOP)) {
> pr_err("Unexpected call sequence at %p: %x\n", ip, op);
> return -EINVAL;
> }
> @@ -676,7 +677,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned
> long addr)
> */
> if (test_24bit_addr(ip, addr)) {
> /* within range */
> - old = PPC_INST_NOP;
> + old = ppc_inst(PPC_INST_NOP);
> new = ftrace_call_replace(ip, addr, 1);
> return ftrace_modify_code(ip, old, new);
> } else if (core_kernel_text(ip))
> diff --git a/arch/powerpc/kernel/uprobes.c b/arch/powerpc/kernel/uprobes.c
> index 1cfef0e5fec5..31c870287f2b 100644
> --- a/arch/powerpc/kernel/uprobes.c
> +++ b/arch/powerpc/kernel/uprobes.c
> @@ -14,6 +14,7 @@
> #include <linux/kdebug.h>
>
> #include <asm/sstep.h>
> +#include <asm/inst.h>
>
> #define UPROBE_TRAP_NR UINT_MAX
>
> diff --git a/arch/powerpc/kvm/emulate_loadstore.c
> b/arch/powerpc/kvm/emulate_loadstore.c
> index 1139bc56e004..135d0e686622 100644
> --- a/arch/powerpc/kvm/emulate_loadstore.c
> +++ b/arch/powerpc/kvm/emulate_loadstore.c
> @@ -95,7 +95,7 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu)
>
> emulated = EMULATE_FAIL;
> vcpu->arch.regs.msr = vcpu->arch.shared->msr;
> - if (analyse_instr(&op, &vcpu->arch.regs, inst) == 0) {
> + if (analyse_instr(&op, &vcpu->arch.regs, ppc_inst(inst)) == 0) {
> int type = op.type & INSTR_TYPE_MASK;
> int size = GETSIZE(op.type);
>
> diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-
> patching.c
> index 4af564aeedf1..fdf0d6ea3575 100644
> --- a/arch/powerpc/lib/code-patching.c
> +++ b/arch/powerpc/lib/code-patching.c
> @@ -17,6 +17,7 @@
> #include <asm/page.h>
> #include <asm/code-patching.h>
> #include <asm/setup.h>
> +#include <asm/inst.h>
>
> static int __patch_instruction(unsigned int *exec_addr, unsigned int instr,
> unsigned int *patch_addr)
> @@ -413,37 +414,37 @@ static void __init test_branch_iform(void)
> addr = (unsigned long)&instr;
>
> /* The simplest case, branch to self, no flags */
> - check(instr_is_branch_iform(0x48000000));
> + check(instr_is_branch_iform(ppc_inst(0x48000000)));
> /* All bits of target set, and flags */
> - check(instr_is_branch_iform(0x4bffffff));
> + check(instr_is_branch_iform(ppc_inst(0x4bffffff)));
> /* High bit of opcode set, which is wrong */
> - check(!instr_is_branch_iform(0xcbffffff));
> + check(!instr_is_branch_iform(ppc_inst(0xcbffffff)));
> /* Middle bits of opcode set, which is wrong */
> - check(!instr_is_branch_iform(0x7bffffff));
> + check(!instr_is_branch_iform(ppc_inst(0x7bffffff)));
>
> /* Simplest case, branch to self with link */
> - check(instr_is_branch_iform(0x48000001));
> + check(instr_is_branch_iform(ppc_inst(0x48000001)));
> /* All bits of targets set */
> - check(instr_is_branch_iform(0x4bfffffd));
> + check(instr_is_branch_iform(ppc_inst(0x4bfffffd)));
> /* Some bits of targets set */
> - check(instr_is_branch_iform(0x4bff00fd));
> + check(instr_is_branch_iform(ppc_inst(0x4bff00fd)));
> /* Must be a valid branch to start with */
> - check(!instr_is_branch_iform(0x7bfffffd));
> + check(!instr_is_branch_iform(ppc_inst(0x7bfffffd)));
>
> /* Absolute branch to 0x100 */
> - instr = 0x48000103;
> + instr = ppc_inst(0x48000103);
> check(instr_is_branch_to_addr(&instr, 0x100));
> /* Absolute branch to 0x420fc */
> - instr = 0x480420ff;
> + instr = ppc_inst(0x480420ff);
> check(instr_is_branch_to_addr(&instr, 0x420fc));
> /* Maximum positive relative branch, + 20MB - 4B */
> - instr = 0x49fffffc;
> + instr = ppc_inst(0x49fffffc);
> check(instr_is_branch_to_addr(&instr, addr + 0x1FFFFFC));
> /* Smallest negative relative branch, - 4B */
> - instr = 0x4bfffffc;
> + instr = ppc_inst(0x4bfffffc);
> check(instr_is_branch_to_addr(&instr, addr - 4));
> /* Largest negative relative branch, - 32 MB */
> - instr = 0x4a000000;
> + instr = ppc_inst(0x4a000000);
> check(instr_is_branch_to_addr(&instr, addr - 0x2000000));
>
> /* Branch to self, with link */
> @@ -477,7 +478,7 @@ static void __init test_branch_iform(void)
> /* Check flags are masked correctly */
> err = create_branch(&instr, &instr, addr, 0xFFFFFFFC);
> check(instr_is_branch_to_addr(&instr, addr));
> - check(instr == 0x48000000);
> + check(instr == ppc_inst(0x48000000));
> }
>
> static void __init test_create_function_call(void)
> @@ -504,28 +505,28 @@ static void __init test_branch_bform(void)
> addr = (unsigned long)iptr;
>
> /* The simplest case, branch to self, no flags */
> - check(instr_is_branch_bform(0x40000000));
> + check(instr_is_branch_bform(ppc_inst(0x40000000)));
> /* All bits of target set, and flags */
> - check(instr_is_branch_bform(0x43ffffff));
> + check(instr_is_branch_bform(ppc_inst(0x43ffffff)));
> /* High bit of opcode set, which is wrong */
> - check(!instr_is_branch_bform(0xc3ffffff));
> + check(!instr_is_branch_bform(ppc_inst(0xc3ffffff)));
> /* Middle bits of opcode set, which is wrong */
> - check(!instr_is_branch_bform(0x7bffffff));
> + check(!instr_is_branch_bform(ppc_inst(0x7bffffff)));
>
> /* Absolute conditional branch to 0x100 */
> - instr = 0x43ff0103;
> + instr = ppc_inst(0x43ff0103);
> check(instr_is_branch_to_addr(&instr, 0x100));
> /* Absolute conditional branch to 0x20fc */
> - instr = 0x43ff20ff;
> + instr = ppc_inst(0x43ff20ff);
> check(instr_is_branch_to_addr(&instr, 0x20fc));
> /* Maximum positive relative conditional branch, + 32 KB - 4B */
> - instr = 0x43ff7ffc;
> + instr = ppc_inst(0x43ff7ffc);
> check(instr_is_branch_to_addr(&instr, addr + 0x7FFC));
> /* Smallest negative relative conditional branch, - 4B */
> - instr = 0x43fffffc;
> + instr = ppc_inst(0x43fffffc);
> check(instr_is_branch_to_addr(&instr, addr - 4));
> /* Largest negative relative conditional branch, - 32 KB */
> - instr = 0x43ff8000;
> + instr = ppc_inst(0x43ff8000);
> check(instr_is_branch_to_addr(&instr, addr - 0x8000));
>
> /* All condition code bits set & link */
> @@ -562,7 +563,7 @@ static void __init test_branch_bform(void)
> /* Check flags are masked correctly */
> err = create_cond_branch(&instr, iptr, addr, 0xFFFFFFFC);
> check(instr_is_branch_to_addr(&instr, addr));
> - check(instr == 0x43FF0000);
> + check(instr == ppc_inst(0x43FF0000));
> }
>
> static void __init test_translate_branch(void)
> @@ -596,7 +597,7 @@ static void __init test_translate_branch(void)
> patch_instruction(q, instr);
> check(instr_is_branch_to_addr(p, addr));
> check(instr_is_branch_to_addr(q, addr));
> - check(*q == 0x4a000000);
> + check(*q == ppc_inst(0x4a000000));
>
> /* Maximum positive case, move x to x - 32 MB + 4 */
> p = buf + 0x2000000;
> @@ -607,7 +608,7 @@ static void __init test_translate_branch(void)
> patch_instruction(q, instr);
> check(instr_is_branch_to_addr(p, addr));
> check(instr_is_branch_to_addr(q, addr));
> - check(*q == 0x49fffffc);
> + check(*q == ppc_inst(0x49fffffc));
>
> /* Jump to x + 16 MB moved to x + 20 MB */
> p = buf;
> @@ -653,7 +654,7 @@ static void __init test_translate_branch(void)
> patch_instruction(q, instr);
> check(instr_is_branch_to_addr(p, addr));
> check(instr_is_branch_to_addr(q, addr));
> - check(*q == 0x43ff8000);
> + check(*q == ppc_inst(0x43ff8000));
>
> /* Maximum positive case, move x to x - 32 KB + 4 */
> p = buf + 0x8000;
> @@ -665,7 +666,7 @@ static void __init test_translate_branch(void)
> patch_instruction(q, instr);
> check(instr_is_branch_to_addr(p, addr));
> check(instr_is_branch_to_addr(q, addr));
> - check(*q == 0x43ff7ffc);
> + check(*q == ppc_inst(0x43ff7ffc));
>
> /* Jump to x + 12 KB moved to x + 20 KB */
> p = buf;
> diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-
> fixups.c
> index b129d7b4e7dd..6e7479b8887a 100644
> --- a/arch/powerpc/lib/feature-fixups.c
> +++ b/arch/powerpc/lib/feature-fixups.c
> @@ -21,6 +21,7 @@
> #include <asm/setup.h>
> #include <asm/security_features.h>
> #include <asm/firmware.h>
> +#include <asm/inst.h>
>
> struct fixup_entry {
> unsigned long mask;
> @@ -89,7 +90,7 @@ static int patch_feature_section(unsigned long value,
> struct fixup_entry *fcur)
> }
>
> for (; dest < end; dest++)
> - raw_patch_instruction(dest, PPC_INST_NOP);
> + raw_patch_instruction(dest, ppc_inst(PPC_INST_NOP));
>
> return 0;
> }
> @@ -146,15 +147,15 @@ static void do_stf_entry_barrier_fixups(enum
> stf_barrier_type types)
>
> pr_devel("patching dest %lx\n", (unsigned long)dest);
>
> - patch_instruction(dest, instrs[0]);
> + patch_instruction(dest, ppc_inst(instrs[0]));
>
> if (types & STF_BARRIER_FALLBACK)
> patch_branch(dest + 1, (unsigned
> long)&stf_barrier_fallback,
> BRANCH_SET_LINK);
> else
> - patch_instruction(dest + 1, instrs[1]);
> + patch_instruction(dest + 1, ppc_inst(instrs[1]));
>
> - patch_instruction(dest + 2, instrs[2]);
> + patch_instruction(dest + 2, ppc_inst(instrs[2]));
> }
>
> printk(KERN_DEBUG "stf-barrier: patched %d entry locations (%s
> barrier)\n", i,
> @@ -207,12 +208,12 @@ static void do_stf_exit_barrier_fixups(enum
> stf_barrier_type types)
>
> pr_devel("patching dest %lx\n", (unsigned long)dest);
>
> - patch_instruction(dest, instrs[0]);
> - patch_instruction(dest + 1, instrs[1]);
> - patch_instruction(dest + 2, instrs[2]);
> - patch_instruction(dest + 3, instrs[3]);
> - patch_instruction(dest + 4, instrs[4]);
> - patch_instruction(dest + 5, instrs[5]);
> + patch_instruction(dest, ppc_inst(instrs[0]));
> + patch_instruction(dest + 1, ppc_inst(instrs[1]));
> + patch_instruction(dest + 2, ppc_inst(instrs[2]));
> + patch_instruction(dest + 3, ppc_inst(instrs[3]));
> + patch_instruction(dest + 4, ppc_inst(instrs[4]));
> + patch_instruction(dest + 5, ppc_inst(instrs[5]));
> }
> printk(KERN_DEBUG "stf-barrier: patched %d exit locations (%s
> barrier)\n", i,
> (types == STF_BARRIER_NONE) ? "no" :
> @@ -260,9 +261,9 @@ void do_rfi_flush_fixups(enum l1d_flush_type types)
>
> pr_devel("patching dest %lx\n", (unsigned long)dest);
>
> - patch_instruction(dest, instrs[0]);
> - patch_instruction(dest + 1, instrs[1]);
> - patch_instruction(dest + 2, instrs[2]);
> + patch_instruction(dest, ppc_inst(instrs[0]));
> + patch_instruction(dest + 1, ppc_inst(instrs[1]));
> + patch_instruction(dest + 2, ppc_inst(instrs[2]));
> }
>
> printk(KERN_DEBUG "rfi-flush: patched %d locations (%s flush)\n", i,
> @@ -295,7 +296,7 @@ void do_barrier_nospec_fixups_range(bool enable, void
> *fixup_start, void *fixup_
> dest = (void *)start + *start;
>
> pr_devel("patching dest %lx\n", (unsigned long)dest);
> - patch_instruction(dest, instr);
> + patch_instruction(dest, ppc_inst(instr));
> }
>
> printk(KERN_DEBUG "barrier-nospec: patched %d locations\n", i);
> @@ -338,8 +339,8 @@ void do_barrier_nospec_fixups_range(bool enable, void
> *fixup_start, void *fixup_
> dest = (void *)start + *start;
>
> pr_devel("patching dest %lx\n", (unsigned long)dest);
> - patch_instruction(dest, instr[0]);
> - patch_instruction(dest + 1, instr[1]);
> + patch_instruction(dest, ppc_inst(instr[0]));
> + patch_instruction(dest + 1, ppc_inst(instr[1]));
> }
>
> printk(KERN_DEBUG "barrier-nospec: patched %d locations\n", i);
> @@ -353,7 +354,7 @@ static void patch_btb_flush_section(long *curr)
> end = (void *)curr + *(curr + 1);
> for (; start < end; start++) {
> pr_devel("patching dest %lx\n", (unsigned long)start);
> - patch_instruction(start, PPC_INST_NOP);
> + patch_instruction(start, ppc_inst(PPC_INST_NOP));
> }
> }
>
> @@ -382,7 +383,7 @@ void do_lwsync_fixups(unsigned long value, void
> *fixup_start, void *fixup_end)
>
> for (; start < end; start++) {
> dest = (void *)start + *start;
> - raw_patch_instruction(dest, PPC_INST_LWSYNC);
> + raw_patch_instruction(dest, ppc_inst(PPC_INST_LWSYNC));
> }
> }
>
> @@ -400,7 +401,7 @@ static void do_final_fixups(void)
> length = (__end_interrupts - _stext) / sizeof(int);
>
> while (length--) {
> - raw_patch_instruction(dest, *src);
> + raw_patch_instruction(dest, ppc_inst(*src));
> src++;
> dest++;
> }
> diff --git a/arch/powerpc/lib/test_emulate_step.c
> b/arch/powerpc/lib/test_emulate_step.c
> index 42347067739c..88b17226a493 100644
> --- a/arch/powerpc/lib/test_emulate_step.c
> +++ b/arch/powerpc/lib/test_emulate_step.c
> @@ -11,6 +11,7 @@
> #include <asm/sstep.h>
> #include <asm/ppc-opcode.h>
> #include <asm/code-patching.h>
> +#include <asm/inst.h>
>
> #define IMM_L(i) ((uintptr_t)(i) & 0xffff)
>
> @@ -18,40 +19,40 @@
> * Defined with TEST_ prefix so it does not conflict with other
> * definitions.
> */
> -#define TEST_LD(r, base, i) (PPC_INST_LD | ___PPC_RT(r) | \
> +#define TEST_LD(r, base, i) ppc_inst(PPC_INST_LD | ___PPC_RT(r) |
> \
> ___PPC_RA(base) | IMM_L(i))
> -#define TEST_LWZ(r, base, i) (PPC_INST_LWZ | ___PPC_RT(r) | \
> +#define TEST_LWZ(r, base, i) ppc_inst(PPC_INST_LWZ | ___PPC_RT(r) |
> \
> ___PPC_RA(base) | IMM_L(i))
> -#define TEST_LWZX(t, a, b) (PPC_INST_LWZX | ___PPC_RT(t) | \
> +#define TEST_LWZX(t, a, b) ppc_inst(PPC_INST_LWZX | ___PPC_RT(t) |
> \
> ___PPC_RA(a) | ___PPC_RB(b))
> -#define TEST_STD(r, base, i) (PPC_INST_STD | ___PPC_RS(r) | \
> +#define TEST_STD(r, base, i) ppc_inst(PPC_INST_STD | ___PPC_RS(r) |
> \
> ___PPC_RA(base) | ((i) & 0xfffc))
> -#define TEST_LDARX(t, a, b, eh) (PPC_INST_LDARX | ___PPC_RT(t) | \
> +#define TEST_LDARX(t, a, b, eh) ppc_inst(PPC_INST_LDARX | ___PPC_RT(t)
> | \
> ___PPC_RA(a) | ___PPC_RB(b) | \
> __PPC_EH(eh))
> -#define TEST_STDCX(s, a, b) (PPC_INST_STDCX | ___PPC_RS(s) | \
> +#define TEST_STDCX(s, a, b) ppc_inst(PPC_INST_STDCX | ___PPC_RS(s) | \
> ___PPC_RA(a) | ___PPC_RB(b))
> -#define TEST_LFSX(t, a, b) (PPC_INST_LFSX | ___PPC_RT(t) | \
> +#define TEST_LFSX(t, a, b) ppc_inst(PPC_INST_LFSX | ___PPC_RT(t) |
> \
> ___PPC_RA(a) | ___PPC_RB(b))
> -#define TEST_STFSX(s, a, b) (PPC_INST_STFSX | ___PPC_RS(s) | \
> +#define TEST_STFSX(s, a, b) ppc_inst(PPC_INST_STFSX | ___PPC_RS(s) | \
> ___PPC_RA(a) | ___PPC_RB(b))
> -#define TEST_LFDX(t, a, b) (PPC_INST_LFDX | ___PPC_RT(t) | \
> +#define TEST_LFDX(t, a, b) ppc_inst(PPC_INST_LFDX | ___PPC_RT(t) |
> \
> ___PPC_RA(a) | ___PPC_RB(b))
> -#define TEST_STFDX(s, a, b) (PPC_INST_STFDX | ___PPC_RS(s) | \
> +#define TEST_STFDX(s, a, b) ppc_inst(PPC_INST_STFDX | ___PPC_RS(s) | \
> ___PPC_RA(a) | ___PPC_RB(b))
> -#define TEST_LVX(t, a, b) (PPC_INST_LVX | ___PPC_RT(t) | \
> +#define TEST_LVX(t, a, b) ppc_inst(PPC_INST_LVX | ___PPC_RT(t) |
> \
> ___PPC_RA(a) | ___PPC_RB(b))
> -#define TEST_STVX(s, a, b) (PPC_INST_STVX | ___PPC_RS(s) | \
> +#define TEST_STVX(s, a, b) ppc_inst(PPC_INST_STVX | ___PPC_RS(s) |
> \
> ___PPC_RA(a) | ___PPC_RB(b))
> -#define TEST_LXVD2X(s, a, b) (PPC_INST_LXVD2X | VSX_XX1((s), R##a, R##b))
> -#define TEST_STXVD2X(s, a, b) (PPC_INST_STXVD2X | VSX_XX1((s), R##a,
> R##b))
> -#define TEST_ADD(t, a, b) (PPC_INST_ADD | ___PPC_RT(t) | \
> +#define TEST_LXVD2X(s, a, b) ppc_inst(PPC_INST_LXVD2X | VSX_XX1((s), R##a,
> R##b))
> +#define TEST_STXVD2X(s, a, b) ppc_inst(PPC_INST_STXVD2X |
> VSX_XX1((s), R##a, R##b))
> +#define TEST_ADD(t, a, b) ppc_inst(PPC_INST_ADD | ___PPC_RT(t) |
> \
> ___PPC_RA(a) | ___PPC_RB(b))
> -#define TEST_ADD_DOT(t, a, b) (PPC_INST_ADD | ___PPC_RT(t) |
> \
> +#define TEST_ADD_DOT(t, a, b) ppc_inst(PPC_INST_ADD | ___PPC_RT(t) |
> \
> ___PPC_RA(a) | ___PPC_RB(b) | 0x1)
> -#define TEST_ADDC(t, a, b) (PPC_INST_ADDC | ___PPC_RT(t) | \
> +#define TEST_ADDC(t, a, b) ppc_inst(PPC_INST_ADDC | ___PPC_RT(t) |
> \
> ___PPC_RA(a) | ___PPC_RB(b))
> -#define TEST_ADDC_DOT(t, a, b) (PPC_INST_ADDC | ___PPC_RT(t) |
> \
> +#define TEST_ADDC_DOT(t, a, b) ppc_inst(PPC_INST_ADDC | ___PPC_RT(t) |
> \
> ___PPC_RA(a) | ___PPC_RB(b) | 0x1)
>
> #define MAX_SUBTESTS 16
> @@ -471,7 +472,7 @@ static struct compute_test compute_tests[] = {
> .subtests = {
> {
> .descr = "R0 = LONG_MAX",
> - .instr = PPC_INST_NOP,
> + .instr = ppc_inst(PPC_INST_NOP),
> .regs = {
> .gpr[0] = LONG_MAX,
> }
> diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
> index 049375206510..68ecb39dd9cc 100644
> --- a/arch/powerpc/xmon/xmon.c
> +++ b/arch/powerpc/xmon/xmon.c
> @@ -54,6 +54,7 @@
> #include <asm/firmware.h>
> #include <asm/code-patching.h>
> #include <asm/sections.h>
> +#include <asm/inst.h>
>
> #ifdef CONFIG_PPC64
> #include <asm/hvcall.h>
> @@ -949,7 +950,7 @@ static void remove_bpts(void)
> if ((bp->enabled & (BP_TRAP|BP_CIABR)) != BP_TRAP)
> continue;
> if (mread(bp->address, &instr, 4) == 4
> - && instr == bpinstr
> + && instr == ppc_inst(bpinstr)
> && patch_instruction(
> (unsigned int *)bp->address, bp->instr[0]) != 0)
> printf("Couldn't remove breakpoint at %lx\n",
> @@ -2845,7 +2846,7 @@ generic_inst_dump(unsigned long adr, long count, int
> praddr,
> {
> int nr, dotted;
> unsigned long first_adr;
> - unsigned int inst, last_inst = 0;
> + unsigned int inst, last_inst = ppc_inst(0);
> unsigned char val[4];
>
> dotted = 0;
> @@ -2858,7 +2859,7 @@ generic_inst_dump(unsigned long adr, long count, int
> praddr,
> }
> break;
> }
> - inst = GETWORD(val);
> + inst = ppc_inst(GETWORD(val));
> if (adr > first_adr && inst == last_inst) {
> if (!dotted) {
> printf(" ...\n");
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 02/21] powerpc/xmon: Move out-of-line instructions to text section
2020-04-06 8:09 ` [PATCH v5 02/21] powerpc/xmon: Move out-of-line instructions to text section Jordan Niethe
@ 2020-04-07 6:45 ` Balamuruhan S
2020-04-09 6:11 ` Christophe Leroy
1 sibling, 0 replies; 71+ messages in thread
From: Balamuruhan S @ 2020-04-07 6:45 UTC (permalink / raw)
To: Jordan Niethe, linuxppc-dev; +Cc: alistair, dja, npiggin
On Mon, 2020-04-06 at 18:09 +1000, Jordan Niethe wrote:
> To execute an instruction out of line after a breakpoint, the NIP is set
> to the address of struct bpt::instr. Here a copy of the instruction that
> was replaced with a breakpoint is kept, along with a trap so normal flow
> can be resumed after XOLing. The struct bpt's are located within the
> data section. This is problematic as the data section may be marked as
> no execute.
>
> Instead of each struct bpt holding the instructions to be XOL'd, make a
> new array, bpt_table[], with enough space to hold instructions for the
> number of supported breakpoints. Place this array in the text section.
> Make struct bpt::instr a pointer to the instructions in bpt_table[]
> associated with that breakpoint. This association is a simple mapping:
> bpts[n] -> bpt_table[n * words per breakpoint]. Currently we only need
> the copied instruction followed by a trap, so 2 words per breakpoint.
we do 2 things here and we discussed to split it into 2 commits, may be
it is up to your thoughts and leave it to you. But otherwise rest looks
good to me.
-- Bala
>
> Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> ---
> v4: New to series
> v5: - Do not use __section(), use a .space directive in .S file
> - Simplify in_breakpoint_table() calculation
> - Define BPT_SIZE
> ---
> arch/powerpc/xmon/Makefile | 2 +-
> arch/powerpc/xmon/xmon.c | 23 +++++++++++++----------
> arch/powerpc/xmon/xmon_bpts.S | 8 ++++++++
> arch/powerpc/xmon/xmon_bpts.h | 8 ++++++++
> 4 files changed, 30 insertions(+), 11 deletions(-)
> create mode 100644 arch/powerpc/xmon/xmon_bpts.S
> create mode 100644 arch/powerpc/xmon/xmon_bpts.h
>
> diff --git a/arch/powerpc/xmon/Makefile b/arch/powerpc/xmon/Makefile
> index c3842dbeb1b7..515a13ea6f28 100644
> --- a/arch/powerpc/xmon/Makefile
> +++ b/arch/powerpc/xmon/Makefile
> @@ -21,7 +21,7 @@ endif
>
> ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC)
>
> -obj-y += xmon.o nonstdio.o spr_access.o
> +obj-y += xmon.o nonstdio.o spr_access.o xmon_bpts.o
>
> ifdef CONFIG_XMON_DISASSEMBLY
> obj-y += ppc-dis.o ppc-opc.o
> diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
> index 02e3bd62cab4..049375206510 100644
> --- a/arch/powerpc/xmon/xmon.c
> +++ b/arch/powerpc/xmon/xmon.c
> @@ -62,6 +62,7 @@
>
> #include "nonstdio.h"
> #include "dis-asm.h"
> +#include "xmon_bpts.h"
>
> #ifdef CONFIG_SMP
> static cpumask_t cpus_in_xmon = CPU_MASK_NONE;
> @@ -97,7 +98,7 @@ static long *xmon_fault_jmp[NR_CPUS];
> /* Breakpoint stuff */
> struct bpt {
> unsigned long address;
> - unsigned int instr[2];
> + unsigned int *instr;
> atomic_t ref_count;
> int enabled;
> unsigned long pad;
> @@ -108,7 +109,6 @@ struct bpt {
> #define BP_TRAP 2
> #define BP_DABR 4
>
> -#define NBPTS 256
> static struct bpt bpts[NBPTS];
> static struct bpt dabr;
> static struct bpt *iabr;
> @@ -116,6 +116,10 @@ static unsigned bpinstr = 0x7fe00008; /* trap */
>
> #define BP_NUM(bp) ((bp) - bpts + 1)
>
> +#define BPT_SIZE (sizeof(unsigned int) * 2)
> +#define BPT_WORDS (BPT_SIZE / sizeof(unsigned int))
> +extern unsigned int bpt_table[NBPTS * BPT_WORDS];
> +
> /* Prototypes */
> static int cmds(struct pt_regs *);
> static int mread(unsigned long, void *, int);
> @@ -853,15 +857,13 @@ static struct bpt *in_breakpoint_table(unsigned long
> nip, unsigned long *offp)
> {
> unsigned long off;
>
> - off = nip - (unsigned long) bpts;
> - if (off >= sizeof(bpts))
> + off = nip - (unsigned long) bpt_table;
> + if (off >= sizeof(bpt_table))
> return NULL;
> - off %= sizeof(struct bpt);
> - if (off != offsetof(struct bpt, instr[0])
> - && off != offsetof(struct bpt, instr[1]))
> + *offp = off % BPT_SIZE;
> + if (*offp != 0 && *offp != 4)
> return NULL;
> - *offp = off - offsetof(struct bpt, instr[0]);
> - return (struct bpt *) (nip - off);
> + return bpts + (off / BPT_SIZE);
> }
>
> static struct bpt *new_breakpoint(unsigned long a)
> @@ -876,7 +878,8 @@ static struct bpt *new_breakpoint(unsigned long a)
> for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
> if (!bp->enabled && atomic_read(&bp->ref_count) == 0) {
> bp->address = a;
> - patch_instruction(&bp->instr[1], bpinstr);
> + bp->instr = bpt_table + ((bp - bpts) * BPT_WORDS);
> + patch_instruction(bp->instr + 1, bpinstr);
> return bp;
> }
> }
> diff --git a/arch/powerpc/xmon/xmon_bpts.S b/arch/powerpc/xmon/xmon_bpts.S
> new file mode 100644
> index 000000000000..ebb2dbc70ca8
> --- /dev/null
> +++ b/arch/powerpc/xmon/xmon_bpts.S
> @@ -0,0 +1,8 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#include <asm/ppc_asm.h>
> +#include <asm/asm-compat.h>
> +#include "xmon_bpts.h"
> +
> +.global bpt_table
> +bpt_table:
> + .space NBPTS * 8
> diff --git a/arch/powerpc/xmon/xmon_bpts.h b/arch/powerpc/xmon/xmon_bpts.h
> new file mode 100644
> index 000000000000..840e70be7945
> --- /dev/null
> +++ b/arch/powerpc/xmon/xmon_bpts.h
> @@ -0,0 +1,8 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef XMON_BPTS_H
> +#define XMON_BPTS_H
> +
> +#define NBPTS 256
> +
> +#endif /* XMON_BPTS_H */
> +
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 03/21] powerpc: Change calling convention for create_branch() et. al.
2020-04-07 6:35 ` Jordan Niethe
@ 2020-04-07 6:59 ` Balamuruhan S
0 siblings, 0 replies; 71+ messages in thread
From: Balamuruhan S @ 2020-04-07 6:59 UTC (permalink / raw)
To: Jordan Niethe
Cc: Alistair Popple, linuxppc-dev, Nicholas Piggin, Daniel Axtens
On Tue, 2020-04-07 at 16:35 +1000, Jordan Niethe wrote:
> On Tue, Apr 7, 2020 at 4:10 PM Balamuruhan S <bala24@linux.ibm.com> wrote:
> > On Mon, 2020-04-06 at 18:09 +1000, Jordan Niethe wrote:
> > > create_branch(), create_cond_branch() and translate_branch() return the
> > > instruction that they create, or return 0 to signal an error. Seperate
> >
> > s/seperate/separate
> thanks.
> > > these concerns in preparation for an instruction type that is not just
> > > an unsigned int. Fill the created instruction to a pointer passed as
> > > the first parameter to the function and use a non-zero return value to
> > > signify an error.
> > >
> > > Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> > > ---
> > > v5: New to series
> > > ---
> > > arch/powerpc/include/asm/code-patching.h | 12 +-
> > > arch/powerpc/kernel/optprobes.c | 24 ++--
> > > arch/powerpc/kernel/setup_32.c | 2 +-
> > > arch/powerpc/kernel/trace/ftrace.c | 24 ++--
> > > arch/powerpc/lib/code-patching.c | 133 +++++++++++++----------
> > > arch/powerpc/lib/feature-fixups.c | 5 +-
> > > 6 files changed, 117 insertions(+), 83 deletions(-)
> > >
> > > diff --git a/arch/powerpc/include/asm/code-patching.h
> > > b/arch/powerpc/include/asm/code-patching.h
> > > index 898b54262881..351dda7215b6 100644
> > > --- a/arch/powerpc/include/asm/code-patching.h
> > > +++ b/arch/powerpc/include/asm/code-patching.h
> > > @@ -22,10 +22,10 @@
> > > #define BRANCH_ABSOLUTE 0x2
> > >
> > > bool is_offset_in_branch_range(long offset);
> > > -unsigned int create_branch(const unsigned int *addr,
> > > - unsigned long target, int flags);
> > > -unsigned int create_cond_branch(const unsigned int *addr,
> > > - unsigned long target, int flags);
> > > +int create_branch(unsigned int *instr, const unsigned int *addr,
> > > + unsigned long target, int flags);
> > > +int create_cond_branch(unsigned int *instr, const unsigned int *addr,
> > > + unsigned long target, int flags);
> > > int patch_branch(unsigned int *addr, unsigned long target, int flags);
> > > int patch_instruction(unsigned int *addr, unsigned int instr);
> > > int raw_patch_instruction(unsigned int *addr, unsigned int instr);
> > > @@ -60,8 +60,8 @@ int instr_is_relative_branch(unsigned int instr);
> > > int instr_is_relative_link_branch(unsigned int instr);
> > > int instr_is_branch_to_addr(const unsigned int *instr, unsigned long
> > > addr);
> > > unsigned long branch_target(const unsigned int *instr);
> > > -unsigned int translate_branch(const unsigned int *dest,
> > > - const unsigned int *src);
> > > +int translate_branch(unsigned int *instr, const unsigned int *dest,
> > > + const unsigned int *src);
> > > extern bool is_conditional_branch(unsigned int instr);
> > > #ifdef CONFIG_PPC_BOOK3E_64
> > > void __patch_exception(int exc, unsigned long addr);
> > > diff --git a/arch/powerpc/kernel/optprobes.c
> > > b/arch/powerpc/kernel/optprobes.c
> > > index 024f7aad1952..445b3dad82dc 100644
> > > --- a/arch/powerpc/kernel/optprobes.c
> > > +++ b/arch/powerpc/kernel/optprobes.c
> > > @@ -251,15 +251,17 @@ int arch_prepare_optimized_kprobe(struct
> > > optimized_kprobe *op, struct kprobe *p)
> > > goto error;
> > > }
> > >
> > > - branch_op_callback = create_branch((unsigned int *)buff +
> > > TMPL_CALL_HDLR_IDX,
> > > - (unsigned long)op_callback_addr,
> > > - BRANCH_SET_LINK);
> > > + rc = create_branch(&branch_op_callback,
> > > + (unsigned int *)buff + TMPL_CALL_HDLR_IDX,
> > > + (unsigned long)op_callback_addr,
> > > + BRANCH_SET_LINK);
> > >
> > > - branch_emulate_step = create_branch((unsigned int *)buff +
> > > TMPL_EMULATE_IDX,
> > > - (unsigned long)emulate_step_addr,
> > > - BRANCH_SET_LINK);
> > > + rc |= create_branch(&branch_emulate_step,
> > > + (unsigned int *)buff + TMPL_EMULATE_IDX,
> > > + (unsigned long)emulate_step_addr,
> > > + BRANCH_SET_LINK);
> > >
> > > - if (!branch_op_callback || !branch_emulate_step)
> > > + if (rc)
> > > goto error;
> > >
> > > patch_instruction(buff + TMPL_CALL_HDLR_IDX, branch_op_callback);
> > > @@ -305,6 +307,7 @@ int arch_check_optimized_kprobe(struct
> > > optimized_kprobe
> > > *op)
> > >
> > > void arch_optimize_kprobes(struct list_head *oplist)
> > > {
> > > + unsigned int instr;
> > > struct optimized_kprobe *op;
> > > struct optimized_kprobe *tmp;
> > >
> > > @@ -315,9 +318,10 @@ void arch_optimize_kprobes(struct list_head *oplist)
> > > */
> > > memcpy(op->optinsn.copied_insn, op->kp.addr,
> > > RELATIVEJUMP_SIZE);
> > > - patch_instruction(op->kp.addr,
> > > - create_branch((unsigned int *)op->kp.addr,
> > > - (unsigned long)op->optinsn.insn, 0));
> > > + create_branch(&instr,
> > > + (unsigned int *)op->kp.addr,
> > > + (unsigned long)op->optinsn.insn, 0);
> > > + patch_instruction(op->kp.addr, instr);
> > > list_del_init(&op->list);
> > > }
> > > }
> > > diff --git a/arch/powerpc/kernel/setup_32.c
> > > b/arch/powerpc/kernel/setup_32.c
> > > index 5b49b26eb154..c1bdd462c5c0 100644
> > > --- a/arch/powerpc/kernel/setup_32.c
> > > +++ b/arch/powerpc/kernel/setup_32.c
> > > @@ -88,7 +88,7 @@ notrace void __init machine_init(u64 dt_ptr)
> > >
> > > patch_instruction_site(&patch__memcpy_nocache, PPC_INST_NOP);
> > >
> > > - insn = create_cond_branch(addr, branch_target(addr), 0x820000);
> > > + create_cond_branch(&insn, addr, branch_target(addr), 0x820000);
> > > patch_instruction(addr, insn); /* replace b by bne cr0 */
> > >
> > > /* Do some early initialization based on the flat device tree */
> > > diff --git a/arch/powerpc/kernel/trace/ftrace.c
> > > b/arch/powerpc/kernel/trace/ftrace.c
> > > index 7ea0ca044b65..4dcb379133f8 100644
> > > --- a/arch/powerpc/kernel/trace/ftrace.c
> > > +++ b/arch/powerpc/kernel/trace/ftrace.c
> > > @@ -48,7 +48,7 @@ ftrace_call_replace(unsigned long ip, unsigned long
> > > addr,
> > > int link)
> > > addr = ppc_function_entry((void *)addr);
> > >
> > > /* if (link) set op to 'bl' else 'b' */
> > > - op = create_branch((unsigned int *)ip, addr, link ? 1 : 0);
> > > + create_branch(&op, (unsigned int *)ip, addr, link ? 1 : 0);
> > >
> > > return op;
> > > }
> > > @@ -89,10 +89,11 @@ ftrace_modify_code(unsigned long ip, unsigned int
> > > old,
> > > unsigned int new)
> > > */
> > > static int test_24bit_addr(unsigned long ip, unsigned long addr)
> > > {
> > > + unsigned int op;
> > > addr = ppc_function_entry((void *)addr);
> > >
> > > /* use the create_branch to verify that this offset can be branched
> > > */
> > > - return create_branch((unsigned int *)ip, addr, 0);
> > > + return create_branch(&op, (unsigned int *)ip, addr, 0) == 0;
> > > }
> > >
> > > static int is_bl_op(unsigned int op)
> > > @@ -287,6 +288,7 @@ __ftrace_make_nop(struct module *mod,
> > > static unsigned long find_ftrace_tramp(unsigned long ip)
> > > {
> > > int i;
> > > + unsigned int instr;
> > >
> > > /*
> > > * We have the compiler generated long_branch tramps at the end
> > > @@ -295,7 +297,8 @@ static unsigned long find_ftrace_tramp(unsigned long
> > > ip)
> > > for (i = NUM_FTRACE_TRAMPS - 1; i >= 0; i--)
> > > if (!ftrace_tramps[i])
> > > continue;
> > > - else if (create_branch((void *)ip, ftrace_tramps[i], 0))
> > > + else if (create_branch(&instr, (void *)ip,
> > > + ftrace_tramps[i], 0) == 0)
> > > return ftrace_tramps[i];
> > >
> > > return 0;
> > > @@ -324,6 +327,7 @@ static int setup_mcount_compiler_tramp(unsigned long
> > > tramp)
> > > {
> > > int i, op;
> > > unsigned long ptr;
> > > + unsigned int instr;
> > > static unsigned long ftrace_plt_tramps[NUM_FTRACE_TRAMPS];
> > >
> > > /* Is this a known long jump tramp? */
> > > @@ -366,7 +370,7 @@ static int setup_mcount_compiler_tramp(unsigned long
> > > tramp)
> > > #else
> > > ptr = ppc_global_function_entry((void *)ftrace_caller);
> > > #endif
> > > - if (!create_branch((void *)tramp, ptr, 0)) {
> > > + if (create_branch(&instr, (void *)tramp, ptr, 0)) {
> > > pr_debug("%ps is not reachable from existing mcount
> > > tramp\n",
> > > (void *)ptr);
> > > return -1;
> > > @@ -511,6 +515,7 @@ static int
> > > __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
> > > {
> > > unsigned int op[2];
> > > + unsigned int instr;
> > > void *ip = (void *)rec->ip;
> > > unsigned long entry, ptr, tramp;
> > > struct module *mod = rec->arch.mod;
> > > @@ -557,7 +562,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned
> > > long
> > > addr)
> > > }
> > >
> > > /* Ensure branch is within 24 bits */
> > > - if (!create_branch(ip, tramp, BRANCH_SET_LINK)) {
> > > + if (create_branch(&instr, ip, tramp, BRANCH_SET_LINK)) {
> > > pr_err("Branch out of range\n");
> > > return -EINVAL;
> > > }
> > > @@ -574,6 +579,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned
> > > long
> > > addr)
> > > static int
> > > __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
> > > {
> > > + int err;
> > > unsigned int op;
> > > unsigned long ip = rec->ip;
> > >
> > > @@ -594,9 +600,9 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned
> > > long
> > > addr)
> > > }
> > >
> > > /* create the branch to the trampoline */
> > > - op = create_branch((unsigned int *)ip,
> > > - rec->arch.mod->arch.tramp, BRANCH_SET_LINK);
> > > - if (!op) {
> > > + err = create_branch(&op, (unsigned int *)ip,
> > > + rec->arch.mod->arch.tramp, BRANCH_SET_LINK);
> > > + if (!err) {
> >
> > should this be `if (err)` as per your new changes ?
> You are right.
> >
> > > pr_err("REL24 out of range!\n");
> > > return -EINVAL;
> > > }
> > > @@ -776,7 +782,7 @@ __ftrace_modify_call(struct dyn_ftrace *rec, unsigned
> > > long old_addr,
> > > }
> > >
> > > /* Ensure branch is within 24 bits */
> > > - if (!create_branch((unsigned int *)ip, tramp, BRANCH_SET_LINK)) {
> > > + if (create_branch(&op, (unsigned int *)ip, tramp, BRANCH_SET_LINK))
> > > {
> > > pr_err("Branch out of range\n");
> > > return -EINVAL;
> > > }
> > > diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-
> > > patching.c
> > > index 3345f039a876..4af564aeedf1 100644
> > > --- a/arch/powerpc/lib/code-patching.c
> > > +++ b/arch/powerpc/lib/code-patching.c
> > > @@ -196,7 +196,10 @@ NOKPROBE_SYMBOL(patch_instruction);
> > >
> > > int patch_branch(unsigned int *addr, unsigned long target, int flags)
> > > {
> > > - return patch_instruction(addr, create_branch(addr, target, flags));
> > > + unsigned int instr;
> > > +
> > > + create_branch(&instr, addr, target, flags);
> > > + return patch_instruction(addr, instr);
> > > }
> > >
> > > bool is_offset_in_branch_range(long offset)
> > > @@ -243,30 +246,30 @@ bool is_conditional_branch(unsigned int instr)
> > > }
> > > NOKPROBE_SYMBOL(is_conditional_branch);
> > >
> > > -unsigned int create_branch(const unsigned int *addr,
> > > - unsigned long target, int flags)
> > > +int create_branch(unsigned int *instr,
> > > + const unsigned int *addr,
> > > + unsigned long target, int flags)
> > > {
> > > - unsigned int instruction;
> > > long offset;
> > >
> > > + *instr = 0;
> > > offset = target;
> > > if (! (flags & BRANCH_ABSOLUTE))
> > > offset = offset - (unsigned long)addr;
> > >
> > > /* Check we can represent the target in the instruction format */
> > > if (!is_offset_in_branch_range(offset))
> > > - return 0;
> > > + return 1;
> > >
> > > /* Mask out the flags and target, so they don't step on each other.
> > > */
> > > - instruction = 0x48000000 | (flags & 0x3) | (offset & 0x03FFFFFC);
> > > + *instr = 0x48000000 | (flags & 0x3) | (offset & 0x03FFFFFC);
> > >
> > > - return instruction;
> > > + return 0;
> > > }
> > >
> > > -unsigned int create_cond_branch(const unsigned int *addr,
> > > - unsigned long target, int flags)
> > > +int create_cond_branch(unsigned int *instr, const unsigned int *addr,
> > > + unsigned long target, int flags)
> > > {
> > > - unsigned int instruction;
> > > long offset;
> > >
> > > offset = target;
> > > @@ -275,12 +278,12 @@ unsigned int create_cond_branch(const unsigned int
> > > *addr,
> > >
> > > /* Check we can represent the target in the instruction format */
> > > if (offset < -0x8000 || offset > 0x7FFF || offset & 0x3)
> > > - return 0;
> > > + return 1;
> > >
> > > /* Mask out the flags and target, so they don't step on each other.
> > > */
> > > - instruction = 0x40000000 | (flags & 0x3FF0003) | (offset & 0xFFFC);
> > > + *instr = 0x40000000 | (flags & 0x3FF0003) | (offset & 0xFFFC);
> > >
> > > - return instruction;
> > > + return 0;
> > > }
> > >
> > > static unsigned int branch_opcode(unsigned int instr)
> > > @@ -361,18 +364,18 @@ int instr_is_branch_to_addr(const unsigned int
> > > *instr,
> > > unsigned long addr)
> > > return 0;
> > > }
> > >
> > > -unsigned int translate_branch(const unsigned int *dest, const unsigned
> > > int
> > > *src)
> > > +int translate_branch(unsigned int *instr, const unsigned int *dest,
> > > const
> > > unsigned int *src)
> > > {
> > > unsigned long target;
> > >
> > > target = branch_target(src);
> > >
> > > if (instr_is_branch_iform(*src))
> > > - return create_branch(dest, target, *src);
> > > + return create_branch(instr, dest, target, *src);
> > > else if (instr_is_branch_bform(*src))
> > > - return create_cond_branch(dest, target, *src);
> > > + return create_cond_branch(instr, dest, target, *src);
> > >
> > > - return 0;
> > > + return 1;
> > > }
> > >
> > > #ifdef CONFIG_PPC_BOOK3E_64
> > > @@ -403,6 +406,7 @@ static void __init test_trampoline(void)
> > >
> > > static void __init test_branch_iform(void)
> > > {
> > > + int err;
> > > unsigned int instr;
> > > unsigned long addr;
> > >
> > > @@ -443,35 +447,35 @@ static void __init test_branch_iform(void)
> > > check(instr_is_branch_to_addr(&instr, addr - 0x2000000));
> > >
> > > /* Branch to self, with link */
> > > - instr = create_branch(&instr, addr, BRANCH_SET_LINK);
> > > + err = create_branch(&instr, &instr, addr, BRANCH_SET_LINK);
> > > check(instr_is_branch_to_addr(&instr, addr));
> > >
> > > /* Branch to self - 0x100, with link */
> > > - instr = create_branch(&instr, addr - 0x100, BRANCH_SET_LINK);
> > > + err = create_branch(&instr, &instr, addr - 0x100, BRANCH_SET_LINK);
> > > check(instr_is_branch_to_addr(&instr, addr - 0x100));
> > >
> > > /* Branch to self + 0x100, no link */
> > > - instr = create_branch(&instr, addr + 0x100, 0);
> > > + err = create_branch(&instr, &instr, addr + 0x100, 0);
> > > check(instr_is_branch_to_addr(&instr, addr + 0x100));
> > >
> > > /* Maximum relative negative offset, - 32 MB */
> > > - instr = create_branch(&instr, addr - 0x2000000, BRANCH_SET_LINK);
> > > + err = create_branch(&instr, &instr, addr - 0x2000000,
> > > BRANCH_SET_LINK);
> > > check(instr_is_branch_to_addr(&instr, addr - 0x2000000));
> > >
> > > /* Out of range relative negative offset, - 32 MB + 4*/
> > > - instr = create_branch(&instr, addr - 0x2000004, BRANCH_SET_LINK);
> > > - check(instr == 0);
> > > + err = create_branch(&instr, &instr, addr - 0x2000004,
> > > BRANCH_SET_LINK);
> > > + check(err);
> > >
> > > /* Out of range relative positive offset, + 32 MB */
> > > - instr = create_branch(&instr, addr + 0x2000000, BRANCH_SET_LINK);
> > > - check(instr == 0);
> > > + err = create_branch(&instr, &instr, addr + 0x2000000,
> > > BRANCH_SET_LINK);
> > > + check(err);
> > >
> > > /* Unaligned target */
> > > - instr = create_branch(&instr, addr + 3, BRANCH_SET_LINK);
> > > - check(instr == 0);
> > > + err = create_branch(&instr, &instr, addr + 3, BRANCH_SET_LINK);
> > > + check(err);
> > >
> > > /* Check flags are masked correctly */
> > > - instr = create_branch(&instr, addr, 0xFFFFFFFC);
> > > + err = create_branch(&instr, &instr, addr, 0xFFFFFFFC);
> > > check(instr_is_branch_to_addr(&instr, addr));
> > > check(instr == 0x48000000);
> > > }
> > > @@ -480,16 +484,19 @@ static void __init test_create_function_call(void)
> > > {
> > > unsigned int *iptr;
> > > unsigned long dest;
> > > + unsigned int instr;
> > >
> > > /* Check we can create a function call */
> > > iptr = (unsigned int *)ppc_function_entry(test_trampoline);
> > > dest = ppc_function_entry(test_create_function_call);
> > > - patch_instruction(iptr, create_branch(iptr, dest,
> > > BRANCH_SET_LINK));
> > > + create_branch(&instr, iptr, dest, BRANCH_SET_LINK);
> > > + patch_instruction(iptr, instr);
> >
> > Are we sure that `create_branch()` would always succeed here to do
> > patch_instruction() ?
> >
> >
> > > check(instr_is_branch_to_addr(iptr, dest));
> > > }
> > >
> > > static void __init test_branch_bform(void)
> > > {
> > > + int err;
> > > unsigned long addr;
> > > unsigned int *iptr, instr, flags;
> > >
> > > @@ -525,35 +532,35 @@ static void __init test_branch_bform(void)
> > > flags = 0x3ff000 | BRANCH_SET_LINK;
> > >
> > > /* Branch to self */
> > > - instr = create_cond_branch(iptr, addr, flags);
> > > + err = create_cond_branch(&instr, iptr, addr, flags);
> > > check(instr_is_branch_to_addr(&instr, addr));
> > >
> > > /* Branch to self - 0x100 */
> > > - instr = create_cond_branch(iptr, addr - 0x100, flags);
> > > + err = create_cond_branch(&instr, iptr, addr - 0x100, flags);
> > > check(instr_is_branch_to_addr(&instr, addr - 0x100));
> > >
> > > /* Branch to self + 0x100 */
> > > - instr = create_cond_branch(iptr, addr + 0x100, flags);
> > > + err = create_cond_branch(&instr, iptr, addr + 0x100, flags);
> > > check(instr_is_branch_to_addr(&instr, addr + 0x100));
> > >
> > > /* Maximum relative negative offset, - 32 KB */
> > > - instr = create_cond_branch(iptr, addr - 0x8000, flags);
> > > + err = create_cond_branch(&instr, iptr, addr - 0x8000, flags);
> > > check(instr_is_branch_to_addr(&instr, addr - 0x8000));
> > >
> > > /* Out of range relative negative offset, - 32 KB + 4*/
> > > - instr = create_cond_branch(iptr, addr - 0x8004, flags);
> > > - check(instr == 0);
> > > + err = create_cond_branch(&instr, iptr, addr - 0x8004, flags);
> > > + check(err);
> > >
> > > /* Out of range relative positive offset, + 32 KB */
> > > - instr = create_cond_branch(iptr, addr + 0x8000, flags);
> > > - check(instr == 0);
> > > + err = create_cond_branch(&instr, iptr, addr + 0x8000, flags);
> > > + check(err);
> > >
> > > /* Unaligned target */
> > > - instr = create_cond_branch(iptr, addr + 3, flags);
> > > - check(instr == 0);
> > > + err = create_cond_branch(&instr, iptr, addr + 3, flags);
> > > + check(err);
> > >
> > > /* Check flags are masked correctly */
> > > - instr = create_cond_branch(iptr, addr, 0xFFFFFFFC);
> > > + err = create_cond_branch(&instr, iptr, addr, 0xFFFFFFFC);
> > > check(instr_is_branch_to_addr(&instr, addr));
> > > check(instr == 0x43FF0000);
> > > }
> > > @@ -562,6 +569,7 @@ static void __init test_translate_branch(void)
> > > {
> > > unsigned long addr;
> > > unsigned int *p, *q;
> > > + unsigned int instr;
> > > void *buf;
> > >
> > > buf = vmalloc(PAGE_ALIGN(0x2000000 + 1));
> > > @@ -575,7 +583,8 @@ static void __init test_translate_branch(void)
> > > patch_branch(p, addr, 0);
> > > check(instr_is_branch_to_addr(p, addr));
> > > q = p + 1;
> > > - patch_instruction(q, translate_branch(q, p));
> > > + translate_branch(&instr, q, p);
> > > + patch_instruction(q, instr);
> >
> > same here and elsewhere in similar such places where we do
> > patch_instruction()
> I figured that if the existing code was not checking the return then
> we probably did not need to add a check.
yes existing code does not checking, I just wanted to ensure we do right
thing. Thanks!
-- Bala
> > -- Bala
> >
> > > check(instr_is_branch_to_addr(q, addr));
> > >
> > > /* Maximum negative case, move b . to addr + 32 MB */
> > > @@ -583,7 +592,8 @@ static void __init test_translate_branch(void)
> > > addr = (unsigned long)p;
> > > patch_branch(p, addr, 0);
> > > q = buf + 0x2000000;
> > > - patch_instruction(q, translate_branch(q, p));
> > > + translate_branch(&instr, q, p);
> > > + patch_instruction(q, instr);
> > > check(instr_is_branch_to_addr(p, addr));
> > > check(instr_is_branch_to_addr(q, addr));
> > > check(*q == 0x4a000000);
> > > @@ -593,7 +603,8 @@ static void __init test_translate_branch(void)
> > > addr = (unsigned long)p;
> > > patch_branch(p, addr, 0);
> > > q = buf + 4;
> > > - patch_instruction(q, translate_branch(q, p));
> > > + translate_branch(&instr, q, p);
> > > + patch_instruction(q, instr);
> > > check(instr_is_branch_to_addr(p, addr));
> > > check(instr_is_branch_to_addr(q, addr));
> > > check(*q == 0x49fffffc);
> > > @@ -603,7 +614,8 @@ static void __init test_translate_branch(void)
> > > addr = 0x1000000 + (unsigned long)buf;
> > > patch_branch(p, addr, BRANCH_SET_LINK);
> > > q = buf + 0x1400000;
> > > - patch_instruction(q, translate_branch(q, p));
> > > + translate_branch(&instr, q, p);
> > > + patch_instruction(q, instr);
> > > check(instr_is_branch_to_addr(p, addr));
> > > check(instr_is_branch_to_addr(q, addr));
> > >
> > > @@ -612,7 +624,8 @@ static void __init test_translate_branch(void)
> > > addr = 0x2000000 + (unsigned long)buf;
> > > patch_branch(p, addr, 0);
> > > q = buf + 4;
> > > - patch_instruction(q, translate_branch(q, p));
> > > + translate_branch(&instr, q, p);
> > > + patch_instruction(q, instr);
> > > check(instr_is_branch_to_addr(p, addr));
> > > check(instr_is_branch_to_addr(q, addr));
> > >
> > > @@ -622,18 +635,22 @@ static void __init test_translate_branch(void)
> > > /* Simple case, branch to self moved a little */
> > > p = buf;
> > > addr = (unsigned long)p;
> > > - patch_instruction(p, create_cond_branch(p, addr, 0));
> > > + create_cond_branch(&instr, p, addr, 0);
> > > + patch_instruction(p, instr);
> > > check(instr_is_branch_to_addr(p, addr));
> > > q = p + 1;
> > > - patch_instruction(q, translate_branch(q, p));
> > > + translate_branch(&instr, q, p);
> > > + patch_instruction(q, instr);
> > > check(instr_is_branch_to_addr(q, addr));
> > >
> > > /* Maximum negative case, move b . to addr + 32 KB */
> > > p = buf;
> > > addr = (unsigned long)p;
> > > - patch_instruction(p, create_cond_branch(p, addr, 0xFFFFFFFC));
> > > + create_cond_branch(&instr, p, addr, 0xFFFFFFFC);
> > > + patch_instruction(p, instr);
> > > q = buf + 0x8000;
> > > - patch_instruction(q, translate_branch(q, p));
> > > + translate_branch(&instr, q, p);
> > > + patch_instruction(q, instr);
> > > check(instr_is_branch_to_addr(p, addr));
> > > check(instr_is_branch_to_addr(q, addr));
> > > check(*q == 0x43ff8000);
> > > @@ -641,9 +658,11 @@ static void __init test_translate_branch(void)
> > > /* Maximum positive case, move x to x - 32 KB + 4 */
> > > p = buf + 0x8000;
> > > addr = (unsigned long)p;
> > > - patch_instruction(p, create_cond_branch(p, addr, 0xFFFFFFFC));
> > > + create_cond_branch(&instr, p, addr, 0xFFFFFFFC);
> > > + patch_instruction(p, instr);
> > > q = buf + 4;
> > > - patch_instruction(q, translate_branch(q, p));
> > > + translate_branch(&instr, q, p);
> > > + patch_instruction(q, instr);
> > > check(instr_is_branch_to_addr(p, addr));
> > > check(instr_is_branch_to_addr(q, addr));
> > > check(*q == 0x43ff7ffc);
> > > @@ -651,18 +670,22 @@ static void __init test_translate_branch(void)
> > > /* Jump to x + 12 KB moved to x + 20 KB */
> > > p = buf;
> > > addr = 0x3000 + (unsigned long)buf;
> > > - patch_instruction(p, create_cond_branch(p, addr, BRANCH_SET_LINK));
> > > + create_cond_branch(&instr, p, addr, BRANCH_SET_LINK);
> > > + patch_instruction(p, instr);
> > > q = buf + 0x5000;
> > > - patch_instruction(q, translate_branch(q, p));
> > > + translate_branch(&instr, q, p);
> > > + patch_instruction(q, instr);
> > > check(instr_is_branch_to_addr(p, addr));
> > > check(instr_is_branch_to_addr(q, addr));
> > >
> > > /* Jump to x + 8 KB moved to x - 8 KB + 4 */
> > > p = buf + 0x2000;
> > > addr = 0x4000 + (unsigned long)buf;
> > > - patch_instruction(p, create_cond_branch(p, addr, 0));
> > > + create_cond_branch(&instr, p, addr, 0);
> > > + patch_instruction(p, instr);
> > > q = buf + 4;
> > > - patch_instruction(q, translate_branch(q, p));
> > > + translate_branch(&instr, q, p);
> > > + patch_instruction(q, instr);
> > > check(instr_is_branch_to_addr(p, addr));
> > > check(instr_is_branch_to_addr(q, addr));
> > >
> > > diff --git a/arch/powerpc/lib/feature-fixups.c
> > > b/arch/powerpc/lib/feature-
> > > fixups.c
> > > index 4ba634b89ce5..b129d7b4e7dd 100644
> > > --- a/arch/powerpc/lib/feature-fixups.c
> > > +++ b/arch/powerpc/lib/feature-fixups.c
> > > @@ -44,6 +44,7 @@ static unsigned int *calc_addr(struct fixup_entry
> > > *fcur,
> > > long offset)
> > > static int patch_alt_instruction(unsigned int *src, unsigned int *dest,
> > > unsigned int *alt_start, unsigned int
> > > *alt_end)
> > > {
> > > + int err;
> > > unsigned int instr;
> > >
> > > instr = *src;
> > > @@ -53,8 +54,8 @@ static int patch_alt_instruction(unsigned int *src,
> > > unsigned int *dest,
> > >
> > > /* Branch within the section doesn't need translating */
> > > if (target < alt_start || target > alt_end) {
> > > - instr = translate_branch(dest, src);
> > > - if (!instr)
> > > + err = translate_branch(&instr, dest, src);
> > > + if (err)
> > > return 1;
> > > }
> > > }
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 05/21] powerpc: Use a function for getting the instruction op code
2020-04-06 8:09 ` [PATCH v5 05/21] powerpc: Use a function for getting the instruction op code Jordan Niethe
2020-04-06 8:22 ` Christophe Leroy
@ 2020-04-07 7:04 ` Balamuruhan S
2020-04-07 8:32 ` Jordan Niethe
2020-04-08 18:21 ` Segher Boessenkool
2 siblings, 1 reply; 71+ messages in thread
From: Balamuruhan S @ 2020-04-07 7:04 UTC (permalink / raw)
To: Jordan Niethe, linuxppc-dev; +Cc: alistair, npiggin, dja
On Mon, 2020-04-06 at 18:09 +1000, Jordan Niethe wrote:
> In preparation for using a data type for instructions that can not be
> directly used with the '>>' operator use a function for getting the op
> code of an instruction.
vecemu.c and sstep.c will need ppc_inst_opcode().
-- Bala
>
> Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> ---
> v4: New to series
> ---
> arch/powerpc/include/asm/inst.h | 5 +++++
> arch/powerpc/kernel/align.c | 2 +-
> arch/powerpc/lib/code-patching.c | 4 ++--
> 3 files changed, 8 insertions(+), 3 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/inst.h
> b/arch/powerpc/include/asm/inst.h
> index 5298ba33b6e5..93959016fe4b 100644
> --- a/arch/powerpc/include/asm/inst.h
> +++ b/arch/powerpc/include/asm/inst.h
> @@ -8,4 +8,9 @@
>
> #define ppc_inst(x) (x)
>
> +static inline int ppc_inst_opcode(u32 x)
> +{
> + return x >> 26;
> +}
> +
> #endif /* _ASM_INST_H */
> diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
> index 86e9bf62f18c..691013aa9f3c 100644
> --- a/arch/powerpc/kernel/align.c
> +++ b/arch/powerpc/kernel/align.c
> @@ -314,7 +314,7 @@ int fix_alignment(struct pt_regs *regs)
> }
>
> #ifdef CONFIG_SPE
> - if ((instr >> 26) == 0x4) {
> + if (ppc_inst_opcode(instr) == 0x4) {
> int reg = (instr >> 21) & 0x1f;
> PPC_WARN_ALIGNMENT(spe, regs);
> return emulate_spe(regs, reg, instr);
> diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-
> patching.c
> index fdf0d6ea3575..099a515202aa 100644
> --- a/arch/powerpc/lib/code-patching.c
> +++ b/arch/powerpc/lib/code-patching.c
> @@ -231,7 +231,7 @@ bool is_offset_in_branch_range(long offset)
> */
> bool is_conditional_branch(unsigned int instr)
> {
> - unsigned int opcode = instr >> 26;
> + unsigned int opcode = ppc_inst_opcode(instr);
>
> if (opcode == 16) /* bc, bca, bcl, bcla */
> return true;
> @@ -289,7 +289,7 @@ int create_cond_branch(unsigned int *instr, const
> unsigned int *addr,
>
> static unsigned int branch_opcode(unsigned int instr)
> {
> - return (instr >> 26) & 0x3F;
> + return ppc_inst_opcode(instr) & 0x3F;
> }
>
> static int instr_is_branch_iform(unsigned int instr)
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 08/21] powerpc: Introduce functions for instruction equality
2020-04-06 8:09 ` [PATCH v5 08/21] powerpc: Introduce functions for instruction equality Jordan Niethe
@ 2020-04-07 7:37 ` Balamuruhan S
0 siblings, 0 replies; 71+ messages in thread
From: Balamuruhan S @ 2020-04-07 7:37 UTC (permalink / raw)
To: Jordan Niethe, linuxppc-dev; +Cc: alistair, npiggin, dja
On Mon, 2020-04-06 at 18:09 +1000, Jordan Niethe wrote:
> In preparation for an instruction data type that can not be directly
> used with the '==' operator use functions for checking equality.
LGTM except one comment below, otherwise
Reviewed-by: Balamuruhan S <bala24@linux.ibm.com>
>
> Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> ---
> v5: Remove ppc_inst_null()
> ---
> arch/powerpc/include/asm/inst.h | 5 +++++
> arch/powerpc/kernel/trace/ftrace.c | 15 ++++++++-------
> arch/powerpc/lib/code-patching.c | 12 ++++++------
> arch/powerpc/lib/test_emulate_step.c | 2 +-
> arch/powerpc/xmon/xmon.c | 4 ++--
> 5 files changed, 22 insertions(+), 16 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/inst.h
> b/arch/powerpc/include/asm/inst.h
> index 78eb1481f1f6..54ee46b0a7c9 100644
> --- a/arch/powerpc/include/asm/inst.h
> +++ b/arch/powerpc/include/asm/inst.h
> @@ -23,4 +23,9 @@ static inline u32 ppc_inst_swab(u32 x)
> return ppc_inst(swab32(ppc_inst_val(x)));
> }
>
> +static inline bool ppc_inst_equal(u32 x, u32 y)
> +{
> + return x == y;
> +}
> +
> #endif /* _ASM_INST_H */
> diff --git a/arch/powerpc/kernel/trace/ftrace.c
> b/arch/powerpc/kernel/trace/ftrace.c
> index 62ff429bddc4..784b5746cc55 100644
> --- a/arch/powerpc/kernel/trace/ftrace.c
> +++ b/arch/powerpc/kernel/trace/ftrace.c
> @@ -72,7 +72,7 @@ ftrace_modify_code(unsigned long ip, unsigned int old,
> unsigned int new)
> return -EFAULT;
>
> /* Make sure it is what we expect it to be */
> - if (replaced != old) {
> + if (!ppc_inst_equal(replaced, old)) {
> pr_err("%p: replaced (%#x) != old (%#x)",
> (void *)ip, ppc_inst_val(replaced), ppc_inst_val(old));
> return -EINVAL;
> @@ -170,7 +170,8 @@ __ftrace_make_nop(struct module *mod,
> }
>
> /* We expect either a mflr r0, or a std r0, LRSAVE(r1) */
> - if (op != ppc_inst(PPC_INST_MFLR) && op != ppc_inst(PPC_INST_STD_LR)) {
> + if (!ppc_inst_equal(op, ppc_inst(PPC_INST_MFLR)) &&
> + !ppc_inst_equal(op, ppc_inst(PPC_INST_STD_LR))) {
> pr_err("Unexpected instruction %08x around bl _mcount\n",
> ppc_inst_val(op));
> return -EINVAL;
> }
> @@ -200,7 +201,7 @@ __ftrace_make_nop(struct module *mod,
> return -EFAULT;
> }
>
> - if (op != ppc_inst(PPC_INST_LD_TOC)) {
> + if (!ppc_inst_equal(op, ppc_inst(PPC_INST_LD_TOC))) {
> pr_err("Expected %08x found %08x\n", PPC_INST_LD_TOC,
> ppc_inst_val(op));
> return -EINVAL;
> }
> @@ -497,7 +498,7 @@ expected_nop_sequence(void *ip, unsigned int op0,
> unsigned int op1)
> * The load offset is different depending on the ABI. For simplicity
> * just mask it out when doing the compare.
> */
> - if ((op0 != ppc_inst(0x48000008)) || (ppc_inst_val(op1) & 0xffff0000)
> != 0xe8410000)
> + if ((!ppc_inst_equal(op0), ppc_inst(0x48000008)) || (ppc_inst_val(op1)
> & 0xffff0000) != 0xe8410000)
> return 0;
> return 1;
> }
> @@ -506,7 +507,7 @@ static int
> expected_nop_sequence(void *ip, unsigned int op0, unsigned int op1)
> {
> /* look for patched "NOP" on ppc64 with -mprofile-kernel */
> - if (op0 != ppc_inst(PPC_INST_NOP))
> + if (!ppc_inst_equal(op0, ppc_inst(PPC_INST_NOP)))
> return 0;
> return 1;
> }
> @@ -589,7 +590,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long
> addr)
> return -EFAULT;
>
> /* It should be pointing to a nop */
> - if (op != ppc_inst(PPC_INST_NOP)) {
> + if (!ppc_inst_equal(op, ppc_inst(PPC_INST_NOP))) {
> pr_err("Expected NOP but have %x\n", op);
> return -EINVAL;
> }
> @@ -646,7 +647,7 @@ static int __ftrace_make_call_kernel(struct dyn_ftrace
> *rec, unsigned long addr)
> return -EFAULT;
> }
>
> - if (op != ppc_inst(PPC_INST_NOP)) {
> + if (!ppc_inst_equal(op, ppc_inst(PPC_INST_NOP))) {
> pr_err("Unexpected call sequence at %p: %x\n", ip,
> ppc_inst_val(op));
> return -EINVAL;
> }
> diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-
> patching.c
> index 3f88d2a4400c..33654c6334a9 100644
> --- a/arch/powerpc/lib/code-patching.c
> +++ b/arch/powerpc/lib/code-patching.c
> @@ -478,7 +478,7 @@ static void __init test_branch_iform(void)
> /* Check flags are masked correctly */
> err = create_branch(&instr, &instr, addr, 0xFFFFFFFC);
> check(instr_is_branch_to_addr(&instr, addr));
> - check(instr == ppc_inst(0x48000000));
> + check(ppc_inst_equal(instr, ppc_inst(0x48000000)));
> }
>
> static void __init test_create_function_call(void)
> @@ -563,7 +563,7 @@ static void __init test_branch_bform(void)
> /* Check flags are masked correctly */
> err = create_cond_branch(&instr, iptr, addr, 0xFFFFFFFC);
> check(instr_is_branch_to_addr(&instr, addr));
> - check(instr == ppc_inst(0x43FF0000));
> + check(ppc_inst_equal(instr, ppc_inst(0x43FF0000)));
> }
>
> static void __init test_translate_branch(void)
> @@ -597,7 +597,7 @@ static void __init test_translate_branch(void)
> patch_instruction(q, instr);
> check(instr_is_branch_to_addr(p, addr));
> check(instr_is_branch_to_addr(q, addr));
> - check(*q == ppc_inst(0x4a000000));
> + check(ppc_inst_equal(*q, ppc_inst(0x4a000000)));
>
> /* Maximum positive case, move x to x - 32 MB + 4 */
> p = buf + 0x2000000;
> @@ -608,7 +608,7 @@ static void __init test_translate_branch(void)
> patch_instruction(q, instr);
> check(instr_is_branch_to_addr(p, addr));
> check(instr_is_branch_to_addr(q, addr));
> - check(*q == ppc_inst(0x49fffffc));
> + check(ppc_inst_equal(*q, ppc_inst(0x49fffffc)));
>
> /* Jump to x + 16 MB moved to x + 20 MB */
> p = buf;
> @@ -654,7 +654,7 @@ static void __init test_translate_branch(void)
> patch_instruction(q, instr);
> check(instr_is_branch_to_addr(p, addr));
> check(instr_is_branch_to_addr(q, addr));
> - check(*q == ppc_inst(0x43ff8000));
> + check(ppc_inst_equal(*q, ppc_inst(0x43ff8000)));
>
> /* Maximum positive case, move x to x - 32 KB + 4 */
> p = buf + 0x8000;
> @@ -666,7 +666,7 @@ static void __init test_translate_branch(void)
> patch_instruction(q, instr);
> check(instr_is_branch_to_addr(p, addr));
> check(instr_is_branch_to_addr(q, addr));
> - check(*q == ppc_inst(0x43ff7ffc));
> + check(ppc_inst_equal(*q, ppc_inst(0x43ff7ffc)));
>
> /* Jump to x + 12 KB moved to x + 20 KB */
> p = buf;
> diff --git a/arch/powerpc/lib/test_emulate_step.c
> b/arch/powerpc/lib/test_emulate_step.c
> index 60f7eb24d742..16387a9bfda0 100644
> --- a/arch/powerpc/lib/test_emulate_step.c
> +++ b/arch/powerpc/lib/test_emulate_step.c
> @@ -865,7 +865,7 @@ static int __init execute_compute_instr(struct pt_regs
> *regs,
> extern int exec_instr(struct pt_regs *regs);
> extern s32 patch__exec_instr;
>
> - if (!regs || !instr)
> + if (!regs || !ppc_inst_val(instr))
This change should go in to below patch,
[PATCH v5 06/21] powerpc: Use an accessor for instructions
-- Bala
> return -EINVAL;
>
> /* Patch the NOP with the actual instruction */
> diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
> index 3c1fb46bfacf..f6c87d3d53ea 100644
> --- a/arch/powerpc/xmon/xmon.c
> +++ b/arch/powerpc/xmon/xmon.c
> @@ -950,7 +950,7 @@ static void remove_bpts(void)
> if ((bp->enabled & (BP_TRAP|BP_CIABR)) != BP_TRAP)
> continue;
> if (mread(bp->address, &instr, 4) == 4
> - && instr == ppc_inst(bpinstr)
> + && ppc_inst_equal(instr, ppc_inst(bpinstr))
> && patch_instruction(
> (unsigned int *)bp->address, bp->instr[0]) != 0)
> printf("Couldn't remove breakpoint at %lx\n",
> @@ -2860,7 +2860,7 @@ generic_inst_dump(unsigned long adr, long count, int
> praddr,
> break;
> }
> inst = ppc_inst(GETWORD(val));
> - if (adr > first_adr && inst == last_inst) {
> + if (adr > first_adr && ppc_inst_equal(inst, last_inst)) {
> if (!dotted) {
> printf(" ...\n");
> dotted = 1;
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 07/21] powerpc: Use a function for byte swapping instructions
2020-04-06 8:09 ` [PATCH v5 07/21] powerpc: Use a function for byte swapping instructions Jordan Niethe
@ 2020-04-07 7:42 ` Balamuruhan S
0 siblings, 0 replies; 71+ messages in thread
From: Balamuruhan S @ 2020-04-07 7:42 UTC (permalink / raw)
To: Jordan Niethe, linuxppc-dev; +Cc: alistair, npiggin, dja
On Mon, 2020-04-06 at 18:09 +1000, Jordan Niethe wrote:
> Use a function for byte swapping instructions in preparation of a more
> complicated instruction type.
Reviewed-by: Balamuruhan S <bala24@linux.ibm.com>
>
> Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> ---
> arch/powerpc/include/asm/inst.h | 5 +++++
> arch/powerpc/kernel/align.c | 2 +-
> 2 files changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/arch/powerpc/include/asm/inst.h
> b/arch/powerpc/include/asm/inst.h
> index 15f570bef936..78eb1481f1f6 100644
> --- a/arch/powerpc/include/asm/inst.h
> +++ b/arch/powerpc/include/asm/inst.h
> @@ -18,4 +18,9 @@ static inline int ppc_inst_opcode(u32 x)
> return x >> 26;
> }
>
> +static inline u32 ppc_inst_swab(u32 x)
> +{
> + return ppc_inst(swab32(ppc_inst_val(x)));
> +}
> +
> #endif /* _ASM_INST_H */
> diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
> index a83d32c6513d..46870cf6a6dc 100644
> --- a/arch/powerpc/kernel/align.c
> +++ b/arch/powerpc/kernel/align.c
> @@ -310,7 +310,7 @@ int fix_alignment(struct pt_regs *regs)
> /* We don't handle PPC little-endian any more... */
> if (cpu_has_feature(CPU_FTR_PPC_LE))
> return -EIO;
> - instr = swab32(instr);
> + instr = ppc_inst_swab(instr);
> }
>
> #ifdef CONFIG_SPE
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 04/21] powerpc: Use a macro for creating instructions from u32s
2020-04-07 6:40 ` Balamuruhan S
@ 2020-04-07 8:27 ` Jordan Niethe
0 siblings, 0 replies; 71+ messages in thread
From: Jordan Niethe @ 2020-04-07 8:27 UTC (permalink / raw)
To: Balamuruhan S
Cc: Alistair Popple, linuxppc-dev, Nicholas Piggin, Daniel Axtens
On Tue, Apr 7, 2020 at 4:40 PM Balamuruhan S <bala24@linux.ibm.com> wrote:
>
> On Mon, 2020-04-06 at 18:09 +1000, Jordan Niethe wrote:
> > In preparation for instructions having a more complex data type start
> > using a macro, ppc_inst(), for making an instruction out of a u32. A
> > macro is used so that instructions can be used as initializer elements.
> > Currently this does nothing, but it will allow for creating a data type
> > that can represent prefixed instructions.
> >
> > Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> > ---
> > v4: New to series
> > v5: - Rename PPC_INST() -> ppc_inst().
> > - Use on epapr_paravirt.c, kgdb.c
> > ---
> > arch/powerpc/include/asm/code-patching.h | 3 +-
> > arch/powerpc/include/asm/inst.h | 11 +++++
> > arch/powerpc/kernel/align.c | 1 +
> > arch/powerpc/kernel/epapr_paravirt.c | 5 ++-
> > arch/powerpc/kernel/hw_breakpoint.c | 3 +-
> > arch/powerpc/kernel/jump_label.c | 3 +-
> > arch/powerpc/kernel/kgdb.c | 5 ++-
> > arch/powerpc/kernel/kprobes.c | 5 ++-
> > arch/powerpc/kernel/module_64.c | 3 +-
> > arch/powerpc/kernel/optprobes.c | 31 ++++++-------
> > arch/powerpc/kernel/security.c | 9 ++--
> > arch/powerpc/kernel/trace/ftrace.c | 25 ++++++-----
> > arch/powerpc/kernel/uprobes.c | 1 +
> > arch/powerpc/kvm/emulate_loadstore.c | 2 +-
> > arch/powerpc/lib/code-patching.c | 57 ++++++++++++------------
> > arch/powerpc/lib/feature-fixups.c | 39 ++++++++--------
> > arch/powerpc/lib/test_emulate_step.c | 39 ++++++++--------
> > arch/powerpc/xmon/xmon.c | 7 +--
> > 18 files changed, 138 insertions(+), 111 deletions(-)
> > create mode 100644 arch/powerpc/include/asm/inst.h
> >
> > diff --git a/arch/powerpc/include/asm/code-patching.h
> > b/arch/powerpc/include/asm/code-patching.h
> > index 351dda7215b6..48e021957ee5 100644
> > --- a/arch/powerpc/include/asm/code-patching.h
> > +++ b/arch/powerpc/include/asm/code-patching.h
> > @@ -11,6 +11,7 @@
> > #include <linux/string.h>
> > #include <linux/kallsyms.h>
> > #include <asm/asm-compat.h>
> > +#include <asm/inst.h>
> >
> > /* Flags for create_branch:
> > * "b" == create_branch(addr, target, 0);
> > @@ -48,7 +49,7 @@ static inline int patch_branch_site(s32 *site, unsigned
> > long target, int flags)
> > static inline int modify_instruction(unsigned int *addr, unsigned int clr,
> > unsigned int set)
> > {
> > - return patch_instruction(addr, (*addr & ~clr) | set);
> > + return patch_instruction(addr, ppc_inst((*addr & ~clr) | set));
> > }
> >
> > static inline int modify_instruction_site(s32 *site, unsigned int clr,
> > unsigned int set)
> > diff --git a/arch/powerpc/include/asm/inst.h
> > b/arch/powerpc/include/asm/inst.h
> > new file mode 100644
> > index 000000000000..5298ba33b6e5
> > --- /dev/null
> > +++ b/arch/powerpc/include/asm/inst.h
> > @@ -0,0 +1,11 @@
> > +/* SPDX-License-Identifier: GPL-2.0-or-later */
> > +#ifndef _ASM_INST_H
> > +#define _ASM_INST_H
> > +
> > +/*
> > + * Instruction data type for POWER
> > + */
> > +
> > +#define ppc_inst(x) (x)
> > +
> > +#endif /* _ASM_INST_H */
> > diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
> > index 92045ed64976..86e9bf62f18c 100644
> > --- a/arch/powerpc/kernel/align.c
> > +++ b/arch/powerpc/kernel/align.c
> > @@ -24,6 +24,7 @@
> > #include <asm/disassemble.h>
> > #include <asm/cpu_has_feature.h>
> > #include <asm/sstep.h>
> > +#include <asm/inst.h>
> >
> > struct aligninfo {
> > unsigned char len;
> > diff --git a/arch/powerpc/kernel/epapr_paravirt.c
> > b/arch/powerpc/kernel/epapr_paravirt.c
> > index 9d32158ce36f..c53e863fb484 100644
> > --- a/arch/powerpc/kernel/epapr_paravirt.c
> > +++ b/arch/powerpc/kernel/epapr_paravirt.c
> > @@ -11,6 +11,7 @@
> > #include <asm/cacheflush.h>
> > #include <asm/code-patching.h>
> > #include <asm/machdep.h>
> > +#include <asm/inst.h>
> >
> > #if !defined(CONFIG_64BIT) || defined(CONFIG_PPC_BOOK3E_64)
> > extern void epapr_ev_idle(void);
> > @@ -37,9 +38,9 @@ static int __init early_init_dt_scan_epapr(unsigned long
> > node,
> >
> > for (i = 0; i < (len / 4); i++) {
> > u32 inst = be32_to_cpu(insts[i]);
> > - patch_instruction(epapr_hypercall_start + i, inst);
> > + patch_instruction(epapr_hypercall_start + i, ppc_inst(inst));
> > #if !defined(CONFIG_64BIT) || defined(CONFIG_PPC_BOOK3E_64)
> > - patch_instruction(epapr_ev_idle_start + i, inst);
> > + patch_instruction(epapr_ev_idle_start + i, ppc_inst(inst));
>
>
> can we do it once while assigning inst ?
>
> u32 inst = ppc_inst(be32_to_cpu(insts[i]));
Yeah that would be better.
>
> -- Bala
>
> > #endif
> > }
> >
> > diff --git a/arch/powerpc/kernel/hw_breakpoint.c
> > b/arch/powerpc/kernel/hw_breakpoint.c
> > index 2462cd7c565c..79f51f182a83 100644
> > --- a/arch/powerpc/kernel/hw_breakpoint.c
> > +++ b/arch/powerpc/kernel/hw_breakpoint.c
> > @@ -24,6 +24,7 @@
> > #include <asm/debug.h>
> > #include <asm/debugfs.h>
> > #include <asm/hvcall.h>
> > +#include <asm/inst.h>
> > #include <linux/uaccess.h>
> >
> > /*
> > @@ -243,7 +244,7 @@ dar_range_overlaps(unsigned long dar, int size, struct
> > arch_hw_breakpoint *info)
> > static bool stepping_handler(struct pt_regs *regs, struct perf_event *bp,
> > struct arch_hw_breakpoint *info)
> > {
> > - unsigned int instr = 0;
> > + unsigned int instr = ppc_inst(0);
> > int ret, type, size;
> > struct instruction_op op;
> > unsigned long addr = info->address;
> > diff --git a/arch/powerpc/kernel/jump_label.c
> > b/arch/powerpc/kernel/jump_label.c
> > index ca37702bde97..daa4afce7ec8 100644
> > --- a/arch/powerpc/kernel/jump_label.c
> > +++ b/arch/powerpc/kernel/jump_label.c
> > @@ -6,6 +6,7 @@
> > #include <linux/kernel.h>
> > #include <linux/jump_label.h>
> > #include <asm/code-patching.h>
> > +#include <asm/inst.h>
> >
> > void arch_jump_label_transform(struct jump_entry *entry,
> > enum jump_label_type type)
> > @@ -15,5 +16,5 @@ void arch_jump_label_transform(struct jump_entry *entry,
> > if (type == JUMP_LABEL_JMP)
> > patch_branch(addr, entry->target, 0);
> > else
> > - patch_instruction(addr, PPC_INST_NOP);
> > + patch_instruction(addr, ppc_inst(PPC_INST_NOP));
> > }
> > diff --git a/arch/powerpc/kernel/kgdb.c b/arch/powerpc/kernel/kgdb.c
> > index 7dd55eb1259d..a6b38a19133f 100644
> > --- a/arch/powerpc/kernel/kgdb.c
> > +++ b/arch/powerpc/kernel/kgdb.c
> > @@ -26,6 +26,7 @@
> > #include <asm/debug.h>
> > #include <asm/code-patching.h>
> > #include <linux/slab.h>
> > +#include <asm/inst.h>
> >
> > /*
> > * This table contains the mapping between PowerPC hardware trap types, and
> > @@ -424,7 +425,7 @@ int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
> > if (err)
> > return err;
> >
> > - err = patch_instruction(addr, BREAK_INSTR);
> > + err = patch_instruction(addr, ppc_inst(BREAK_INSTR));
> > if (err)
> > return -EFAULT;
> >
> > @@ -439,7 +440,7 @@ int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
> > unsigned int instr = *(unsigned int *)bpt->saved_instr;
> > unsigned int *addr = (unsigned int *)bpt->bpt_addr;
> >
> > - err = patch_instruction(addr, instr);
> > + err = patch_instruction(addr, ppc_inst(instr));
> > if (err)
> > return -EFAULT;
> >
> > diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
> > index 2d27ec4feee4..a1a3686f41c6 100644
> > --- a/arch/powerpc/kernel/kprobes.c
> > +++ b/arch/powerpc/kernel/kprobes.c
> > @@ -23,6 +23,7 @@
> > #include <asm/cacheflush.h>
> > #include <asm/sstep.h>
> > #include <asm/sections.h>
> > +#include <asm/inst.h>
> > #include <linux/uaccess.h>
> >
> > DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
> > @@ -138,13 +139,13 @@ NOKPROBE_SYMBOL(arch_prepare_kprobe);
> >
> > void arch_arm_kprobe(struct kprobe *p)
> > {
> > - patch_instruction(p->addr, BREAKPOINT_INSTRUCTION);
> > + patch_instruction(p->addr, ppc_inst(BREAKPOINT_INSTRUCTION));
> > }
> > NOKPROBE_SYMBOL(arch_arm_kprobe);
> >
> > void arch_disarm_kprobe(struct kprobe *p)
> > {
> > - patch_instruction(p->addr, p->opcode);
> > + patch_instruction(p->addr, ppc_inst(p->opcode));
> > }
> > NOKPROBE_SYMBOL(arch_disarm_kprobe);
> >
> > diff --git a/arch/powerpc/kernel/module_64.c
> > b/arch/powerpc/kernel/module_64.c
> > index 007606a48fd9..7fd6b29edcb2 100644
> > --- a/arch/powerpc/kernel/module_64.c
> > +++ b/arch/powerpc/kernel/module_64.c
> > @@ -20,6 +20,7 @@
> > #include <linux/sort.h>
> > #include <asm/setup.h>
> > #include <asm/sections.h>
> > +#include <asm/inst.h>
> >
> > /* FIXME: We don't do .init separately. To do this, we'd need to have
> > a separate r2 value in the init and core section, and stub between
> > @@ -506,7 +507,7 @@ static int restore_r2(const char *name, u32 *instruction,
> > struct module *me)
> > * "link" branches and they don't return, so they don't need the r2
> > * restore afterwards.
> > */
> > - if (!instr_is_relative_link_branch(*prev_insn))
> > + if (!instr_is_relative_link_branch(ppc_inst(*prev_insn)))
> > return 1;
> >
> > if (*instruction != PPC_INST_NOP) {
> > diff --git a/arch/powerpc/kernel/optprobes.c
> > b/arch/powerpc/kernel/optprobes.c
> > index 445b3dad82dc..3b33ebf18859 100644
> > --- a/arch/powerpc/kernel/optprobes.c
> > +++ b/arch/powerpc/kernel/optprobes.c
> > @@ -16,6 +16,7 @@
> > #include <asm/code-patching.h>
> > #include <asm/sstep.h>
> > #include <asm/ppc-opcode.h>
> > +#include <asm/inst.h>
> >
> > #define TMPL_CALL_HDLR_IDX \
> > (optprobe_template_call_handler - optprobe_template_entry)
> > @@ -147,13 +148,13 @@ void arch_remove_optimized_kprobe(struct
> > optimized_kprobe *op)
> > void patch_imm32_load_insns(unsigned int val, kprobe_opcode_t *addr)
> > {
> > /* addis r4,0,(insn)@h */
> > - patch_instruction(addr, PPC_INST_ADDIS | ___PPC_RT(4) |
> > - ((val >> 16) & 0xffff));
> > + patch_instruction(addr, ppc_inst(PPC_INST_ADDIS | ___PPC_RT(4) |
> > + ((val >> 16) & 0xffff)));
> > addr++;
> >
> > /* ori r4,r4,(insn)@l */
> > - patch_instruction(addr, PPC_INST_ORI | ___PPC_RA(4) |
> > - ___PPC_RS(4) | (val & 0xffff));
> > + patch_instruction(addr, ppc_inst(PPC_INST_ORI | ___PPC_RA(4) |
> > + ___PPC_RS(4) | (val & 0xffff)));
> > }
> >
> > /*
> > @@ -163,28 +164,28 @@ void patch_imm32_load_insns(unsigned int val,
> > kprobe_opcode_t *addr)
> > void patch_imm64_load_insns(unsigned long val, kprobe_opcode_t *addr)
> > {
> > /* lis r3,(op)@highest */
> > - patch_instruction(addr, PPC_INST_ADDIS | ___PPC_RT(3) |
> > - ((val >> 48) & 0xffff));
> > + patch_instruction(addr, ppc_inst(PPC_INST_ADDIS | ___PPC_RT(3) |
> > + ((val >> 48) & 0xffff)));
> > addr++;
> >
> > /* ori r3,r3,(op)@higher */
> > - patch_instruction(addr, PPC_INST_ORI | ___PPC_RA(3) |
> > - ___PPC_RS(3) | ((val >> 32) & 0xffff));
> > + patch_instruction(addr, ppc_inst(PPC_INST_ORI | ___PPC_RA(3) |
> > + ___PPC_RS(3) | ((val >> 32) & 0xffff)));
> > addr++;
> >
> > /* rldicr r3,r3,32,31 */
> > - patch_instruction(addr, PPC_INST_RLDICR | ___PPC_RA(3) |
> > - ___PPC_RS(3) | __PPC_SH64(32) | __PPC_ME64(31));
> > + patch_instruction(addr, ppc_inst(PPC_INST_RLDICR | ___PPC_RA(3) |
> > + ___PPC_RS(3) | __PPC_SH64(32) | __PPC_ME64(31)));
> > addr++;
> >
> > /* oris r3,r3,(op)@h */
> > - patch_instruction(addr, PPC_INST_ORIS | ___PPC_RA(3) |
> > - ___PPC_RS(3) | ((val >> 16) & 0xffff));
> > + patch_instruction(addr, ppc_inst(PPC_INST_ORIS | ___PPC_RA(3) |
> > + ___PPC_RS(3) | ((val >> 16) & 0xffff)));
> > addr++;
> >
> > /* ori r3,r3,(op)@l */
> > - patch_instruction(addr, PPC_INST_ORI | ___PPC_RA(3) |
> > - ___PPC_RS(3) | (val & 0xffff));
> > + patch_instruction(addr, ppc_inst(PPC_INST_ORI | ___PPC_RA(3) |
> > + ___PPC_RS(3) | (val & 0xffff)));
> > }
> >
> > int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe
> > *p)
> > @@ -230,7 +231,7 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe
> > *op, struct kprobe *p)
> > size = (TMPL_END_IDX * sizeof(kprobe_opcode_t)) / sizeof(int);
> > pr_devel("Copying template to %p, size %lu\n", buff, size);
> > for (i = 0; i < size; i++) {
> > - rc = patch_instruction(buff + i, *(optprobe_template_entry +
> > i));
> > + rc = patch_instruction(buff + i,
> > ppc_inst(*(optprobe_template_entry + i)));
> > if (rc < 0)
> > goto error;
> > }
> > diff --git a/arch/powerpc/kernel/security.c b/arch/powerpc/kernel/security.c
> > index bd70f5be1c27..81a288b1a603 100644
> > --- a/arch/powerpc/kernel/security.c
> > +++ b/arch/powerpc/kernel/security.c
> > @@ -14,6 +14,7 @@
> > #include <asm/debugfs.h>
> > #include <asm/security_features.h>
> > #include <asm/setup.h>
> > +#include <asm/inst.h>
> >
> >
> > u64 powerpc_security_features __read_mostly = SEC_FTR_DEFAULT;
> > @@ -403,9 +404,9 @@ static void toggle_count_cache_flush(bool enable)
> > enable = false;
> >
> > if (!enable) {
> > - patch_instruction_site(&patch__call_flush_count_cache,
> > PPC_INST_NOP);
> > + patch_instruction_site(&patch__call_flush_count_cache,
> > ppc_inst(PPC_INST_NOP));
> > #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
> > - patch_instruction_site(&patch__call_kvm_flush_link_stack,
> > PPC_INST_NOP);
> > + patch_instruction_site(&patch__call_kvm_flush_link_stack,
> > ppc_inst(PPC_INST_NOP));
> > #endif
> > pr_info("link-stack-flush: software flush disabled.\n");
> > link_stack_flush_enabled = false;
> > @@ -428,7 +429,7 @@ static void toggle_count_cache_flush(bool enable)
> >
> > // If we just need to flush the link stack, patch an early return
> > if (!security_ftr_enabled(SEC_FTR_FLUSH_COUNT_CACHE)) {
> > - patch_instruction_site(&patch__flush_link_stack_return,
> > PPC_INST_BLR);
> > + patch_instruction_site(&patch__flush_link_stack_return,
> > ppc_inst(PPC_INST_BLR));
> > no_count_cache_flush();
> > return;
> > }
> > @@ -439,7 +440,7 @@ static void toggle_count_cache_flush(bool enable)
> > return;
> > }
> >
> > - patch_instruction_site(&patch__flush_count_cache_return, PPC_INST_BLR);
> > + patch_instruction_site(&patch__flush_count_cache_return,
> > ppc_inst(PPC_INST_BLR));
> > count_cache_flush_type = COUNT_CACHE_FLUSH_HW;
> > pr_info("count-cache-flush: hardware assisted flush sequence
> > enabled\n");
> > }
> > diff --git a/arch/powerpc/kernel/trace/ftrace.c
> > b/arch/powerpc/kernel/trace/ftrace.c
> > index 4dcb379133f8..47233e671c18 100644
> > --- a/arch/powerpc/kernel/trace/ftrace.c
> > +++ b/arch/powerpc/kernel/trace/ftrace.c
> > @@ -27,6 +27,7 @@
> > #include <asm/code-patching.h>
> > #include <asm/ftrace.h>
> > #include <asm/syscall.h>
> > +#include <asm/inst.h>
> >
> >
> > #ifdef CONFIG_DYNAMIC_FTRACE
> > @@ -161,7 +162,7 @@ __ftrace_make_nop(struct module *mod,
> >
> > #ifdef CONFIG_MPROFILE_KERNEL
> > /* When using -mkernel_profile there is no load to jump over */
> > - pop = PPC_INST_NOP;
> > + pop = ppc_inst(PPC_INST_NOP);
> >
> > if (probe_kernel_read(&op, (void *)(ip - 4), 4)) {
> > pr_err("Fetching instruction at %lx failed.\n", ip - 4);
> > @@ -169,7 +170,7 @@ __ftrace_make_nop(struct module *mod,
> > }
> >
> > /* We expect either a mflr r0, or a std r0, LRSAVE(r1) */
> > - if (op != PPC_INST_MFLR && op != PPC_INST_STD_LR) {
> > + if (op != ppc_inst(PPC_INST_MFLR) && op != ppc_inst(PPC_INST_STD_LR)) {
> > pr_err("Unexpected instruction %08x around bl _mcount\n", op);
> > return -EINVAL;
> > }
> > @@ -188,7 +189,7 @@ __ftrace_make_nop(struct module *mod,
> > * Use a b +8 to jump over the load.
> > */
> >
> > - pop = PPC_INST_BRANCH | 8; /* b +8 */
> > + pop = ppc_inst(PPC_INST_BRANCH | 8); /* b +8 */
> >
> > /*
> > * Check what is in the next instruction. We can see ld r2,40(r1), but
> > @@ -199,7 +200,7 @@ __ftrace_make_nop(struct module *mod,
> > return -EFAULT;
> > }
> >
> > - if (op != PPC_INST_LD_TOC) {
> > + if (op != ppc_inst(PPC_INST_LD_TOC)) {
> > pr_err("Expected %08x found %08x\n", PPC_INST_LD_TOC, op);
> > return -EINVAL;
> > }
> > @@ -275,7 +276,7 @@ __ftrace_make_nop(struct module *mod,
> > return -EINVAL;
> > }
> >
> > - op = PPC_INST_NOP;
> > + op = ppc_inst(PPC_INST_NOP);
> >
> > if (patch_instruction((unsigned int *)ip, op))
> > return -EPERM;
> > @@ -420,7 +421,7 @@ static int __ftrace_make_nop_kernel(struct dyn_ftrace
> > *rec, unsigned long addr)
> > }
> > }
> >
> > - if (patch_instruction((unsigned int *)ip, PPC_INST_NOP)) {
> > + if (patch_instruction((unsigned int *)ip, ppc_inst(PPC_INST_NOP))) {
> > pr_err("Patching NOP failed.\n");
> > return -EPERM;
> > }
> > @@ -442,7 +443,7 @@ int ftrace_make_nop(struct module *mod,
> > if (test_24bit_addr(ip, addr)) {
> > /* within range */
> > old = ftrace_call_replace(ip, addr, 1);
> > - new = PPC_INST_NOP;
> > + new = ppc_inst(PPC_INST_NOP);
> > return ftrace_modify_code(ip, old, new);
> > } else if (core_kernel_text(ip))
> > return __ftrace_make_nop_kernel(rec, addr);
> > @@ -496,7 +497,7 @@ expected_nop_sequence(void *ip, unsigned int op0,
> > unsigned int op1)
> > * The load offset is different depending on the ABI. For simplicity
> > * just mask it out when doing the compare.
> > */
> > - if ((op0 != 0x48000008) || ((op1 & 0xffff0000) != 0xe8410000))
> > + if ((op0 != ppc_inst(0x48000008)) || ((op1 & 0xffff0000) !=
> > 0xe8410000))
> > return 0;
> > return 1;
> > }
> > @@ -505,7 +506,7 @@ static int
> > expected_nop_sequence(void *ip, unsigned int op0, unsigned int op1)
> > {
> > /* look for patched "NOP" on ppc64 with -mprofile-kernel */
> > - if (op0 != PPC_INST_NOP)
> > + if (op0 != ppc_inst(PPC_INST_NOP))
> > return 0;
> > return 1;
> > }
> > @@ -588,7 +589,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long
> > addr)
> > return -EFAULT;
> >
> > /* It should be pointing to a nop */
> > - if (op != PPC_INST_NOP) {
> > + if (op != ppc_inst(PPC_INST_NOP)) {
> > pr_err("Expected NOP but have %x\n", op);
> > return -EINVAL;
> > }
> > @@ -645,7 +646,7 @@ static int __ftrace_make_call_kernel(struct dyn_ftrace
> > *rec, unsigned long addr)
> > return -EFAULT;
> > }
> >
> > - if (op != PPC_INST_NOP) {
> > + if (op != ppc_inst(PPC_INST_NOP)) {
> > pr_err("Unexpected call sequence at %p: %x\n", ip, op);
> > return -EINVAL;
> > }
> > @@ -676,7 +677,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned
> > long addr)
> > */
> > if (test_24bit_addr(ip, addr)) {
> > /* within range */
> > - old = PPC_INST_NOP;
> > + old = ppc_inst(PPC_INST_NOP);
> > new = ftrace_call_replace(ip, addr, 1);
> > return ftrace_modify_code(ip, old, new);
> > } else if (core_kernel_text(ip))
> > diff --git a/arch/powerpc/kernel/uprobes.c b/arch/powerpc/kernel/uprobes.c
> > index 1cfef0e5fec5..31c870287f2b 100644
> > --- a/arch/powerpc/kernel/uprobes.c
> > +++ b/arch/powerpc/kernel/uprobes.c
> > @@ -14,6 +14,7 @@
> > #include <linux/kdebug.h>
> >
> > #include <asm/sstep.h>
> > +#include <asm/inst.h>
> >
> > #define UPROBE_TRAP_NR UINT_MAX
> >
> > diff --git a/arch/powerpc/kvm/emulate_loadstore.c
> > b/arch/powerpc/kvm/emulate_loadstore.c
> > index 1139bc56e004..135d0e686622 100644
> > --- a/arch/powerpc/kvm/emulate_loadstore.c
> > +++ b/arch/powerpc/kvm/emulate_loadstore.c
> > @@ -95,7 +95,7 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu)
> >
> > emulated = EMULATE_FAIL;
> > vcpu->arch.regs.msr = vcpu->arch.shared->msr;
> > - if (analyse_instr(&op, &vcpu->arch.regs, inst) == 0) {
> > + if (analyse_instr(&op, &vcpu->arch.regs, ppc_inst(inst)) == 0) {
> > int type = op.type & INSTR_TYPE_MASK;
> > int size = GETSIZE(op.type);
> >
> > diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-
> > patching.c
> > index 4af564aeedf1..fdf0d6ea3575 100644
> > --- a/arch/powerpc/lib/code-patching.c
> > +++ b/arch/powerpc/lib/code-patching.c
> > @@ -17,6 +17,7 @@
> > #include <asm/page.h>
> > #include <asm/code-patching.h>
> > #include <asm/setup.h>
> > +#include <asm/inst.h>
> >
> > static int __patch_instruction(unsigned int *exec_addr, unsigned int instr,
> > unsigned int *patch_addr)
> > @@ -413,37 +414,37 @@ static void __init test_branch_iform(void)
> > addr = (unsigned long)&instr;
> >
> > /* The simplest case, branch to self, no flags */
> > - check(instr_is_branch_iform(0x48000000));
> > + check(instr_is_branch_iform(ppc_inst(0x48000000)));
> > /* All bits of target set, and flags */
> > - check(instr_is_branch_iform(0x4bffffff));
> > + check(instr_is_branch_iform(ppc_inst(0x4bffffff)));
> > /* High bit of opcode set, which is wrong */
> > - check(!instr_is_branch_iform(0xcbffffff));
> > + check(!instr_is_branch_iform(ppc_inst(0xcbffffff)));
> > /* Middle bits of opcode set, which is wrong */
> > - check(!instr_is_branch_iform(0x7bffffff));
> > + check(!instr_is_branch_iform(ppc_inst(0x7bffffff)));
> >
> > /* Simplest case, branch to self with link */
> > - check(instr_is_branch_iform(0x48000001));
> > + check(instr_is_branch_iform(ppc_inst(0x48000001)));
> > /* All bits of targets set */
> > - check(instr_is_branch_iform(0x4bfffffd));
> > + check(instr_is_branch_iform(ppc_inst(0x4bfffffd)));
> > /* Some bits of targets set */
> > - check(instr_is_branch_iform(0x4bff00fd));
> > + check(instr_is_branch_iform(ppc_inst(0x4bff00fd)));
> > /* Must be a valid branch to start with */
> > - check(!instr_is_branch_iform(0x7bfffffd));
> > + check(!instr_is_branch_iform(ppc_inst(0x7bfffffd)));
> >
> > /* Absolute branch to 0x100 */
> > - instr = 0x48000103;
> > + instr = ppc_inst(0x48000103);
> > check(instr_is_branch_to_addr(&instr, 0x100));
> > /* Absolute branch to 0x420fc */
> > - instr = 0x480420ff;
> > + instr = ppc_inst(0x480420ff);
> > check(instr_is_branch_to_addr(&instr, 0x420fc));
> > /* Maximum positive relative branch, + 20MB - 4B */
> > - instr = 0x49fffffc;
> > + instr = ppc_inst(0x49fffffc);
> > check(instr_is_branch_to_addr(&instr, addr + 0x1FFFFFC));
> > /* Smallest negative relative branch, - 4B */
> > - instr = 0x4bfffffc;
> > + instr = ppc_inst(0x4bfffffc);
> > check(instr_is_branch_to_addr(&instr, addr - 4));
> > /* Largest negative relative branch, - 32 MB */
> > - instr = 0x4a000000;
> > + instr = ppc_inst(0x4a000000);
> > check(instr_is_branch_to_addr(&instr, addr - 0x2000000));
> >
> > /* Branch to self, with link */
> > @@ -477,7 +478,7 @@ static void __init test_branch_iform(void)
> > /* Check flags are masked correctly */
> > err = create_branch(&instr, &instr, addr, 0xFFFFFFFC);
> > check(instr_is_branch_to_addr(&instr, addr));
> > - check(instr == 0x48000000);
> > + check(instr == ppc_inst(0x48000000));
> > }
> >
> > static void __init test_create_function_call(void)
> > @@ -504,28 +505,28 @@ static void __init test_branch_bform(void)
> > addr = (unsigned long)iptr;
> >
> > /* The simplest case, branch to self, no flags */
> > - check(instr_is_branch_bform(0x40000000));
> > + check(instr_is_branch_bform(ppc_inst(0x40000000)));
> > /* All bits of target set, and flags */
> > - check(instr_is_branch_bform(0x43ffffff));
> > + check(instr_is_branch_bform(ppc_inst(0x43ffffff)));
> > /* High bit of opcode set, which is wrong */
> > - check(!instr_is_branch_bform(0xc3ffffff));
> > + check(!instr_is_branch_bform(ppc_inst(0xc3ffffff)));
> > /* Middle bits of opcode set, which is wrong */
> > - check(!instr_is_branch_bform(0x7bffffff));
> > + check(!instr_is_branch_bform(ppc_inst(0x7bffffff)));
> >
> > /* Absolute conditional branch to 0x100 */
> > - instr = 0x43ff0103;
> > + instr = ppc_inst(0x43ff0103);
> > check(instr_is_branch_to_addr(&instr, 0x100));
> > /* Absolute conditional branch to 0x20fc */
> > - instr = 0x43ff20ff;
> > + instr = ppc_inst(0x43ff20ff);
> > check(instr_is_branch_to_addr(&instr, 0x20fc));
> > /* Maximum positive relative conditional branch, + 32 KB - 4B */
> > - instr = 0x43ff7ffc;
> > + instr = ppc_inst(0x43ff7ffc);
> > check(instr_is_branch_to_addr(&instr, addr + 0x7FFC));
> > /* Smallest negative relative conditional branch, - 4B */
> > - instr = 0x43fffffc;
> > + instr = ppc_inst(0x43fffffc);
> > check(instr_is_branch_to_addr(&instr, addr - 4));
> > /* Largest negative relative conditional branch, - 32 KB */
> > - instr = 0x43ff8000;
> > + instr = ppc_inst(0x43ff8000);
> > check(instr_is_branch_to_addr(&instr, addr - 0x8000));
> >
> > /* All condition code bits set & link */
> > @@ -562,7 +563,7 @@ static void __init test_branch_bform(void)
> > /* Check flags are masked correctly */
> > err = create_cond_branch(&instr, iptr, addr, 0xFFFFFFFC);
> > check(instr_is_branch_to_addr(&instr, addr));
> > - check(instr == 0x43FF0000);
> > + check(instr == ppc_inst(0x43FF0000));
> > }
> >
> > static void __init test_translate_branch(void)
> > @@ -596,7 +597,7 @@ static void __init test_translate_branch(void)
> > patch_instruction(q, instr);
> > check(instr_is_branch_to_addr(p, addr));
> > check(instr_is_branch_to_addr(q, addr));
> > - check(*q == 0x4a000000);
> > + check(*q == ppc_inst(0x4a000000));
> >
> > /* Maximum positive case, move x to x - 32 MB + 4 */
> > p = buf + 0x2000000;
> > @@ -607,7 +608,7 @@ static void __init test_translate_branch(void)
> > patch_instruction(q, instr);
> > check(instr_is_branch_to_addr(p, addr));
> > check(instr_is_branch_to_addr(q, addr));
> > - check(*q == 0x49fffffc);
> > + check(*q == ppc_inst(0x49fffffc));
> >
> > /* Jump to x + 16 MB moved to x + 20 MB */
> > p = buf;
> > @@ -653,7 +654,7 @@ static void __init test_translate_branch(void)
> > patch_instruction(q, instr);
> > check(instr_is_branch_to_addr(p, addr));
> > check(instr_is_branch_to_addr(q, addr));
> > - check(*q == 0x43ff8000);
> > + check(*q == ppc_inst(0x43ff8000));
> >
> > /* Maximum positive case, move x to x - 32 KB + 4 */
> > p = buf + 0x8000;
> > @@ -665,7 +666,7 @@ static void __init test_translate_branch(void)
> > patch_instruction(q, instr);
> > check(instr_is_branch_to_addr(p, addr));
> > check(instr_is_branch_to_addr(q, addr));
> > - check(*q == 0x43ff7ffc);
> > + check(*q == ppc_inst(0x43ff7ffc));
> >
> > /* Jump to x + 12 KB moved to x + 20 KB */
> > p = buf;
> > diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-
> > fixups.c
> > index b129d7b4e7dd..6e7479b8887a 100644
> > --- a/arch/powerpc/lib/feature-fixups.c
> > +++ b/arch/powerpc/lib/feature-fixups.c
> > @@ -21,6 +21,7 @@
> > #include <asm/setup.h>
> > #include <asm/security_features.h>
> > #include <asm/firmware.h>
> > +#include <asm/inst.h>
> >
> > struct fixup_entry {
> > unsigned long mask;
> > @@ -89,7 +90,7 @@ static int patch_feature_section(unsigned long value,
> > struct fixup_entry *fcur)
> > }
> >
> > for (; dest < end; dest++)
> > - raw_patch_instruction(dest, PPC_INST_NOP);
> > + raw_patch_instruction(dest, ppc_inst(PPC_INST_NOP));
> >
> > return 0;
> > }
> > @@ -146,15 +147,15 @@ static void do_stf_entry_barrier_fixups(enum
> > stf_barrier_type types)
> >
> > pr_devel("patching dest %lx\n", (unsigned long)dest);
> >
> > - patch_instruction(dest, instrs[0]);
> > + patch_instruction(dest, ppc_inst(instrs[0]));
> >
> > if (types & STF_BARRIER_FALLBACK)
> > patch_branch(dest + 1, (unsigned
> > long)&stf_barrier_fallback,
> > BRANCH_SET_LINK);
> > else
> > - patch_instruction(dest + 1, instrs[1]);
> > + patch_instruction(dest + 1, ppc_inst(instrs[1]));
> >
> > - patch_instruction(dest + 2, instrs[2]);
> > + patch_instruction(dest + 2, ppc_inst(instrs[2]));
> > }
> >
> > printk(KERN_DEBUG "stf-barrier: patched %d entry locations (%s
> > barrier)\n", i,
> > @@ -207,12 +208,12 @@ static void do_stf_exit_barrier_fixups(enum
> > stf_barrier_type types)
> >
> > pr_devel("patching dest %lx\n", (unsigned long)dest);
> >
> > - patch_instruction(dest, instrs[0]);
> > - patch_instruction(dest + 1, instrs[1]);
> > - patch_instruction(dest + 2, instrs[2]);
> > - patch_instruction(dest + 3, instrs[3]);
> > - patch_instruction(dest + 4, instrs[4]);
> > - patch_instruction(dest + 5, instrs[5]);
> > + patch_instruction(dest, ppc_inst(instrs[0]));
> > + patch_instruction(dest + 1, ppc_inst(instrs[1]));
> > + patch_instruction(dest + 2, ppc_inst(instrs[2]));
> > + patch_instruction(dest + 3, ppc_inst(instrs[3]));
> > + patch_instruction(dest + 4, ppc_inst(instrs[4]));
> > + patch_instruction(dest + 5, ppc_inst(instrs[5]));
> > }
> > printk(KERN_DEBUG "stf-barrier: patched %d exit locations (%s
> > barrier)\n", i,
> > (types == STF_BARRIER_NONE) ? "no" :
> > @@ -260,9 +261,9 @@ void do_rfi_flush_fixups(enum l1d_flush_type types)
> >
> > pr_devel("patching dest %lx\n", (unsigned long)dest);
> >
> > - patch_instruction(dest, instrs[0]);
> > - patch_instruction(dest + 1, instrs[1]);
> > - patch_instruction(dest + 2, instrs[2]);
> > + patch_instruction(dest, ppc_inst(instrs[0]));
> > + patch_instruction(dest + 1, ppc_inst(instrs[1]));
> > + patch_instruction(dest + 2, ppc_inst(instrs[2]));
> > }
> >
> > printk(KERN_DEBUG "rfi-flush: patched %d locations (%s flush)\n", i,
> > @@ -295,7 +296,7 @@ void do_barrier_nospec_fixups_range(bool enable, void
> > *fixup_start, void *fixup_
> > dest = (void *)start + *start;
> >
> > pr_devel("patching dest %lx\n", (unsigned long)dest);
> > - patch_instruction(dest, instr);
> > + patch_instruction(dest, ppc_inst(instr));
> > }
> >
> > printk(KERN_DEBUG "barrier-nospec: patched %d locations\n", i);
> > @@ -338,8 +339,8 @@ void do_barrier_nospec_fixups_range(bool enable, void
> > *fixup_start, void *fixup_
> > dest = (void *)start + *start;
> >
> > pr_devel("patching dest %lx\n", (unsigned long)dest);
> > - patch_instruction(dest, instr[0]);
> > - patch_instruction(dest + 1, instr[1]);
> > + patch_instruction(dest, ppc_inst(instr[0]));
> > + patch_instruction(dest + 1, ppc_inst(instr[1]));
> > }
> >
> > printk(KERN_DEBUG "barrier-nospec: patched %d locations\n", i);
> > @@ -353,7 +354,7 @@ static void patch_btb_flush_section(long *curr)
> > end = (void *)curr + *(curr + 1);
> > for (; start < end; start++) {
> > pr_devel("patching dest %lx\n", (unsigned long)start);
> > - patch_instruction(start, PPC_INST_NOP);
> > + patch_instruction(start, ppc_inst(PPC_INST_NOP));
> > }
> > }
> >
> > @@ -382,7 +383,7 @@ void do_lwsync_fixups(unsigned long value, void
> > *fixup_start, void *fixup_end)
> >
> > for (; start < end; start++) {
> > dest = (void *)start + *start;
> > - raw_patch_instruction(dest, PPC_INST_LWSYNC);
> > + raw_patch_instruction(dest, ppc_inst(PPC_INST_LWSYNC));
> > }
> > }
> >
> > @@ -400,7 +401,7 @@ static void do_final_fixups(void)
> > length = (__end_interrupts - _stext) / sizeof(int);
> >
> > while (length--) {
> > - raw_patch_instruction(dest, *src);
> > + raw_patch_instruction(dest, ppc_inst(*src));
> > src++;
> > dest++;
> > }
> > diff --git a/arch/powerpc/lib/test_emulate_step.c
> > b/arch/powerpc/lib/test_emulate_step.c
> > index 42347067739c..88b17226a493 100644
> > --- a/arch/powerpc/lib/test_emulate_step.c
> > +++ b/arch/powerpc/lib/test_emulate_step.c
> > @@ -11,6 +11,7 @@
> > #include <asm/sstep.h>
> > #include <asm/ppc-opcode.h>
> > #include <asm/code-patching.h>
> > +#include <asm/inst.h>
> >
> > #define IMM_L(i) ((uintptr_t)(i) & 0xffff)
> >
> > @@ -18,40 +19,40 @@
> > * Defined with TEST_ prefix so it does not conflict with other
> > * definitions.
> > */
> > -#define TEST_LD(r, base, i) (PPC_INST_LD | ___PPC_RT(r) | \
> > +#define TEST_LD(r, base, i) ppc_inst(PPC_INST_LD | ___PPC_RT(r) |
> > \
> > ___PPC_RA(base) | IMM_L(i))
> > -#define TEST_LWZ(r, base, i) (PPC_INST_LWZ | ___PPC_RT(r) | \
> > +#define TEST_LWZ(r, base, i) ppc_inst(PPC_INST_LWZ | ___PPC_RT(r) |
> > \
> > ___PPC_RA(base) | IMM_L(i))
> > -#define TEST_LWZX(t, a, b) (PPC_INST_LWZX | ___PPC_RT(t) | \
> > +#define TEST_LWZX(t, a, b) ppc_inst(PPC_INST_LWZX | ___PPC_RT(t) |
> > \
> > ___PPC_RA(a) | ___PPC_RB(b))
> > -#define TEST_STD(r, base, i) (PPC_INST_STD | ___PPC_RS(r) | \
> > +#define TEST_STD(r, base, i) ppc_inst(PPC_INST_STD | ___PPC_RS(r) |
> > \
> > ___PPC_RA(base) | ((i) & 0xfffc))
> > -#define TEST_LDARX(t, a, b, eh) (PPC_INST_LDARX | ___PPC_RT(t) | \
> > +#define TEST_LDARX(t, a, b, eh) ppc_inst(PPC_INST_LDARX | ___PPC_RT(t)
> > | \
> > ___PPC_RA(a) | ___PPC_RB(b) | \
> > __PPC_EH(eh))
> > -#define TEST_STDCX(s, a, b) (PPC_INST_STDCX | ___PPC_RS(s) | \
> > +#define TEST_STDCX(s, a, b) ppc_inst(PPC_INST_STDCX | ___PPC_RS(s) | \
> > ___PPC_RA(a) | ___PPC_RB(b))
> > -#define TEST_LFSX(t, a, b) (PPC_INST_LFSX | ___PPC_RT(t) | \
> > +#define TEST_LFSX(t, a, b) ppc_inst(PPC_INST_LFSX | ___PPC_RT(t) |
> > \
> > ___PPC_RA(a) | ___PPC_RB(b))
> > -#define TEST_STFSX(s, a, b) (PPC_INST_STFSX | ___PPC_RS(s) | \
> > +#define TEST_STFSX(s, a, b) ppc_inst(PPC_INST_STFSX | ___PPC_RS(s) | \
> > ___PPC_RA(a) | ___PPC_RB(b))
> > -#define TEST_LFDX(t, a, b) (PPC_INST_LFDX | ___PPC_RT(t) | \
> > +#define TEST_LFDX(t, a, b) ppc_inst(PPC_INST_LFDX | ___PPC_RT(t) |
> > \
> > ___PPC_RA(a) | ___PPC_RB(b))
> > -#define TEST_STFDX(s, a, b) (PPC_INST_STFDX | ___PPC_RS(s) | \
> > +#define TEST_STFDX(s, a, b) ppc_inst(PPC_INST_STFDX | ___PPC_RS(s) | \
> > ___PPC_RA(a) | ___PPC_RB(b))
> > -#define TEST_LVX(t, a, b) (PPC_INST_LVX | ___PPC_RT(t) | \
> > +#define TEST_LVX(t, a, b) ppc_inst(PPC_INST_LVX | ___PPC_RT(t) |
> > \
> > ___PPC_RA(a) | ___PPC_RB(b))
> > -#define TEST_STVX(s, a, b) (PPC_INST_STVX | ___PPC_RS(s) | \
> > +#define TEST_STVX(s, a, b) ppc_inst(PPC_INST_STVX | ___PPC_RS(s) |
> > \
> > ___PPC_RA(a) | ___PPC_RB(b))
> > -#define TEST_LXVD2X(s, a, b) (PPC_INST_LXVD2X | VSX_XX1((s), R##a, R##b))
> > -#define TEST_STXVD2X(s, a, b) (PPC_INST_STXVD2X | VSX_XX1((s), R##a,
> > R##b))
> > -#define TEST_ADD(t, a, b) (PPC_INST_ADD | ___PPC_RT(t) | \
> > +#define TEST_LXVD2X(s, a, b) ppc_inst(PPC_INST_LXVD2X | VSX_XX1((s), R##a,
> > R##b))
> > +#define TEST_STXVD2X(s, a, b) ppc_inst(PPC_INST_STXVD2X |
> > VSX_XX1((s), R##a, R##b))
> > +#define TEST_ADD(t, a, b) ppc_inst(PPC_INST_ADD | ___PPC_RT(t) |
> > \
> > ___PPC_RA(a) | ___PPC_RB(b))
> > -#define TEST_ADD_DOT(t, a, b) (PPC_INST_ADD | ___PPC_RT(t) |
> > \
> > +#define TEST_ADD_DOT(t, a, b) ppc_inst(PPC_INST_ADD | ___PPC_RT(t) |
> > \
> > ___PPC_RA(a) | ___PPC_RB(b) | 0x1)
> > -#define TEST_ADDC(t, a, b) (PPC_INST_ADDC | ___PPC_RT(t) | \
> > +#define TEST_ADDC(t, a, b) ppc_inst(PPC_INST_ADDC | ___PPC_RT(t) |
> > \
> > ___PPC_RA(a) | ___PPC_RB(b))
> > -#define TEST_ADDC_DOT(t, a, b) (PPC_INST_ADDC | ___PPC_RT(t) |
> > \
> > +#define TEST_ADDC_DOT(t, a, b) ppc_inst(PPC_INST_ADDC | ___PPC_RT(t) |
> > \
> > ___PPC_RA(a) | ___PPC_RB(b) | 0x1)
> >
> > #define MAX_SUBTESTS 16
> > @@ -471,7 +472,7 @@ static struct compute_test compute_tests[] = {
> > .subtests = {
> > {
> > .descr = "R0 = LONG_MAX",
> > - .instr = PPC_INST_NOP,
> > + .instr = ppc_inst(PPC_INST_NOP),
> > .regs = {
> > .gpr[0] = LONG_MAX,
> > }
> > diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
> > index 049375206510..68ecb39dd9cc 100644
> > --- a/arch/powerpc/xmon/xmon.c
> > +++ b/arch/powerpc/xmon/xmon.c
> > @@ -54,6 +54,7 @@
> > #include <asm/firmware.h>
> > #include <asm/code-patching.h>
> > #include <asm/sections.h>
> > +#include <asm/inst.h>
> >
> > #ifdef CONFIG_PPC64
> > #include <asm/hvcall.h>
> > @@ -949,7 +950,7 @@ static void remove_bpts(void)
> > if ((bp->enabled & (BP_TRAP|BP_CIABR)) != BP_TRAP)
> > continue;
> > if (mread(bp->address, &instr, 4) == 4
> > - && instr == bpinstr
> > + && instr == ppc_inst(bpinstr)
> > && patch_instruction(
> > (unsigned int *)bp->address, bp->instr[0]) != 0)
> > printf("Couldn't remove breakpoint at %lx\n",
> > @@ -2845,7 +2846,7 @@ generic_inst_dump(unsigned long adr, long count, int
> > praddr,
> > {
> > int nr, dotted;
> > unsigned long first_adr;
> > - unsigned int inst, last_inst = 0;
> > + unsigned int inst, last_inst = ppc_inst(0);
> > unsigned char val[4];
> >
> > dotted = 0;
> > @@ -2858,7 +2859,7 @@ generic_inst_dump(unsigned long adr, long count, int
> > praddr,
> > }
> > break;
> > }
> > - inst = GETWORD(val);
> > + inst = ppc_inst(GETWORD(val));
> > if (adr > first_adr && inst == last_inst) {
> > if (!dotted) {
> > printf(" ...\n");
>
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 05/21] powerpc: Use a function for getting the instruction op code
2020-04-07 7:04 ` Balamuruhan S
@ 2020-04-07 8:32 ` Jordan Niethe
0 siblings, 0 replies; 71+ messages in thread
From: Jordan Niethe @ 2020-04-07 8:32 UTC (permalink / raw)
To: Balamuruhan S
Cc: Alistair Popple, linuxppc-dev, Nicholas Piggin, Daniel Axtens
On Tue, Apr 7, 2020 at 5:05 PM Balamuruhan S <bala24@linux.ibm.com> wrote:
>
> On Mon, 2020-04-06 at 18:09 +1000, Jordan Niethe wrote:
> > In preparation for using a data type for instructions that can not be
> > directly used with the '>>' operator use a function for getting the op
> > code of an instruction.
>
> vecemu.c and sstep.c will need ppc_inst_opcode().
Sorry, I forget you pointed those files out before. I added other
things to them but then I forgot to add this. Will do for next time.
>
> -- Bala
>
> >
> > Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> > ---
> > v4: New to series
> > ---
> > arch/powerpc/include/asm/inst.h | 5 +++++
> > arch/powerpc/kernel/align.c | 2 +-
> > arch/powerpc/lib/code-patching.c | 4 ++--
> > 3 files changed, 8 insertions(+), 3 deletions(-)
> >
> > diff --git a/arch/powerpc/include/asm/inst.h
> > b/arch/powerpc/include/asm/inst.h
> > index 5298ba33b6e5..93959016fe4b 100644
> > --- a/arch/powerpc/include/asm/inst.h
> > +++ b/arch/powerpc/include/asm/inst.h
> > @@ -8,4 +8,9 @@
> >
> > #define ppc_inst(x) (x)
> >
> > +static inline int ppc_inst_opcode(u32 x)
> > +{
> > + return x >> 26;
> > +}
> > +
> > #endif /* _ASM_INST_H */
> > diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
> > index 86e9bf62f18c..691013aa9f3c 100644
> > --- a/arch/powerpc/kernel/align.c
> > +++ b/arch/powerpc/kernel/align.c
> > @@ -314,7 +314,7 @@ int fix_alignment(struct pt_regs *regs)
> > }
> >
> > #ifdef CONFIG_SPE
> > - if ((instr >> 26) == 0x4) {
> > + if (ppc_inst_opcode(instr) == 0x4) {
> > int reg = (instr >> 21) & 0x1f;
> > PPC_WARN_ALIGNMENT(spe, regs);
> > return emulate_spe(regs, reg, instr);
> > diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-
> > patching.c
> > index fdf0d6ea3575..099a515202aa 100644
> > --- a/arch/powerpc/lib/code-patching.c
> > +++ b/arch/powerpc/lib/code-patching.c
> > @@ -231,7 +231,7 @@ bool is_offset_in_branch_range(long offset)
> > */
> > bool is_conditional_branch(unsigned int instr)
> > {
> > - unsigned int opcode = instr >> 26;
> > + unsigned int opcode = ppc_inst_opcode(instr);
> >
> > if (opcode == 16) /* bc, bca, bcl, bcla */
> > return true;
> > @@ -289,7 +289,7 @@ int create_cond_branch(unsigned int *instr, const
> > unsigned int *addr,
> >
> > static unsigned int branch_opcode(unsigned int instr)
> > {
> > - return (instr >> 26) & 0x3F;
> > + return ppc_inst_opcode(instr) & 0x3F;
> > }
> >
> > static int instr_is_branch_iform(unsigned int instr)
>
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 09/21] powerpc: Use a datatype for instructions
2020-04-06 8:09 ` [PATCH v5 09/21] powerpc: Use a datatype for instructions Jordan Niethe
2020-04-06 10:34 ` kbuild test robot
2020-04-06 10:35 ` kbuild test robot
@ 2020-04-07 10:30 ` Balamuruhan S
2020-04-08 2:11 ` Jordan Niethe
2 siblings, 1 reply; 71+ messages in thread
From: Balamuruhan S @ 2020-04-07 10:30 UTC (permalink / raw)
To: Jordan Niethe, linuxppc-dev; +Cc: alistair, npiggin, dja
On Mon, 2020-04-06 at 18:09 +1000, Jordan Niethe wrote:
> Currently unsigned ints are used to represent instructions on powerpc.
> This has worked well as instructions have always been 4 byte words.
> However, a future ISA version will introduce some changes to
> instructions that mean this scheme will no longer work as well. This
> change is Prefixed Instructions. A prefixed instruction is made up of a
> word prefix followed by a word suffix to make an 8 byte double word
> instruction. No matter the endianess of the system the prefix always
> comes first. Prefixed instructions are only planned for powerpc64.
>
> Introduce a ppc_inst type to represent both prefixed and word
> instructions on powerpc64 while keeping it possible to exclusively have
> word instructions on powerpc32, A latter patch will expand the type to
> include prefixed instructions but for now just typedef it to a u32.
>
> Later patches will introduce helper functions and macros for
> manipulating the instructions so that powerpc64 and powerpc32 might
> maintain separate type definitions.
>
> Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> ---
> v4: New to series
> v5: Add to epapr_paravirt.c, kgdb.c
> ---
> arch/powerpc/include/asm/code-patching.h | 32 ++++-----
> arch/powerpc/include/asm/inst.h | 20 +++---
> arch/powerpc/include/asm/sstep.h | 5 +-
> arch/powerpc/include/asm/uprobes.h | 5 +-
> arch/powerpc/kernel/align.c | 4 +-
> arch/powerpc/kernel/epapr_paravirt.c | 4 +-
> arch/powerpc/kernel/hw_breakpoint.c | 4 +-
> arch/powerpc/kernel/jump_label.c | 2 +-
> arch/powerpc/kernel/kgdb.c | 4 +-
> arch/powerpc/kernel/kprobes.c | 8 +--
> arch/powerpc/kernel/mce_power.c | 5 +-
> arch/powerpc/kernel/optprobes.c | 40 ++++++------
> arch/powerpc/kernel/setup_32.c | 2 +-
> arch/powerpc/kernel/trace/ftrace.c | 83 ++++++++++++------------
> arch/powerpc/kernel/vecemu.c | 5 +-
> arch/powerpc/lib/code-patching.c | 69 ++++++++++----------
> arch/powerpc/lib/feature-fixups.c | 48 +++++++-------
> arch/powerpc/lib/sstep.c | 4 +-
> arch/powerpc/lib/test_emulate_step.c | 9 +--
> arch/powerpc/perf/core-book3s.c | 4 +-
> arch/powerpc/xmon/xmon.c | 24 +++----
> 21 files changed, 196 insertions(+), 185 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/code-patching.h
> b/arch/powerpc/include/asm/code-patching.h
> index 48e021957ee5..eacc9102c251 100644
> --- a/arch/powerpc/include/asm/code-patching.h
> +++ b/arch/powerpc/include/asm/code-patching.h
> @@ -23,33 +23,33 @@
> #define BRANCH_ABSOLUTE 0x2
>
> bool is_offset_in_branch_range(long offset);
> -int create_branch(unsigned int *instr, const unsigned int *addr,
> +int create_branch(struct ppc_inst *instr, const struct ppc_inst *addr,
> unsigned long target, int flags);
> -int create_cond_branch(unsigned int *instr, const unsigned int *addr,
> +int create_cond_branch(struct ppc_inst *instr, const struct ppc_inst *addr,
> unsigned long target, int flags);
> -int patch_branch(unsigned int *addr, unsigned long target, int flags);
> -int patch_instruction(unsigned int *addr, unsigned int instr);
> -int raw_patch_instruction(unsigned int *addr, unsigned int instr);
> +int patch_branch(struct ppc_inst *addr, unsigned long target, int flags);
> +int patch_instruction(struct ppc_inst *addr, struct ppc_inst instr);
> +int raw_patch_instruction(struct ppc_inst *addr, struct ppc_inst instr);
>
> static inline unsigned long patch_site_addr(s32 *site)
> {
> return (unsigned long)site + *site;
> }
>
> -static inline int patch_instruction_site(s32 *site, unsigned int instr)
> +static inline int patch_instruction_site(s32 *site, struct ppc_inst instr)
> {
> - return patch_instruction((unsigned int *)patch_site_addr(site), instr);
> + return patch_instruction((struct ppc_inst *)patch_site_addr(site),
> instr);
> }
>
> static inline int patch_branch_site(s32 *site, unsigned long target, int
> flags)
> {
> - return patch_branch((unsigned int *)patch_site_addr(site), target,
> flags);
> + return patch_branch((struct ppc_inst *)patch_site_addr(site), target,
> flags);
> }
>
> static inline int modify_instruction(unsigned int *addr, unsigned int clr,
> unsigned int set)
> {
> - return patch_instruction(addr, ppc_inst((*addr & ~clr) | set));
> + return patch_instruction((struct ppc_inst *)addr, ppc_inst((*addr &
> ~clr) | set));
> }
>
> static inline int modify_instruction_site(s32 *site, unsigned int clr,
> unsigned int set)
> @@ -57,13 +57,13 @@ static inline int modify_instruction_site(s32 *site,
> unsigned int clr, unsigned
> return modify_instruction((unsigned int *)patch_site_addr(site), clr,
> set);
> }
>
> -int instr_is_relative_branch(unsigned int instr);
> -int instr_is_relative_link_branch(unsigned int instr);
> -int instr_is_branch_to_addr(const unsigned int *instr, unsigned long addr);
> -unsigned long branch_target(const unsigned int *instr);
> -int translate_branch(unsigned int *instr, const unsigned int *dest,
> - const unsigned int *src);
> -extern bool is_conditional_branch(unsigned int instr);
> +int instr_is_relative_branch(struct ppc_inst instr);
> +int instr_is_relative_link_branch(struct ppc_inst instr);
> +int instr_is_branch_to_addr(const struct ppc_inst *instr, unsigned long
> addr);
> +unsigned long branch_target(const struct ppc_inst *instr);
> +int translate_branch(struct ppc_inst *instr, const struct ppc_inst *dest,
> + const struct ppc_inst *src);
> +extern bool is_conditional_branch(struct ppc_inst instr);
> #ifdef CONFIG_PPC_BOOK3E_64
> void __patch_exception(int exc, unsigned long addr);
> #define patch_exception(exc, name) do { \
> diff --git a/arch/powerpc/include/asm/inst.h
> b/arch/powerpc/include/asm/inst.h
> index 54ee46b0a7c9..a71decf5f871 100644
> --- a/arch/powerpc/include/asm/inst.h
> +++ b/arch/powerpc/include/asm/inst.h
> @@ -6,26 +6,30 @@
> * Instruction data type for POWER
> */
>
> -#define ppc_inst(x) (x)
> +struct ppc_inst {
> + u32 val;
> +} __packed;
>
> -static inline u32 ppc_inst_val(u32 x)
> +#define ppc_inst(x) ((struct ppc_inst){ .val = x })
> +
> +static inline u32 ppc_inst_val(struct ppc_inst x)
> {
> - return x;
> + return x.val;
> }
>
> -static inline int ppc_inst_opcode(u32 x)
> +static inline int ppc_inst_opcode(struct ppc_inst x)
> {
> - return x >> 26;
> + return x.val >> 26;
> }
>
> -static inline u32 ppc_inst_swab(u32 x)
> +static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
> {
> return ppc_inst(swab32(ppc_inst_val(x)));
> }
>
> -static inline bool ppc_inst_equal(u32 x, u32 y)
> +static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
> {
> - return x == y;
> + return !memcmp(&x, &y, sizeof(struct ppc_inst));
> }
>
> #endif /* _ASM_INST_H */
> diff --git a/arch/powerpc/include/asm/sstep.h
> b/arch/powerpc/include/asm/sstep.h
> index 26d729562fe2..c3ce903ac488 100644
> --- a/arch/powerpc/include/asm/sstep.h
> +++ b/arch/powerpc/include/asm/sstep.h
> @@ -2,6 +2,7 @@
> /*
> * Copyright (C) 2004 Paul Mackerras <paulus@au.ibm.com>, IBM
> */
> +#include <asm/inst.h>
>
> struct pt_regs;
>
> @@ -132,7 +133,7 @@ union vsx_reg {
> * otherwise.
> */
> extern int analyse_instr(struct instruction_op *op, const struct pt_regs
> *regs,
> - unsigned int instr);
> + struct ppc_inst instr);
>
> /*
> * Emulate an instruction that can be executed just by updating
> @@ -149,7 +150,7 @@ void emulate_update_regs(struct pt_regs *reg, struct
> instruction_op *op);
> * 0 if it could not be emulated, or -1 for an instruction that
> * should not be emulated (rfid, mtmsrd clearing MSR_RI, etc.).
> */
> -extern int emulate_step(struct pt_regs *regs, unsigned int instr);
> +extern int emulate_step(struct pt_regs *regs, struct ppc_inst instr);
>
> /*
> * Emulate a load or store instruction by reading/writing the
> diff --git a/arch/powerpc/include/asm/uprobes.h
> b/arch/powerpc/include/asm/uprobes.h
> index 2bbdf27d09b5..7e3b329ba2d3 100644
> --- a/arch/powerpc/include/asm/uprobes.h
> +++ b/arch/powerpc/include/asm/uprobes.h
> @@ -11,6 +11,7 @@
>
> #include <linux/notifier.h>
> #include <asm/probes.h>
> +#include <asm/inst.h>
>
> typedef ppc_opcode_t uprobe_opcode_t;
>
> @@ -23,8 +24,8 @@ typedef ppc_opcode_t uprobe_opcode_t;
>
> struct arch_uprobe {
> union {
> - u32 insn;
> - u32 ixol;
> + struct ppc_inst insn;
> + struct ppc_inst ixol;
> };
> };
>
> diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
> index 46870cf6a6dc..66a6d1de7799 100644
> --- a/arch/powerpc/kernel/align.c
> +++ b/arch/powerpc/kernel/align.c
> @@ -294,7 +294,7 @@ static int emulate_spe(struct pt_regs *regs, unsigned int
> reg,
>
> int fix_alignment(struct pt_regs *regs)
> {
> - unsigned int instr;
> + struct ppc_inst instr;
> struct instruction_op op;
> int r, type;
>
> @@ -304,7 +304,7 @@ int fix_alignment(struct pt_regs *regs)
> */
> CHECK_FULL_REGS(regs);
>
> - if (unlikely(__get_user(instr, (unsigned int __user *)regs->nip)))
> + if (unlikely(__get_user(instr.val, (unsigned int __user *)regs->nip)))
don't we have to use the helper `ppc_inst_val()` here to retrieve instr.val ?
I see couple of other places we directly retrieve as instr.val.
if we need to change it, then all of them should go to patch 6,
[PATCH v5 06/21] powerpc: Use an accessor for instructions
> return -EFAULT;
> if ((regs->msr & MSR_LE) != (MSR_KERNEL & MSR_LE)) {
> /* We don't handle PPC little-endian any more... */
> diff --git a/arch/powerpc/kernel/epapr_paravirt.c
> b/arch/powerpc/kernel/epapr_paravirt.c
> index c53e863fb484..c42aa3926632 100644
> --- a/arch/powerpc/kernel/epapr_paravirt.c
> +++ b/arch/powerpc/kernel/epapr_paravirt.c
> @@ -38,9 +38,9 @@ static int __init early_init_dt_scan_epapr(unsigned long
> node,
>
> for (i = 0; i < (len / 4); i++) {
> u32 inst = be32_to_cpu(insts[i]);
> - patch_instruction(epapr_hypercall_start + i, ppc_inst(inst));
> + patch_instruction((struct ppc_inst *)(epapr_hypercall_start +
> i), ppc_inst(inst));
> #if !defined(CONFIG_64BIT) || defined(CONFIG_PPC_BOOK3E_64)
> - patch_instruction(epapr_ev_idle_start + i, ppc_inst(inst));
> + patch_instruction((struct ppc_inst *)(epapr_ev_idle_start + i),
> ppc_inst(inst));
> #endif
> }
>
> diff --git a/arch/powerpc/kernel/hw_breakpoint.c
> b/arch/powerpc/kernel/hw_breakpoint.c
> index 79f51f182a83..542f65ccf68b 100644
> --- a/arch/powerpc/kernel/hw_breakpoint.c
> +++ b/arch/powerpc/kernel/hw_breakpoint.c
> @@ -244,12 +244,12 @@ dar_range_overlaps(unsigned long dar, int size, struct
> arch_hw_breakpoint *info)
> static bool stepping_handler(struct pt_regs *regs, struct perf_event *bp,
> struct arch_hw_breakpoint *info)
> {
> - unsigned int instr = ppc_inst(0);
> + struct ppc_inst instr = ppc_inst(0);
> int ret, type, size;
> struct instruction_op op;
> unsigned long addr = info->address;
>
> - if (__get_user_inatomic(instr, (unsigned int *)regs->nip))
> + if (__get_user_inatomic(instr.val, (unsigned int *)regs->nip))
[...] reference to above
> goto fail;
>
> ret = analyse_instr(&op, regs, instr);
> diff --git a/arch/powerpc/kernel/jump_label.c
> b/arch/powerpc/kernel/jump_label.c
> index daa4afce7ec8..144858027fa3 100644
> --- a/arch/powerpc/kernel/jump_label.c
> +++ b/arch/powerpc/kernel/jump_label.c
> @@ -11,7 +11,7 @@
> void arch_jump_label_transform(struct jump_entry *entry,
> enum jump_label_type type)
> {
> - u32 *addr = (u32 *)(unsigned long)entry->code;
> + struct ppc_inst *addr = (struct ppc_inst *)(unsigned long)entry->code;
>
> if (type == JUMP_LABEL_JMP)
> patch_branch(addr, entry->target, 0);
> diff --git a/arch/powerpc/kernel/kgdb.c b/arch/powerpc/kernel/kgdb.c
> index a6b38a19133f..652b2852bea3 100644
> --- a/arch/powerpc/kernel/kgdb.c
> +++ b/arch/powerpc/kernel/kgdb.c
> @@ -419,7 +419,7 @@ int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
> {
> int err;
> unsigned int instr;
> - unsigned int *addr = (unsigned int *)bpt->bpt_addr;
> + struct ppc_inst *addr = (struct ppc_inst *)bpt->bpt_addr;
>
> err = probe_kernel_address(addr, instr);
> if (err)
> @@ -438,7 +438,7 @@ int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
> {
> int err;
> unsigned int instr = *(unsigned int *)bpt->saved_instr;
> - unsigned int *addr = (unsigned int *)bpt->bpt_addr;
> + struct ppc_inst *addr = (struct ppc_inst *)bpt->bpt_addr;
>
> err = patch_instruction(addr, ppc_inst(instr));
> if (err)
> diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
> index 8420b1944164..9ed996cb0589 100644
> --- a/arch/powerpc/kernel/kprobes.c
> +++ b/arch/powerpc/kernel/kprobes.c
> @@ -106,7 +106,7 @@ kprobe_opcode_t *kprobe_lookup_name(const char *name,
> unsigned int offset)
> int arch_prepare_kprobe(struct kprobe *p)
> {
> int ret = 0;
> - kprobe_opcode_t insn = *p->addr;
> + struct ppc_inst insn = *(struct ppc_inst *)p->addr;
>
> if ((unsigned long)p->addr & 0x03) {
> printk("Attempt to register kprobe at an unaligned address\n");
> @@ -139,13 +139,13 @@ NOKPROBE_SYMBOL(arch_prepare_kprobe);
>
> void arch_arm_kprobe(struct kprobe *p)
> {
> - patch_instruction(p->addr, ppc_inst(BREAKPOINT_INSTRUCTION));
> + patch_instruction((struct ppc_inst *)p->addr,
> ppc_inst(BREAKPOINT_INSTRUCTION));
> }
> NOKPROBE_SYMBOL(arch_arm_kprobe);
>
> void arch_disarm_kprobe(struct kprobe *p)
> {
> - patch_instruction(p->addr, ppc_inst(p->opcode));
> + patch_instruction((struct ppc_inst *)p->addr, ppc_inst(p->opcode));
> }
> NOKPROBE_SYMBOL(arch_disarm_kprobe);
>
> @@ -217,7 +217,7 @@ NOKPROBE_SYMBOL(arch_prepare_kretprobe);
> static int try_to_emulate(struct kprobe *p, struct pt_regs *regs)
> {
> int ret;
> - unsigned int insn = *p->ainsn.insn;
> + struct ppc_inst insn = *(struct ppc_inst *)p->ainsn.insn;
>
> /* regs->nip is also adjusted if emulate_step returns 1 */
> ret = emulate_step(regs, insn);
> diff --git a/arch/powerpc/kernel/mce_power.c
> b/arch/powerpc/kernel/mce_power.c
> index 1cbf7f1a4e3d..7118b46a6543 100644
> --- a/arch/powerpc/kernel/mce_power.c
> +++ b/arch/powerpc/kernel/mce_power.c
> @@ -20,6 +20,7 @@
> #include <asm/sstep.h>
> #include <asm/exception-64s.h>
> #include <asm/extable.h>
> +#include <asm/inst.h>
>
> /*
> * Convert an address related to an mm to a PFN. NOTE: we are in real
> @@ -365,7 +366,7 @@ static int mce_find_instr_ea_and_phys(struct pt_regs
> *regs, uint64_t *addr,
> * in real-mode is tricky and can lead to recursive
> * faults
> */
> - int instr;
> + struct ppc_inst instr;
> unsigned long pfn, instr_addr;
> struct instruction_op op;
> struct pt_regs tmp = *regs;
> @@ -373,7 +374,7 @@ static int mce_find_instr_ea_and_phys(struct pt_regs
> *regs, uint64_t *addr,
> pfn = addr_to_pfn(regs, regs->nip);
> if (pfn != ULONG_MAX) {
> instr_addr = (pfn << PAGE_SHIFT) + (regs->nip & ~PAGE_MASK);
> - instr = *(unsigned int *)(instr_addr);
> + instr = *(struct ppc_inst *)(instr_addr);
> if (!analyse_instr(&op, &tmp, instr)) {
> pfn = addr_to_pfn(regs, op.ea);
> *addr = op.ea;
> diff --git a/arch/powerpc/kernel/optprobes.c
> b/arch/powerpc/kernel/optprobes.c
> index 3b33ebf18859..b61bbcee84f4 100644
> --- a/arch/powerpc/kernel/optprobes.c
> +++ b/arch/powerpc/kernel/optprobes.c
> @@ -100,8 +100,8 @@ static unsigned long can_optimize(struct kprobe *p)
> * Ensure that the instruction is not a conditional branch,
> * and that can be emulated.
> */
> - if (!is_conditional_branch(*p->ainsn.insn) &&
> - analyse_instr(&op, ®s, *p->ainsn.insn) == 1) {
> + if (!is_conditional_branch(*(struct ppc_inst *)p->ainsn.insn) &&
> + analyse_instr(&op, ®s, *(struct ppc_inst *)p-
> >ainsn.insn) == 1) {
> emulate_update_regs(®s, &op);
> nip = regs.nip;
> }
> @@ -148,12 +148,12 @@ void arch_remove_optimized_kprobe(struct
> optimized_kprobe *op)
> void patch_imm32_load_insns(unsigned int val, kprobe_opcode_t *addr)
> {
> /* addis r4,0,(insn)@h */
> - patch_instruction(addr, ppc_inst(PPC_INST_ADDIS | ___PPC_RT(4) |
> + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ADDIS |
> ___PPC_RT(4) |
> ((val >> 16) & 0xffff)));
> addr++;
>
> /* ori r4,r4,(insn)@l */
> - patch_instruction(addr, ppc_inst(PPC_INST_ORI | ___PPC_RA(4) |
> + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI |
> ___PPC_RA(4) |
> ___PPC_RS(4) | (val & 0xffff)));
> }
>
> @@ -164,34 +164,34 @@ void patch_imm32_load_insns(unsigned int val,
> kprobe_opcode_t *addr)
> void patch_imm64_load_insns(unsigned long val, kprobe_opcode_t *addr)
> {
> /* lis r3,(op)@highest */
> - patch_instruction(addr, ppc_inst(PPC_INST_ADDIS | ___PPC_RT(3) |
> + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ADDIS |
> ___PPC_RT(3) |
> ((val >> 48) & 0xffff)));
> addr++;
>
> /* ori r3,r3,(op)@higher */
> - patch_instruction(addr, ppc_inst(PPC_INST_ORI | ___PPC_RA(3) |
> + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI |
> ___PPC_RA(3) |
> ___PPC_RS(3) | ((val >> 32) & 0xffff)));
> addr++;
>
> /* rldicr r3,r3,32,31 */
> - patch_instruction(addr, ppc_inst(PPC_INST_RLDICR | ___PPC_RA(3) |
> + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_RLDICR |
> ___PPC_RA(3) |
> ___PPC_RS(3) | __PPC_SH64(32) | __PPC_ME64(31)));
> addr++;
>
> /* oris r3,r3,(op)@h */
> - patch_instruction(addr, ppc_inst(PPC_INST_ORIS | ___PPC_RA(3) |
> + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORIS |
> ___PPC_RA(3) |
> ___PPC_RS(3) | ((val >> 16) & 0xffff)));
> addr++;
>
> /* ori r3,r3,(op)@l */
> - patch_instruction(addr, ppc_inst(PPC_INST_ORI | ___PPC_RA(3) |
> + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI |
> ___PPC_RA(3) |
> ___PPC_RS(3) | (val & 0xffff)));
> }
>
> int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe
> *p)
> {
> - kprobe_opcode_t *buff, branch_op_callback, branch_emulate_step;
> - kprobe_opcode_t *op_callback_addr, *emulate_step_addr;
> + struct ppc_inst branch_op_callback, branch_emulate_step;
> + kprobe_opcode_t *op_callback_addr, *emulate_step_addr, *buff;
> long b_offset;
> unsigned long nip, size;
> int rc, i;
> @@ -231,7 +231,7 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe
> *op, struct kprobe *p)
> size = (TMPL_END_IDX * sizeof(kprobe_opcode_t)) / sizeof(int);
> pr_devel("Copying template to %p, size %lu\n", buff, size);
> for (i = 0; i < size; i++) {
> - rc = patch_instruction(buff + i,
> ppc_inst(*(optprobe_template_entry + i)));
> + rc = patch_instruction((struct ppc_inst *)(buff + i),
> ppc_inst(*(optprobe_template_entry + i)));
> if (rc < 0)
> goto error;
> }
> @@ -253,20 +253,20 @@ int arch_prepare_optimized_kprobe(struct
> optimized_kprobe *op, struct kprobe *p)
> }
>
> rc = create_branch(&branch_op_callback,
> - (unsigned int *)buff + TMPL_CALL_HDLR_IDX,
> + (struct ppc_inst *)(buff + TMPL_CALL_HDLR_IDX),
> (unsigned long)op_callback_addr,
> BRANCH_SET_LINK);
>
> rc |= create_branch(&branch_emulate_step,
> - (unsigned int *)buff + TMPL_EMULATE_IDX,
> + (struct ppc_inst *)(buff + TMPL_EMULATE_IDX),
> (unsigned long)emulate_step_addr,
> BRANCH_SET_LINK);
>
> if (rc)
> goto error;
>
> - patch_instruction(buff + TMPL_CALL_HDLR_IDX, branch_op_callback);
> - patch_instruction(buff + TMPL_EMULATE_IDX, branch_emulate_step);
> + patch_instruction((struct ppc_inst *)(buff + TMPL_CALL_HDLR_IDX),
> branch_op_callback);
> + patch_instruction((struct ppc_inst *)(buff + TMPL_EMULATE_IDX),
> branch_emulate_step);
>
> /*
> * 3. load instruction to be emulated into relevant register, and
> @@ -276,7 +276,7 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe
> *op, struct kprobe *p)
> /*
> * 4. branch back from trampoline
> */
> - patch_branch(buff + TMPL_RET_IDX, (unsigned long)nip, 0);
> + patch_branch((void *)(buff + TMPL_RET_IDX), (unsigned long)nip, 0);
why do we cast it differently here ?
>
> flush_icache_range((unsigned long)buff,
> (unsigned long)(&buff[TMPL_END_IDX]));
> @@ -308,7 +308,7 @@ int arch_check_optimized_kprobe(struct optimized_kprobe
> *op)
>
> void arch_optimize_kprobes(struct list_head *oplist)
> {
> - unsigned int instr;
> + struct ppc_inst instr;
> struct optimized_kprobe *op;
> struct optimized_kprobe *tmp;
>
> @@ -320,9 +320,9 @@ void arch_optimize_kprobes(struct list_head *oplist)
> memcpy(op->optinsn.copied_insn, op->kp.addr,
> RELATIVEJUMP_SIZE);
> create_branch(&instr,
> - (unsigned int *)op->kp.addr,
> + (struct ppc_inst *)op->kp.addr,
> (unsigned long)op->optinsn.insn, 0);
> - patch_instruction(op->kp.addr, instr);
> + patch_instruction((struct ppc_inst *)op->kp.addr, instr);
> list_del_init(&op->list);
> }
> }
> diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
> index c1bdd462c5c0..989809e58234 100644
> --- a/arch/powerpc/kernel/setup_32.c
> +++ b/arch/powerpc/kernel/setup_32.c
> @@ -76,7 +76,7 @@ EXPORT_SYMBOL(DMA_MODE_WRITE);
> notrace void __init machine_init(u64 dt_ptr)
> {
> unsigned int *addr = (unsigned int
> *)patch_site_addr(&patch__memset_nocache);
> - unsigned long insn;
> + struct ppc_inst insn;
>
> /* Configure static keys first, now that we're relocated. */
> setup_feature_keys();
> diff --git a/arch/powerpc/kernel/trace/ftrace.c
> b/arch/powerpc/kernel/trace/ftrace.c
> index 784b5746cc55..442c62fb68ff 100644
> --- a/arch/powerpc/kernel/trace/ftrace.c
> +++ b/arch/powerpc/kernel/trace/ftrace.c
> @@ -41,23 +41,23 @@
> #define NUM_FTRACE_TRAMPS 8
> static unsigned long ftrace_tramps[NUM_FTRACE_TRAMPS];
>
> -static unsigned int
> +static struct ppc_inst
> ftrace_call_replace(unsigned long ip, unsigned long addr, int link)
> {
> - unsigned int op;
> + struct ppc_inst op;
>
> addr = ppc_function_entry((void *)addr);
>
> /* if (link) set op to 'bl' else 'b' */
> - create_branch(&op, (unsigned int *)ip, addr, link ? 1 : 0);
> + create_branch(&op, (struct ppc_inst *)ip, addr, link ? 1 : 0);
>
> return op;
> }
>
> static int
> -ftrace_modify_code(unsigned long ip, unsigned int old, unsigned int new)
> +ftrace_modify_code(unsigned long ip, struct ppc_inst old, struct ppc_inst
> new)
> {
> - unsigned int replaced;
> + struct ppc_inst replaced;
>
> /*
> * Note:
> @@ -79,7 +79,7 @@ ftrace_modify_code(unsigned long ip, unsigned int old,
> unsigned int new)
> }
>
> /* replace the text with the new text */
> - if (patch_instruction((unsigned int *)ip, new))
> + if (patch_instruction((struct ppc_inst *)ip, new))
> return -EPERM;
>
> return 0;
> @@ -90,24 +90,24 @@ ftrace_modify_code(unsigned long ip, unsigned int old,
> unsigned int new)
> */
> static int test_24bit_addr(unsigned long ip, unsigned long addr)
> {
> - unsigned int op;
> + struct ppc_inst op;
> addr = ppc_function_entry((void *)addr);
>
> /* use the create_branch to verify that this offset can be branched */
> - return create_branch(&op, (unsigned int *)ip, addr, 0) == 0;
> + return create_branch(&op, (struct ppc_inst *)ip, addr, 0) == 0;
> }
>
> -static int is_bl_op(unsigned int op)
> +static int is_bl_op(struct ppc_inst op)
> {
> return (ppc_inst_val(op) & 0xfc000003) == 0x48000001;
> }
>
> -static int is_b_op(unsigned int op)
> +static int is_b_op(struct ppc_inst op)
> {
> return (ppc_inst_val(op) & 0xfc000003) == 0x48000000;
> }
>
> -static unsigned long find_bl_target(unsigned long ip, unsigned int op)
> +static unsigned long find_bl_target(unsigned long ip, struct ppc_inst op)
> {
> int offset;
>
> @@ -127,7 +127,7 @@ __ftrace_make_nop(struct module *mod,
> {
> unsigned long entry, ptr, tramp;
> unsigned long ip = rec->ip;
> - unsigned int op, pop;
> + struct ppc_inst op, pop;
>
> /* read where this goes */
> if (probe_kernel_read(&op, (void *)ip, sizeof(int))) {
> @@ -207,7 +207,7 @@ __ftrace_make_nop(struct module *mod,
> }
> #endif /* CONFIG_MPROFILE_KERNEL */
>
> - if (patch_instruction((unsigned int *)ip, pop)) {
> + if (patch_instruction((struct ppc_inst *)ip, pop)) {
> pr_err("Patching NOP failed.\n");
> return -EPERM;
> }
> @@ -220,7 +220,7 @@ static int
> __ftrace_make_nop(struct module *mod,
> struct dyn_ftrace *rec, unsigned long addr)
> {
> - unsigned int op;
> + struct ppc_inst op;
> unsigned int jmp[4];
> unsigned long ip = rec->ip;
> unsigned long tramp;
> @@ -279,7 +279,7 @@ __ftrace_make_nop(struct module *mod,
>
> op = ppc_inst(PPC_INST_NOP);
>
> - if (patch_instruction((unsigned int *)ip, op))
> + if (patch_instruction((struct ppc_inst *)ip, op))
> return -EPERM;
>
> return 0;
> @@ -290,7 +290,7 @@ __ftrace_make_nop(struct module *mod,
> static unsigned long find_ftrace_tramp(unsigned long ip)
> {
> int i;
> - unsigned int instr;
> + struct ppc_inst instr;
>
> /*
> * We have the compiler generated long_branch tramps at the end
> @@ -327,9 +327,10 @@ static int add_ftrace_tramp(unsigned long tramp)
> */
> static int setup_mcount_compiler_tramp(unsigned long tramp)
> {
> - int i, op;
> + int i;
> + struct ppc_inst op;
> unsigned long ptr;
> - unsigned int instr;
> + struct ppc_inst instr;
> static unsigned long ftrace_plt_tramps[NUM_FTRACE_TRAMPS];
>
> /* Is this a known long jump tramp? */
> @@ -378,7 +379,7 @@ static int setup_mcount_compiler_tramp(unsigned long
> tramp)
> return -1;
> }
>
> - if (patch_branch((unsigned int *)tramp, ptr, 0)) {
> + if (patch_branch((struct ppc_inst *)tramp, ptr, 0)) {
> pr_debug("REL24 out of range!\n");
> return -1;
> }
> @@ -394,7 +395,7 @@ static int setup_mcount_compiler_tramp(unsigned long
> tramp)
> static int __ftrace_make_nop_kernel(struct dyn_ftrace *rec, unsigned long
> addr)
> {
> unsigned long tramp, ip = rec->ip;
> - unsigned int op;
> + struct ppc_inst op;
>
> /* Read where this goes */
> if (probe_kernel_read(&op, (void *)ip, sizeof(int))) {
> @@ -422,7 +423,7 @@ static int __ftrace_make_nop_kernel(struct dyn_ftrace
> *rec, unsigned long addr)
> }
> }
>
> - if (patch_instruction((unsigned int *)ip, ppc_inst(PPC_INST_NOP))) {
> + if (patch_instruction((struct ppc_inst *)ip, ppc_inst(PPC_INST_NOP))) {
> pr_err("Patching NOP failed.\n");
> return -EPERM;
> }
> @@ -434,7 +435,7 @@ int ftrace_make_nop(struct module *mod,
> struct dyn_ftrace *rec, unsigned long addr)
> {
> unsigned long ip = rec->ip;
> - unsigned int old, new;
> + struct ppc_inst old, new;
>
> /*
> * If the calling address is more that 24 bits away,
> @@ -487,7 +488,7 @@ int ftrace_make_nop(struct module *mod,
> */
> #ifndef CONFIG_MPROFILE_KERNEL
> static int
> -expected_nop_sequence(void *ip, unsigned int op0, unsigned int op1)
> +expected_nop_sequence(void *ip, struct ppc_inst op0, struct ppc_inst op1)
> {
> /*
> * We expect to see:
> @@ -504,7 +505,7 @@ expected_nop_sequence(void *ip, unsigned int op0,
> unsigned int op1)
> }
> #else
> static int
> -expected_nop_sequence(void *ip, unsigned int op0, unsigned int op1)
> +expected_nop_sequence(void *ip, struct ppc_inst op0, struct ppc_inst op1)
> {
> /* look for patched "NOP" on ppc64 with -mprofile-kernel */
> if (!ppc_inst_equal(op0, ppc_inst(PPC_INST_NOP)))
> @@ -516,8 +517,8 @@ expected_nop_sequence(void *ip, unsigned int op0,
> unsigned int op1)
> static int
> __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
> {
> - unsigned int op[2];
> - unsigned int instr;
> + struct ppc_inst op[2];
> + struct ppc_inst instr;
> void *ip = (void *)rec->ip;
> unsigned long entry, ptr, tramp;
> struct module *mod = rec->arch.mod;
> @@ -528,7 +529,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long
> addr)
>
> if (!expected_nop_sequence(ip, op[0], op[1])) {
> pr_err("Unexpected call sequence at %p: %x %x\n",
> - ip, op[0], op[1]);
> + ip, ppc_inst_val(op[0]), ppc_inst_val(op[1]));
shouldn't this change be part of patch 6,
[PATCH v5 06/21] powerpc: Use an accessor for instructions
> return -EINVAL;
> }
>
> @@ -582,7 +583,7 @@ static int
> __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
> {
> int err;
> - unsigned int op;
> + struct ppc_inst op;
> unsigned long ip = rec->ip;
>
> /* read where this goes */
> @@ -602,7 +603,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long
> addr)
> }
>
> /* create the branch to the trampoline */
> - err = create_branch(&op, (unsigned int *)ip,
> + err = create_branch(&op, (struct ppc_inst *)ip,
> rec->arch.mod->arch.tramp, BRANCH_SET_LINK);
> if (!err) {
> pr_err("REL24 out of range!\n");
> @@ -621,7 +622,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long
> addr)
>
> static int __ftrace_make_call_kernel(struct dyn_ftrace *rec, unsigned long
> addr)
> {
> - unsigned int op;
> + struct ppc_inst op;
> void *ip = (void *)rec->ip;
> unsigned long tramp, entry, ptr;
>
> @@ -669,7 +670,7 @@ static int __ftrace_make_call_kernel(struct dyn_ftrace
> *rec, unsigned long addr)
> int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
> {
> unsigned long ip = rec->ip;
> - unsigned int old, new;
> + struct ppc_inst old, new;
>
> /*
> * If the calling address is more that 24 bits away,
> @@ -708,7 +709,7 @@ static int
> __ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
> unsigned long addr)
> {
> - unsigned int op;
> + struct ppc_inst op;
> unsigned long ip = rec->ip;
> unsigned long entry, ptr, tramp;
> struct module *mod = rec->arch.mod;
> @@ -756,7 +757,7 @@ __ftrace_modify_call(struct dyn_ftrace *rec, unsigned
> long old_addr,
> /* The new target may be within range */
> if (test_24bit_addr(ip, addr)) {
> /* within range */
> - if (patch_branch((unsigned int *)ip, addr, BRANCH_SET_LINK)) {
> + if (patch_branch((struct ppc_inst *)ip, addr, BRANCH_SET_LINK))
> {
> pr_err("REL24 out of range!\n");
> return -EINVAL;
> }
> @@ -784,12 +785,12 @@ __ftrace_modify_call(struct dyn_ftrace *rec, unsigned
> long old_addr,
> }
>
> /* Ensure branch is within 24 bits */
> - if (create_branch(&op, (unsigned int *)ip, tramp, BRANCH_SET_LINK)) {
> + if (create_branch(&op, (struct ppc_inst *)ip, tramp, BRANCH_SET_LINK))
> {
> pr_err("Branch out of range\n");
> return -EINVAL;
> }
>
> - if (patch_branch((unsigned int *)ip, tramp, BRANCH_SET_LINK)) {
> + if (patch_branch((struct ppc_inst *)ip, tramp, BRANCH_SET_LINK)) {
> pr_err("REL24 out of range!\n");
> return -EINVAL;
> }
> @@ -802,7 +803,7 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned
> long old_addr,
> unsigned long addr)
> {
> unsigned long ip = rec->ip;
> - unsigned int old, new;
> + struct ppc_inst old, new;
>
> /*
> * If the calling address is more that 24 bits away,
> @@ -842,10 +843,10 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned
> long old_addr,
> int ftrace_update_ftrace_func(ftrace_func_t func)
> {
> unsigned long ip = (unsigned long)(&ftrace_call);
> - unsigned int old, new;
> + struct ppc_inst old, new;
> int ret;
>
> - old = *(unsigned int *)&ftrace_call;
> + old = *(struct ppc_inst *)&ftrace_call;
> new = ftrace_call_replace(ip, (unsigned long)func, 1);
> ret = ftrace_modify_code(ip, old, new);
>
> @@ -853,7 +854,7 @@ int ftrace_update_ftrace_func(ftrace_func_t func)
> /* Also update the regs callback function */
> if (!ret) {
> ip = (unsigned long)(&ftrace_regs_call);
> - old = *(unsigned int *)&ftrace_regs_call;
> + old = *(struct ppc_inst *)&ftrace_regs_call;
> new = ftrace_call_replace(ip, (unsigned long)func, 1);
> ret = ftrace_modify_code(ip, old, new);
> }
> @@ -927,7 +928,7 @@ int ftrace_enable_ftrace_graph_caller(void)
> unsigned long ip = (unsigned long)(&ftrace_graph_call);
> unsigned long addr = (unsigned long)(&ftrace_graph_caller);
> unsigned long stub = (unsigned long)(&ftrace_graph_stub);
> - unsigned int old, new;
> + struct ppc_inst old, new;
>
> old = ftrace_call_replace(ip, stub, 0);
> new = ftrace_call_replace(ip, addr, 0);
> @@ -940,7 +941,7 @@ int ftrace_disable_ftrace_graph_caller(void)
> unsigned long ip = (unsigned long)(&ftrace_graph_call);
> unsigned long addr = (unsigned long)(&ftrace_graph_caller);
> unsigned long stub = (unsigned long)(&ftrace_graph_stub);
> - unsigned int old, new;
> + struct ppc_inst old, new;
>
> old = ftrace_call_replace(ip, addr, 0);
> new = ftrace_call_replace(ip, stub, 0);
> diff --git a/arch/powerpc/kernel/vecemu.c b/arch/powerpc/kernel/vecemu.c
> index c8d21e812d8c..bbf536e10902 100644
> --- a/arch/powerpc/kernel/vecemu.c
> +++ b/arch/powerpc/kernel/vecemu.c
> @@ -261,11 +261,12 @@ static unsigned int rfin(unsigned int x)
>
> int emulate_altivec(struct pt_regs *regs)
> {
> - unsigned int instr, i, word;
> + struct ppc_inst instr;
> + unsigned int i, word;
> unsigned int va, vb, vc, vd;
> vector128 *vrs;
>
> - if (get_user(instr, (unsigned int __user *) regs->nip))
> + if (get_user(instr.val, (unsigned int __user *) regs->nip))
[...] reference to above for using helper.
> return -EFAULT;
>
> word = ppc_inst_val(instr);
> diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-
> patching.c
> index 33654c6334a9..91be4a0b51cb 100644
> --- a/arch/powerpc/lib/code-patching.c
> +++ b/arch/powerpc/lib/code-patching.c
> @@ -19,12 +19,12 @@
> #include <asm/setup.h>
> #include <asm/inst.h>
>
> -static int __patch_instruction(unsigned int *exec_addr, unsigned int instr,
> - unsigned int *patch_addr)
> +static int __patch_instruction(struct ppc_inst *exec_addr, struct ppc_inst
> instr,
> + struct ppc_inst *patch_addr)
> {
> int err = 0;
>
> - __put_user_asm(instr, patch_addr, err, "stw");
> + __put_user_asm(ppc_inst_val(instr), patch_addr, err, "stw");
> if (err)
> return err;
>
> @@ -34,7 +34,7 @@ static int __patch_instruction(unsigned int *exec_addr,
> unsigned int instr,
> return 0;
> }
>
> -int raw_patch_instruction(unsigned int *addr, unsigned int instr)
> +int raw_patch_instruction(struct ppc_inst *addr, struct ppc_inst instr)
> {
> return __patch_instruction(addr, instr, addr);
> }
> @@ -137,10 +137,10 @@ static inline int unmap_patch_area(unsigned long addr)
> return 0;
> }
>
> -static int do_patch_instruction(unsigned int *addr, unsigned int instr)
> +static int do_patch_instruction(struct ppc_inst *addr, struct ppc_inst
> instr)
> {
> int err;
> - unsigned int *patch_addr = NULL;
> + struct ppc_inst *patch_addr = NULL;
> unsigned long flags;
> unsigned long text_poke_addr;
> unsigned long kaddr = (unsigned long)addr;
> @@ -177,14 +177,14 @@ static int do_patch_instruction(unsigned int *addr,
> unsigned int instr)
> }
> #else /* !CONFIG_STRICT_KERNEL_RWX */
>
> -static int do_patch_instruction(unsigned int *addr, unsigned int instr)
> +static int do_patch_instruction(struct ppc_inst *addr, struct ppc_inst
> instr)
> {
> return raw_patch_instruction(addr, instr);
> }
>
> #endif /* CONFIG_STRICT_KERNEL_RWX */
>
> -int patch_instruction(unsigned int *addr, unsigned int instr)
> +int patch_instruction(struct ppc_inst *addr, struct ppc_inst instr)
> {
> /* Make sure we aren't patching a freed init section */
> if (init_mem_is_free && init_section_contains(addr, 4)) {
> @@ -195,9 +195,9 @@ int patch_instruction(unsigned int *addr, unsigned int
> instr)
> }
> NOKPROBE_SYMBOL(patch_instruction);
>
> -int patch_branch(unsigned int *addr, unsigned long target, int flags)
> +int patch_branch(struct ppc_inst *addr, unsigned long target, int flags)
> {
> - unsigned int instr;
> + struct ppc_inst instr;
>
> create_branch(&instr, addr, target, flags);
> return patch_instruction(addr, instr);
> @@ -229,7 +229,7 @@ bool is_offset_in_branch_range(long offset)
> * Helper to check if a given instruction is a conditional branch
> * Derived from the conditional checks in analyse_instr()
> */
> -bool is_conditional_branch(unsigned int instr)
> +bool is_conditional_branch(struct ppc_inst instr)
> {
> unsigned int opcode = ppc_inst_opcode(instr);
>
> @@ -247,13 +247,13 @@ bool is_conditional_branch(unsigned int instr)
> }
> NOKPROBE_SYMBOL(is_conditional_branch);
>
> -int create_branch(unsigned int *instr,
> - const unsigned int *addr,
> +int create_branch(struct ppc_inst *instr,
> + const struct ppc_inst *addr,
> unsigned long target, int flags)
> {
> long offset;
>
> - *instr = 0;
> + *instr = ppc_inst(0);
> offset = target;
> if (! (flags & BRANCH_ABSOLUTE))
> offset = offset - (unsigned long)addr;
> @@ -263,12 +263,12 @@ int create_branch(unsigned int *instr,
> return 1;
>
> /* Mask out the flags and target, so they don't step on each other. */
> - *instr = 0x48000000 | (flags & 0x3) | (offset & 0x03FFFFFC);
> + *instr = ppc_inst(0x48000000 | (flags & 0x3) | (offset & 0x03FFFFFC));
>
> return 0;
> }
>
> -int create_cond_branch(unsigned int *instr, const unsigned int *addr,
> +int create_cond_branch(struct ppc_inst *instr, const struct ppc_inst *addr,
> unsigned long target, int flags)
> {
> long offset;
> @@ -282,27 +282,27 @@ int create_cond_branch(unsigned int *instr, const
> unsigned int *addr,
> return 1;
>
> /* Mask out the flags and target, so they don't step on each other. */
> - *instr = 0x40000000 | (flags & 0x3FF0003) | (offset & 0xFFFC);
> + *instr = ppc_inst(0x40000000 | (flags & 0x3FF0003) | (offset &
> 0xFFFC));
>
> return 0;
> }
>
> -static unsigned int branch_opcode(unsigned int instr)
> +static unsigned int branch_opcode(struct ppc_inst instr)
> {
> return ppc_inst_opcode(instr) & 0x3F;
> }
>
> -static int instr_is_branch_iform(unsigned int instr)
> +static int instr_is_branch_iform(struct ppc_inst instr)
> {
> return branch_opcode(instr) == 18;
> }
>
> -static int instr_is_branch_bform(unsigned int instr)
> +static int instr_is_branch_bform(struct ppc_inst instr)
> {
> return branch_opcode(instr) == 16;
> }
>
> -int instr_is_relative_branch(unsigned int instr)
> +int instr_is_relative_branch(struct ppc_inst instr)
> {
> if (ppc_inst_val(instr) & BRANCH_ABSOLUTE)
> return 0;
> @@ -310,12 +310,12 @@ int instr_is_relative_branch(unsigned int instr)
> return instr_is_branch_iform(instr) || instr_is_branch_bform(instr);
> }
>
> -int instr_is_relative_link_branch(unsigned int instr)
> +int instr_is_relative_link_branch(struct ppc_inst instr)
> {
> return instr_is_relative_branch(instr) && (ppc_inst_val(instr) &
> BRANCH_SET_LINK);
> }
>
> -static unsigned long branch_iform_target(const unsigned int *instr)
> +static unsigned long branch_iform_target(const struct ppc_inst *instr)
> {
> signed long imm;
>
> @@ -331,7 +331,7 @@ static unsigned long branch_iform_target(const unsigned
> int *instr)
> return (unsigned long)imm;
> }
>
> -static unsigned long branch_bform_target(const unsigned int *instr)
> +static unsigned long branch_bform_target(const struct ppc_inst *instr)
> {
> signed long imm;
>
> @@ -347,7 +347,7 @@ static unsigned long branch_bform_target(const unsigned
> int *instr)
> return (unsigned long)imm;
> }
>
> -unsigned long branch_target(const unsigned int *instr)
> +unsigned long branch_target(const struct ppc_inst *instr)
> {
> if (instr_is_branch_iform(*instr))
> return branch_iform_target(instr);
> @@ -357,7 +357,7 @@ unsigned long branch_target(const unsigned int *instr)
> return 0;
> }
>
> -int instr_is_branch_to_addr(const unsigned int *instr, unsigned long addr)
> +int instr_is_branch_to_addr(const struct ppc_inst *instr, unsigned long
> addr)
> {
> if (instr_is_branch_iform(*instr) || instr_is_branch_bform(*instr))
> return branch_target(instr) == addr;
> @@ -365,7 +365,7 @@ int instr_is_branch_to_addr(const unsigned int *instr,
> unsigned long addr)
> return 0;
> }
>
> -int translate_branch(unsigned int *instr, const unsigned int *dest, const
> unsigned int *src)
> +int translate_branch(struct ppc_inst *instr, const struct ppc_inst *dest,
> const struct ppc_inst *src)
> {
> unsigned long target;
>
> @@ -408,7 +408,7 @@ static void __init test_trampoline(void)
> static void __init test_branch_iform(void)
> {
> int err;
> - unsigned int instr;
> + struct ppc_inst instr;
> unsigned long addr;
>
> addr = (unsigned long)&instr;
> @@ -483,12 +483,12 @@ static void __init test_branch_iform(void)
>
> static void __init test_create_function_call(void)
> {
> - unsigned int *iptr;
> + struct ppc_inst *iptr;
> unsigned long dest;
> - unsigned int instr;
> + struct ppc_inst instr;
>
> /* Check we can create a function call */
> - iptr = (unsigned int *)ppc_function_entry(test_trampoline);
> + iptr = (struct ppc_inst *)ppc_function_entry(test_trampoline);
> dest = ppc_function_entry(test_create_function_call);
> create_branch(&instr, iptr, dest, BRANCH_SET_LINK);
> patch_instruction(iptr, instr);
> @@ -499,7 +499,8 @@ static void __init test_branch_bform(void)
> {
> int err;
> unsigned long addr;
> - unsigned int *iptr, instr, flags;
> + struct ppc_inst *iptr, instr;
> + unsigned int flags;
>
> iptr = &instr;
> addr = (unsigned long)iptr;
> @@ -569,8 +570,8 @@ static void __init test_branch_bform(void)
> static void __init test_translate_branch(void)
> {
> unsigned long addr;
> - unsigned int *p, *q;
> - unsigned int instr;
> + struct ppc_inst *p, *q;
> + struct ppc_inst instr;
> void *buf;
>
> buf = vmalloc(PAGE_ALIGN(0x2000000 + 1));
> diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-
> fixups.c
> index 6e7479b8887a..8c5d0db77013 100644
> --- a/arch/powerpc/lib/feature-fixups.c
> +++ b/arch/powerpc/lib/feature-fixups.c
> @@ -32,26 +32,26 @@ struct fixup_entry {
> long alt_end_off;
> };
>
> -static unsigned int *calc_addr(struct fixup_entry *fcur, long offset)
> +static struct ppc_inst *calc_addr(struct fixup_entry *fcur, long offset)
> {
> /*
> * We store the offset to the code as a negative offset from
> * the start of the alt_entry, to support the VDSO. This
> * routine converts that back into an actual address.
> */
> - return (unsigned int *)((unsigned long)fcur + offset);
> + return (struct ppc_inst *)((unsigned long)fcur + offset);
> }
>
> -static int patch_alt_instruction(unsigned int *src, unsigned int *dest,
> - unsigned int *alt_start, unsigned int
> *alt_end)
> +static int patch_alt_instruction(struct ppc_inst *src, struct ppc_inst
> *dest,
> + struct ppc_inst *alt_start, struct ppc_inst
> *alt_end)
> {
> int err;
> - unsigned int instr;
> + struct ppc_inst instr;
>
> instr = *src;
>
> if (instr_is_relative_branch(*src)) {
> - unsigned int *target = (unsigned int *)branch_target(src);
> + struct ppc_inst *target = (struct ppc_inst
> *)branch_target(src);
>
> /* Branch within the section doesn't need translating */
> if (target < alt_start || target > alt_end) {
> @@ -68,7 +68,7 @@ static int patch_alt_instruction(unsigned int *src,
> unsigned int *dest,
>
> static int patch_feature_section(unsigned long value, struct fixup_entry
> *fcur)
> {
> - unsigned int *start, *end, *alt_start, *alt_end, *src, *dest;
> + struct ppc_inst *start, *end, *alt_start, *alt_end, *src, *dest;
>
> start = calc_addr(fcur, fcur->start_off);
> end = calc_addr(fcur, fcur->end_off);
> @@ -147,15 +147,15 @@ static void do_stf_entry_barrier_fixups(enum
> stf_barrier_type types)
>
> pr_devel("patching dest %lx\n", (unsigned long)dest);
>
> - patch_instruction(dest, ppc_inst(instrs[0]));
> + patch_instruction((struct ppc_inst *)dest,
> ppc_inst(instrs[0]));
we had already declared them as struct ppc_inst *
>
> if (types & STF_BARRIER_FALLBACK)
> - patch_branch(dest + 1, (unsigned
> long)&stf_barrier_fallback,
> + patch_branch((struct ppc_inst *)(dest + 1), (unsigned
> long)&stf_barrier_fallback,
> BRANCH_SET_LINK);
> else
> - patch_instruction(dest + 1, ppc_inst(instrs[1]));
> + patch_instruction((struct ppc_inst *)(dest + 1),
> ppc_inst(instrs[1]));
>
> - patch_instruction(dest + 2, ppc_inst(instrs[2]));
> + patch_instruction((struct ppc_inst *)(dest + 2),
> ppc_inst(instrs[2]));
> }
>
> printk(KERN_DEBUG "stf-barrier: patched %d entry locations (%s
> barrier)\n", i,
> @@ -208,12 +208,12 @@ static void do_stf_exit_barrier_fixups(enum
> stf_barrier_type types)
>
> pr_devel("patching dest %lx\n", (unsigned long)dest);
>
> - patch_instruction(dest, ppc_inst(instrs[0]));
> - patch_instruction(dest + 1, ppc_inst(instrs[1]));
> - patch_instruction(dest + 2, ppc_inst(instrs[2]));
> - patch_instruction(dest + 3, ppc_inst(instrs[3]));
> - patch_instruction(dest + 4, ppc_inst(instrs[4]));
> - patch_instruction(dest + 5, ppc_inst(instrs[5]));
> + patch_instruction((struct ppc_inst *)dest,
> ppc_inst(instrs[0]));
> + patch_instruction((struct ppc_inst *)(dest + 1),
> ppc_inst(instrs[1]));
> + patch_instruction((struct ppc_inst *)(dest + 2),
> ppc_inst(instrs[2]));
> + patch_instruction((struct ppc_inst *)(dest + 3),
> ppc_inst(instrs[3]));
> + patch_instruction((struct ppc_inst *)(dest + 4),
> ppc_inst(instrs[4]));
> + patch_instruction((struct ppc_inst *)(dest + 5),
> ppc_inst(instrs[5]));
> }
> printk(KERN_DEBUG "stf-barrier: patched %d exit locations (%s
> barrier)\n", i,
> (types == STF_BARRIER_NONE) ? "no" :
> @@ -261,9 +261,9 @@ void do_rfi_flush_fixups(enum l1d_flush_type types)
>
> pr_devel("patching dest %lx\n", (unsigned long)dest);
>
> - patch_instruction(dest, ppc_inst(instrs[0]));
> - patch_instruction(dest + 1, ppc_inst(instrs[1]));
> - patch_instruction(dest + 2, ppc_inst(instrs[2]));
> + patch_instruction((struct ppc_inst *)dest,
> ppc_inst(instrs[0]));
> + patch_instruction((struct ppc_inst *)(dest + 1),
> ppc_inst(instrs[1]));
> + patch_instruction((struct ppc_inst *)(dest + 2),
> ppc_inst(instrs[2]));
> }
>
> printk(KERN_DEBUG "rfi-flush: patched %d locations (%s flush)\n", i,
> @@ -296,7 +296,7 @@ void do_barrier_nospec_fixups_range(bool enable, void
> *fixup_start, void *fixup_
> dest = (void *)start + *start;
>
> pr_devel("patching dest %lx\n", (unsigned long)dest);
> - patch_instruction(dest, ppc_inst(instr));
> + patch_instruction((struct ppc_inst *)dest, ppc_inst(instr));
> }
>
> printk(KERN_DEBUG "barrier-nospec: patched %d locations\n", i);
> @@ -339,8 +339,8 @@ void do_barrier_nospec_fixups_range(bool enable, void
> *fixup_start, void *fixup_
> dest = (void *)start + *start;
>
> pr_devel("patching dest %lx\n", (unsigned long)dest);
> - patch_instruction(dest, ppc_inst(instr[0]));
> - patch_instruction(dest + 1, ppc_inst(instr[1]));
> + patch_instruction((struct ppc_inst *)dest, ppc_inst(instr[0]));
> + patch_instruction((struct ppc_inst *)(dest + 1),
> ppc_inst(instr[1]));
> }
>
> printk(KERN_DEBUG "barrier-nospec: patched %d locations\n", i);
> @@ -373,7 +373,7 @@ void do_btb_flush_fixups(void)
> void do_lwsync_fixups(unsigned long value, void *fixup_start, void
> *fixup_end)
> {
> long *start, *end;
> - unsigned int *dest;
> + struct ppc_inst *dest;
>
> if (!(value & CPU_FTR_LWSYNC))
> return ;
> diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
> index 26e37176692e..52ddd3122dc8 100644
> --- a/arch/powerpc/lib/sstep.c
> +++ b/arch/powerpc/lib/sstep.c
> @@ -1163,7 +1163,7 @@ static nokprobe_inline int trap_compare(long v1, long
> v2)
> * otherwise.
> */
> int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
> - unsigned int instr)
> + struct ppc_inst instr)
we need to take care of `instr` inside this function as well to adopt
the helpers to work with it.
-- Bala
> {
> unsigned int opcode, ra, rb, rc, rd, spr, u;
> unsigned long int imm;
> @@ -3103,7 +3103,7 @@ NOKPROBE_SYMBOL(emulate_loadstore);
> * or -1 if the instruction is one that should not be stepped,
> * such as an rfid, or a mtmsrd that would clear MSR_RI.
> */
> -int emulate_step(struct pt_regs *regs, unsigned int instr)
> +int emulate_step(struct pt_regs *regs, struct ppc_inst instr)
> {
> struct instruction_op op;
> int r, err, type;
> diff --git a/arch/powerpc/lib/test_emulate_step.c
> b/arch/powerpc/lib/test_emulate_step.c
> index 16387a9bfda0..60b159b60545 100644
> --- a/arch/powerpc/lib/test_emulate_step.c
> +++ b/arch/powerpc/lib/test_emulate_step.c
> @@ -461,7 +461,7 @@ struct compute_test {
> struct {
> char *descr;
> unsigned long flags;
> - unsigned int instr;
> + struct ppc_inst instr;
> struct pt_regs regs;
> } subtests[MAX_SUBTESTS + 1];
> };
> @@ -842,7 +842,7 @@ static struct compute_test compute_tests[] = {
> };
>
> static int __init emulate_compute_instr(struct pt_regs *regs,
> - unsigned int instr)
> + struct ppc_inst instr)
> {
> struct instruction_op op;
>
> @@ -860,7 +860,7 @@ static int __init emulate_compute_instr(struct pt_regs
> *regs,
> }
>
> static int __init execute_compute_instr(struct pt_regs *regs,
> - unsigned int instr)
> + struct ppc_inst instr)
> {
> extern int exec_instr(struct pt_regs *regs);
> extern s32 patch__exec_instr;
> @@ -891,7 +891,8 @@ static void __init run_tests_compute(void)
> unsigned long flags;
> struct compute_test *test;
> struct pt_regs *regs, exp, got;
> - unsigned int i, j, k, instr;
> + unsigned int i, j, k;
> + struct ppc_inst instr;
> bool ignore_gpr, ignore_xer, ignore_ccr, passed;
>
> for (i = 0; i < ARRAY_SIZE(compute_tests); i++) {
> diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-
> book3s.c
> index 3086055bf681..2d2580a4bfb5 100644
> --- a/arch/powerpc/perf/core-book3s.c
> +++ b/arch/powerpc/perf/core-book3s.c
> @@ -421,14 +421,14 @@ static __u64 power_pmu_bhrb_to(u64 addr)
> if (probe_kernel_read(&instr, (void *)addr, sizeof(instr)))
> return 0;
>
> - return branch_target(&instr);
> + return branch_target((struct ppc_inst *)&instr);
> }
>
> /* Userspace: need copy instruction here then translate it */
> if (probe_user_read(&instr, (unsigned int __user *)addr,
> sizeof(instr)))
> return 0;
>
> - target = branch_target(&instr);
> + target = branch_target((struct ppc_inst *)&instr);
> if ((!target) || (instr & BRANCH_ABSOLUTE))
> return target;
>
> diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
> index f6c87d3d53ea..e3d8e1b8ce01 100644
> --- a/arch/powerpc/xmon/xmon.c
> +++ b/arch/powerpc/xmon/xmon.c
> @@ -99,7 +99,7 @@ static long *xmon_fault_jmp[NR_CPUS];
> /* Breakpoint stuff */
> struct bpt {
> unsigned long address;
> - unsigned int *instr;
> + struct ppc_inst *instr;
> atomic_t ref_count;
> int enabled;
> unsigned long pad;
> @@ -117,7 +117,7 @@ static unsigned bpinstr = 0x7fe00008; /* trap */
>
> #define BP_NUM(bp) ((bp) - bpts + 1)
>
> -#define BPT_SIZE (sizeof(unsigned int) * 2)
> +#define BPT_SIZE (sizeof(struct ppc_inst) * 2)
> #define BPT_WORDS (BPT_SIZE / sizeof(unsigned int))
> extern unsigned int bpt_table[NBPTS * BPT_WORDS];
>
> @@ -879,8 +879,8 @@ static struct bpt *new_breakpoint(unsigned long a)
> for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
> if (!bp->enabled && atomic_read(&bp->ref_count) == 0) {
> bp->address = a;
> - bp->instr = bpt_table + ((bp - bpts) * BPT_WORDS);
> - patch_instruction(bp->instr + 1, bpinstr);
> + bp->instr = (void *)(bpt_table + ((bp - bpts) *
> BPT_WORDS));
> + patch_instruction(bp->instr + 1, ppc_inst(bpinstr));
> return bp;
> }
> }
> @@ -892,7 +892,7 @@ static struct bpt *new_breakpoint(unsigned long a)
> static void insert_bpts(void)
> {
> int i;
> - unsigned int instr;
> + struct ppc_inst instr;
> struct bpt *bp;
>
> bp = bpts;
> @@ -914,8 +914,8 @@ static void insert_bpts(void)
> patch_instruction(bp->instr, instr);
> if (bp->enabled & BP_CIABR)
> continue;
> - if (patch_instruction((unsigned int *)bp->address,
> - bpinstr) != 0) {
> + if (patch_instruction((struct ppc_inst *)bp->address,
> + ppc_inst(bpinstr)) !=
> 0) {
> printf("Couldn't write instruction at %lx, "
> "disabling breakpoint there\n", bp->address);
> bp->enabled &= ~BP_TRAP;
> @@ -943,7 +943,7 @@ static void remove_bpts(void)
> {
> int i;
> struct bpt *bp;
> - unsigned instr;
> + struct ppc_inst instr;
>
> bp = bpts;
> for (i = 0; i < NBPTS; ++i, ++bp) {
> @@ -952,7 +952,7 @@ static void remove_bpts(void)
> if (mread(bp->address, &instr, 4) == 4
> && ppc_inst_equal(instr, ppc_inst(bpinstr))
> && patch_instruction(
> - (unsigned int *)bp->address, bp->instr[0]) != 0)
> + (struct ppc_inst *)bp->address, bp->instr[0]) != 0)
> printf("Couldn't remove breakpoint at %lx\n",
> bp->address);
> }
> @@ -1159,7 +1159,7 @@ static int do_step(struct pt_regs *regs)
> */
> static int do_step(struct pt_regs *regs)
> {
> - unsigned int instr;
> + struct ppc_inst instr;
> int stepped;
>
> force_enable_xmon();
> @@ -1325,7 +1325,7 @@ csum(void)
> */
> static long check_bp_loc(unsigned long addr)
> {
> - unsigned int instr;
> + struct ppc_inst instr;
>
> addr &= ~3;
> if (!is_kernel_addr(addr)) {
> @@ -2846,7 +2846,7 @@ generic_inst_dump(unsigned long adr, long count, int
> praddr,
> {
> int nr, dotted;
> unsigned long first_adr;
> - unsigned int inst, last_inst = ppc_inst(0);
> + struct ppc_inst inst, last_inst = ppc_inst(0);
> unsigned char val[4];
>
> dotted = 0;
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 10/21] powerpc: Use a function for reading instructions
2020-04-06 8:09 ` [PATCH v5 10/21] powerpc: Use a function for reading instructions Jordan Niethe
@ 2020-04-07 10:42 ` Balamuruhan S
0 siblings, 0 replies; 71+ messages in thread
From: Balamuruhan S @ 2020-04-07 10:42 UTC (permalink / raw)
To: Jordan Niethe, linuxppc-dev; +Cc: alistair, npiggin, dja
On Mon, 2020-04-06 at 18:09 +1000, Jordan Niethe wrote:
> Prefixed instructions will mean there are instructions of different
> length. As a result dereferencing a pointer to an instruction will not
> necessarily give the desired result. Introduce a function for reading
> instructions from memory into the instruction data type.
>
> Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> ---
> v4: New to series
> v5: - Rename read_inst() -> probe_kernel_read_inst()
> - No longer modify uprobe probe type in this patch
> ---
> arch/powerpc/include/asm/inst.h | 5 +++++
> arch/powerpc/kernel/kprobes.c | 11 ++++------
> arch/powerpc/kernel/mce_power.c | 2 +-
> arch/powerpc/kernel/optprobes.c | 4 ++--
> arch/powerpc/kernel/trace/ftrace.c | 33 +++++++++++++++++++-----------
> arch/powerpc/lib/code-patching.c | 23 ++++++++++-----------
> arch/powerpc/lib/feature-fixups.c | 2 +-
> arch/powerpc/xmon/xmon.c | 6 +++---
> 8 files changed, 48 insertions(+), 38 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/inst.h
> b/arch/powerpc/include/asm/inst.h
> index a71decf5f871..369b35ce964c 100644
> --- a/arch/powerpc/include/asm/inst.h
> +++ b/arch/powerpc/include/asm/inst.h
> @@ -27,6 +27,11 @@ static inline struct ppc_inst ppc_inst_swab(struct
> ppc_inst x)
> return ppc_inst(swab32(ppc_inst_val(x)));
> }
>
> +static inline struct ppc_inst ppc_inst_read(const struct ppc_inst *ptr)
> +{
> + return *ptr;
> +}
> +
> static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
> {
> return !memcmp(&x, &y, sizeof(struct ppc_inst));
> diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
> index 9ed996cb0589..ff53e5ef7e40 100644
> --- a/arch/powerpc/kernel/kprobes.c
> +++ b/arch/powerpc/kernel/kprobes.c
> @@ -106,7 +106,7 @@ kprobe_opcode_t *kprobe_lookup_name(const char *name,
> unsigned int offset)
> int arch_prepare_kprobe(struct kprobe *p)
> {
> int ret = 0;
> - struct ppc_inst insn = *(struct ppc_inst *)p->addr;
> + struct ppc_inst insn = ppc_inst_read((struct ppc_inst *)p->addr);
>
> if ((unsigned long)p->addr & 0x03) {
> printk("Attempt to register kprobe at an unaligned address\n");
> @@ -125,11 +125,8 @@ int arch_prepare_kprobe(struct kprobe *p)
> }
>
> if (!ret) {
> - memcpy(p->ainsn.insn, p->addr,
> - MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
> - p->opcode = *p->addr;
> - flush_icache_range((unsigned long)p->ainsn.insn,
> - (unsigned long)p->ainsn.insn +
> sizeof(kprobe_opcode_t));
> + patch_instruction((struct ppc_inst *)p->ainsn.insn, insn);
> + p->opcode = ppc_inst_val(insn);
This is a different change from this commit
-- Bala
> }
>
> p->ainsn.boostable = 0;
> @@ -217,7 +214,7 @@ NOKPROBE_SYMBOL(arch_prepare_kretprobe);
> static int try_to_emulate(struct kprobe *p, struct pt_regs *regs)
> {
> int ret;
> - struct ppc_inst insn = *(struct ppc_inst *)p->ainsn.insn;
> + struct ppc_inst insn = ppc_inst_read((struct ppc_inst *)p->ainsn.insn);
>
> /* regs->nip is also adjusted if emulate_step returns 1 */
> ret = emulate_step(regs, insn);
> diff --git a/arch/powerpc/kernel/mce_power.c
> b/arch/powerpc/kernel/mce_power.c
> index 7118b46a6543..859b602fa270 100644
> --- a/arch/powerpc/kernel/mce_power.c
> +++ b/arch/powerpc/kernel/mce_power.c
> @@ -374,7 +374,7 @@ static int mce_find_instr_ea_and_phys(struct pt_regs
> *regs, uint64_t *addr,
> pfn = addr_to_pfn(regs, regs->nip);
> if (pfn != ULONG_MAX) {
> instr_addr = (pfn << PAGE_SHIFT) + (regs->nip & ~PAGE_MASK);
> - instr = *(struct ppc_inst *)(instr_addr);
> + instr = ppc_inst_read((struct ppc_inst *)instr_addr);
> if (!analyse_instr(&op, &tmp, instr)) {
> pfn = addr_to_pfn(regs, op.ea);
> *addr = op.ea;
> diff --git a/arch/powerpc/kernel/optprobes.c
> b/arch/powerpc/kernel/optprobes.c
> index b61bbcee84f4..684640b8fa2e 100644
> --- a/arch/powerpc/kernel/optprobes.c
> +++ b/arch/powerpc/kernel/optprobes.c
> @@ -100,8 +100,8 @@ static unsigned long can_optimize(struct kprobe *p)
> * Ensure that the instruction is not a conditional branch,
> * and that can be emulated.
> */
> - if (!is_conditional_branch(*(struct ppc_inst *)p->ainsn.insn) &&
> - analyse_instr(&op, ®s, *(struct ppc_inst *)p-
> >ainsn.insn) == 1) {
> + if (!is_conditional_branch(ppc_inst_read((struct ppc_inst *)p-
> >ainsn.insn)) &&
> + analyse_instr(&op, ®s, ppc_inst_read((struct
> ppc_inst *)p->ainsn.insn)) == 1) {
> emulate_update_regs(®s, &op);
> nip = regs.nip;
> }
> diff --git a/arch/powerpc/kernel/trace/ftrace.c
> b/arch/powerpc/kernel/trace/ftrace.c
> index 442c62fb68ff..e78742613b36 100644
> --- a/arch/powerpc/kernel/trace/ftrace.c
> +++ b/arch/powerpc/kernel/trace/ftrace.c
> @@ -41,6 +41,12 @@
> #define NUM_FTRACE_TRAMPS 8
> static unsigned long ftrace_tramps[NUM_FTRACE_TRAMPS];
>
> +static long
> +probe_kernel_read_inst(struct ppc_inst *inst, const void *src)
> +{
> + return probe_kernel_read((void *)inst, src, MCOUNT_INSN_SIZE);
> +}
> +
> static struct ppc_inst
> ftrace_call_replace(unsigned long ip, unsigned long addr, int link)
> {
> @@ -68,7 +74,7 @@ ftrace_modify_code(unsigned long ip, struct ppc_inst old,
> struct ppc_inst new)
> */
>
> /* read the text we want to modify */
> - if (probe_kernel_read(&replaced, (void *)ip, MCOUNT_INSN_SIZE))
> + if (probe_kernel_read_inst(&replaced, (void *)ip))
> return -EFAULT;
>
> /* Make sure it is what we expect it to be */
> @@ -130,7 +136,7 @@ __ftrace_make_nop(struct module *mod,
> struct ppc_inst op, pop;
>
> /* read where this goes */
> - if (probe_kernel_read(&op, (void *)ip, sizeof(int))) {
> + if (probe_kernel_read_inst(&op, (void *)ip)) {
> pr_err("Fetching opcode failed.\n");
> return -EFAULT;
> }
> @@ -164,7 +170,7 @@ __ftrace_make_nop(struct module *mod,
> /* When using -mkernel_profile there is no load to jump over */
> pop = ppc_inst(PPC_INST_NOP);
>
> - if (probe_kernel_read(&op, (void *)(ip - 4), 4)) {
> + if (probe_kernel_read_inst(&op, (void *)(ip - 4))) {
> pr_err("Fetching instruction at %lx failed.\n", ip - 4);
> return -EFAULT;
> }
> @@ -196,7 +202,7 @@ __ftrace_make_nop(struct module *mod,
> * Check what is in the next instruction. We can see ld r2,40(r1), but
> * on first pass after boot we will see mflr r0.
> */
> - if (probe_kernel_read(&op, (void *)(ip+4), MCOUNT_INSN_SIZE)) {
> + if (probe_kernel_read_inst(&op, (void *)(ip+4))) {
> pr_err("Fetching op failed.\n");
> return -EFAULT;
> }
> @@ -348,7 +354,7 @@ static int setup_mcount_compiler_tramp(unsigned long
> tramp)
> return -1;
>
> /* New trampoline -- read where this goes */
> - if (probe_kernel_read(&op, (void *)tramp, sizeof(int))) {
> + if (probe_kernel_read_inst(&op, (void *)tramp)) {
> pr_debug("Fetching opcode failed.\n");
> return -1;
> }
> @@ -398,7 +404,7 @@ static int __ftrace_make_nop_kernel(struct dyn_ftrace
> *rec, unsigned long addr)
> struct ppc_inst op;
>
> /* Read where this goes */
> - if (probe_kernel_read(&op, (void *)ip, sizeof(int))) {
> + if (probe_kernel_read_inst(&op, (void *)ip)) {
> pr_err("Fetching opcode failed.\n");
> return -EFAULT;
> }
> @@ -524,7 +530,10 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long
> addr)
> struct module *mod = rec->arch.mod;
>
> /* read where this goes */
> - if (probe_kernel_read(op, ip, sizeof(op)))
> + if (probe_kernel_read_inst(op, ip))
> + return -EFAULT;
> +
> + if (probe_kernel_read_inst(op + 1, ip + 4))
> return -EFAULT;
>
> if (!expected_nop_sequence(ip, op[0], op[1])) {
> @@ -587,7 +596,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long
> addr)
> unsigned long ip = rec->ip;
>
> /* read where this goes */
> - if (probe_kernel_read(&op, (void *)ip, MCOUNT_INSN_SIZE))
> + if (probe_kernel_read_inst(&op, (void *)ip))
> return -EFAULT;
>
> /* It should be pointing to a nop */
> @@ -643,7 +652,7 @@ static int __ftrace_make_call_kernel(struct dyn_ftrace
> *rec, unsigned long addr)
> }
>
> /* Make sure we have a nop */
> - if (probe_kernel_read(&op, ip, sizeof(op))) {
> + if (probe_kernel_read_inst(&op, ip)) {
> pr_err("Unable to read ftrace location %p\n", ip);
> return -EFAULT;
> }
> @@ -721,7 +730,7 @@ __ftrace_modify_call(struct dyn_ftrace *rec, unsigned
> long old_addr,
> }
>
> /* read where this goes */
> - if (probe_kernel_read(&op, (void *)ip, sizeof(int))) {
> + if (probe_kernel_read_inst(&op, (void *)ip)) {
> pr_err("Fetching opcode failed.\n");
> return -EFAULT;
> }
> @@ -846,7 +855,7 @@ int ftrace_update_ftrace_func(ftrace_func_t func)
> struct ppc_inst old, new;
> int ret;
>
> - old = *(struct ppc_inst *)&ftrace_call;
> + old = ppc_inst_read((struct ppc_inst *)&ftrace_call);
> new = ftrace_call_replace(ip, (unsigned long)func, 1);
> ret = ftrace_modify_code(ip, old, new);
>
> @@ -854,7 +863,7 @@ int ftrace_update_ftrace_func(ftrace_func_t func)
> /* Also update the regs callback function */
> if (!ret) {
> ip = (unsigned long)(&ftrace_regs_call);
> - old = *(struct ppc_inst *)&ftrace_regs_call;
> + old = ppc_inst_read((struct ppc_inst *)&ftrace_regs_call);
> new = ftrace_call_replace(ip, (unsigned long)func, 1);
> ret = ftrace_modify_code(ip, old, new);
> }
> diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-
> patching.c
> index 91be4a0b51cb..ba08f3815d00 100644
> --- a/arch/powerpc/lib/code-patching.c
> +++ b/arch/powerpc/lib/code-patching.c
> @@ -349,9 +349,9 @@ static unsigned long branch_bform_target(const struct
> ppc_inst *instr)
>
> unsigned long branch_target(const struct ppc_inst *instr)
> {
> - if (instr_is_branch_iform(*instr))
> + if (instr_is_branch_iform(ppc_inst_read(instr)))
> return branch_iform_target(instr);
> - else if (instr_is_branch_bform(*instr))
> + else if (instr_is_branch_bform(ppc_inst_read(instr)))
> return branch_bform_target(instr);
>
> return 0;
> @@ -359,7 +359,7 @@ unsigned long branch_target(const struct ppc_inst *instr)
>
> int instr_is_branch_to_addr(const struct ppc_inst *instr, unsigned long
> addr)
> {
> - if (instr_is_branch_iform(*instr) || instr_is_branch_bform(*instr))
> + if (instr_is_branch_iform(ppc_inst_read(instr)) ||
> instr_is_branch_bform(ppc_inst_read(instr)))
> return branch_target(instr) == addr;
>
> return 0;
> @@ -368,13 +368,12 @@ int instr_is_branch_to_addr(const struct ppc_inst
> *instr, unsigned long addr)
> int translate_branch(struct ppc_inst *instr, const struct ppc_inst *dest,
> const struct ppc_inst *src)
> {
> unsigned long target;
> -
> target = branch_target(src);
>
> - if (instr_is_branch_iform(*src))
> - return create_branch(instr, dest, target, ppc_inst_val(*src));
> - else if (instr_is_branch_bform(*src))
> - return create_cond_branch(instr, dest, target,
> ppc_inst_val(*src));
> + if (instr_is_branch_iform(ppc_inst_read(src)))
> + return create_branch(instr, dest, target,
> ppc_inst_val(ppc_inst_read(src)));
> + else if (instr_is_branch_bform(ppc_inst_read(src)))
> + return create_cond_branch(instr, dest, target,
> ppc_inst_val(ppc_inst_read(src)));
>
> return 1;
> }
> @@ -598,7 +597,7 @@ static void __init test_translate_branch(void)
> patch_instruction(q, instr);
> check(instr_is_branch_to_addr(p, addr));
> check(instr_is_branch_to_addr(q, addr));
> - check(ppc_inst_equal(*q, ppc_inst(0x4a000000)));
> + check(ppc_inst_equal(ppc_inst_read(q), ppc_inst(0x4a000000)));
>
> /* Maximum positive case, move x to x - 32 MB + 4 */
> p = buf + 0x2000000;
> @@ -609,7 +608,7 @@ static void __init test_translate_branch(void)
> patch_instruction(q, instr);
> check(instr_is_branch_to_addr(p, addr));
> check(instr_is_branch_to_addr(q, addr));
> - check(ppc_inst_equal(*q, ppc_inst(0x49fffffc)));
> + check(ppc_inst_equal(ppc_inst_read(q), ppc_inst(0x49fffffc)));
>
> /* Jump to x + 16 MB moved to x + 20 MB */
> p = buf;
> @@ -655,7 +654,7 @@ static void __init test_translate_branch(void)
> patch_instruction(q, instr);
> check(instr_is_branch_to_addr(p, addr));
> check(instr_is_branch_to_addr(q, addr));
> - check(ppc_inst_equal(*q, ppc_inst(0x43ff8000)));
> + check(ppc_inst_equal(ppc_inst_read(q), ppc_inst(0x43ff8000)));
>
> /* Maximum positive case, move x to x - 32 KB + 4 */
> p = buf + 0x8000;
> @@ -667,7 +666,7 @@ static void __init test_translate_branch(void)
> patch_instruction(q, instr);
> check(instr_is_branch_to_addr(p, addr));
> check(instr_is_branch_to_addr(q, addr));
> - check(ppc_inst_equal(*q, ppc_inst(0x43ff7ffc)));
> + check(ppc_inst_equal(ppc_inst_read(q), ppc_inst(0x43ff7ffc)));
>
> /* Jump to x + 12 KB moved to x + 20 KB */
> p = buf;
> diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-
> fixups.c
> index 8c5d0db77013..f00dd13b1c3c 100644
> --- a/arch/powerpc/lib/feature-fixups.c
> +++ b/arch/powerpc/lib/feature-fixups.c
> @@ -48,7 +48,7 @@ static int patch_alt_instruction(struct ppc_inst *src,
> struct ppc_inst *dest,
> int err;
> struct ppc_inst instr;
>
> - instr = *src;
> + instr = ppc_inst_read(src);
>
> if (instr_is_relative_branch(*src)) {
> struct ppc_inst *target = (struct ppc_inst
> *)branch_target(src);
> diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
> index e3d8e1b8ce01..5e3949322a6c 100644
> --- a/arch/powerpc/xmon/xmon.c
> +++ b/arch/powerpc/xmon/xmon.c
> @@ -705,13 +705,13 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
> if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT)) {
> bp = at_breakpoint(regs->nip);
> if (bp != NULL) {
> - int stepped = emulate_step(regs, bp->instr[0]);
> + int stepped = emulate_step(regs, ppc_inst_read(bp-
> >instr));
> if (stepped == 0) {
> regs->nip = (unsigned long) &bp->instr[0];
> atomic_inc(&bp->ref_count);
> } else if (stepped < 0) {
> printf("Couldn't single-step %s instruction\n",
> - (IS_RFID(bp->instr[0])? "rfid": "mtmsrd"));
> + IS_RFID(ppc_inst_read(bp->instr))? "rfid":
> "mtmsrd");
> }
> }
> }
> @@ -952,7 +952,7 @@ static void remove_bpts(void)
> if (mread(bp->address, &instr, 4) == 4
> && ppc_inst_equal(instr, ppc_inst(bpinstr))
> && patch_instruction(
> - (struct ppc_inst *)bp->address, bp->instr[0]) != 0)
> + (struct ppc_inst *)bp->address, ppc_inst_read(bp-
> >instr)) != 0)
> printf("Couldn't remove breakpoint at %lx\n",
> bp->address);
> }
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 11/21] powerpc: Define and use __get_user_instr{, inatomic}()
2020-04-06 8:09 ` [PATCH v5 11/21] powerpc: Define and use __get_user_instr{, inatomic}() Jordan Niethe
@ 2020-04-07 10:48 ` Balamuruhan S
2020-04-08 2:13 ` Jordan Niethe
0 siblings, 1 reply; 71+ messages in thread
From: Balamuruhan S @ 2020-04-07 10:48 UTC (permalink / raw)
To: Jordan Niethe, linuxppc-dev; +Cc: alistair, npiggin, dja
On Mon, 2020-04-06 at 18:09 +1000, Jordan Niethe wrote:
> Define specific __get_user_instr() and __get_user_instr_inatomic()
> macros for reading instructions from user space.
>
> Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> ---
> arch/powerpc/include/asm/uaccess.h | 5 +++++
> arch/powerpc/kernel/align.c | 2 +-
> arch/powerpc/kernel/hw_breakpoint.c | 2 +-
> arch/powerpc/kernel/vecemu.c | 2 +-
> 4 files changed, 8 insertions(+), 3 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/uaccess.h
> b/arch/powerpc/include/asm/uaccess.h
> index 2f500debae21..c0a35e4586a5 100644
> --- a/arch/powerpc/include/asm/uaccess.h
> +++ b/arch/powerpc/include/asm/uaccess.h
> @@ -105,6 +105,11 @@ 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)))
>
> +#define __get_user_instr(x, ptr) \
> + __get_user_nocheck((x).val, (u32 *)(ptr), sizeof(u32), true)
> +
> +#define __get_user_instr_inatomic(x, ptr) \
> + __get_user_nosleep((x).val, (u32 *)(ptr), sizeof(u32))
should we use ppc_inst_val() ?
-- Bala
> extern long __put_user_bad(void);
>
> /*
> diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
> index 66a6d1de7799..65cdfd41e3a1 100644
> --- a/arch/powerpc/kernel/align.c
> +++ b/arch/powerpc/kernel/align.c
> @@ -304,7 +304,7 @@ int fix_alignment(struct pt_regs *regs)
> */
> CHECK_FULL_REGS(regs);
>
> - if (unlikely(__get_user(instr.val, (unsigned int __user *)regs->nip)))
> + if (unlikely(__get_user_instr(instr, (void __user *)regs->nip)))
> return -EFAULT;
> if ((regs->msr & MSR_LE) != (MSR_KERNEL & MSR_LE)) {
> /* We don't handle PPC little-endian any more... */
> diff --git a/arch/powerpc/kernel/hw_breakpoint.c
> b/arch/powerpc/kernel/hw_breakpoint.c
> index 542f65ccf68b..cebab14e2788 100644
> --- a/arch/powerpc/kernel/hw_breakpoint.c
> +++ b/arch/powerpc/kernel/hw_breakpoint.c
> @@ -249,7 +249,7 @@ static bool stepping_handler(struct pt_regs *regs, struct
> perf_event *bp,
> struct instruction_op op;
> unsigned long addr = info->address;
>
> - if (__get_user_inatomic(instr.val, (unsigned int *)regs->nip))
> + if (__get_user_instr_inatomic(instr, (void __user *)regs->nip))
> goto fail;
>
> ret = analyse_instr(&op, regs, instr);
> diff --git a/arch/powerpc/kernel/vecemu.c b/arch/powerpc/kernel/vecemu.c
> index bbf536e10902..c82ede46d71b 100644
> --- a/arch/powerpc/kernel/vecemu.c
> +++ b/arch/powerpc/kernel/vecemu.c
> @@ -266,7 +266,7 @@ int emulate_altivec(struct pt_regs *regs)
> unsigned int va, vb, vc, vd;
> vector128 *vrs;
>
> - if (get_user(instr.val, (unsigned int __user *) regs->nip))
> + if (__get_user_instr(instr, (void __user *) regs->nip))
> return -EFAULT;
>
> word = ppc_inst_val(instr);
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 12/21] powerpc: Introduce a function for reporting instruction length
2020-04-06 8:09 ` [PATCH v5 12/21] powerpc: Introduce a function for reporting instruction length Jordan Niethe
@ 2020-04-07 11:14 ` Balamuruhan S
2020-04-08 2:14 ` Jordan Niethe
0 siblings, 1 reply; 71+ messages in thread
From: Balamuruhan S @ 2020-04-07 11:14 UTC (permalink / raw)
To: Jordan Niethe, linuxppc-dev; +Cc: alistair, npiggin, dja
On Mon, 2020-04-06 at 18:09 +1000, Jordan Niethe wrote:
> Currently all instructions have the same length, but in preparation for
> prefixed instructions introduce a function for returning instruction
> length.
>
> Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> ---
> arch/powerpc/include/asm/inst.h | 5 +++++
> arch/powerpc/kernel/kprobes.c | 6 ++++--
> arch/powerpc/kernel/uprobes.c | 2 +-
> 3 files changed, 10 insertions(+), 3 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/inst.h
> b/arch/powerpc/include/asm/inst.h
> index 369b35ce964c..70b37a35a91a 100644
> --- a/arch/powerpc/include/asm/inst.h
> +++ b/arch/powerpc/include/asm/inst.h
> @@ -17,6 +17,11 @@ static inline u32 ppc_inst_val(struct ppc_inst x)
> return x.val;
> }
>
> +static inline bool ppc_inst_len(struct ppc_inst x)
return type shouldn't be a bool, `size_t` instead.
-- Bala
> +{
> + return sizeof(struct ppc_inst);
> +}
> +
> static inline int ppc_inst_opcode(struct ppc_inst x)
> {
> return x.val >> 26;
> diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
> index ff53e5ef7e40..8d17cfdcdc54 100644
> --- a/arch/powerpc/kernel/kprobes.c
> +++ b/arch/powerpc/kernel/kprobes.c
> @@ -474,14 +474,16 @@ NOKPROBE_SYMBOL(trampoline_probe_handler);
> */
> int kprobe_post_handler(struct pt_regs *regs)
> {
> + int len;
> struct kprobe *cur = kprobe_running();
> struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
>
> if (!cur || user_mode(regs))
> return 0;
>
> + len = ppc_inst_len(ppc_inst_read((struct ppc_inst *)cur->ainsn.insn));
> /* make sure we got here for instruction we have a kprobe on */
> - if (((unsigned long)cur->ainsn.insn + 4) != regs->nip)
> + if (((unsigned long)cur->ainsn.insn + len) != regs->nip)
> return 0;
>
> if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) {
> @@ -490,7 +492,7 @@ int kprobe_post_handler(struct pt_regs *regs)
> }
>
> /* Adjust nip to after the single-stepped instruction */
> - regs->nip = (unsigned long)cur->addr + 4;
> + regs->nip = (unsigned long)cur->addr + len;
> regs->msr |= kcb->kprobe_saved_msr;
>
> /*Restore back the original saved kprobes variables and continue. */
> diff --git a/arch/powerpc/kernel/uprobes.c b/arch/powerpc/kernel/uprobes.c
> index 31c870287f2b..8e63afa012ba 100644
> --- a/arch/powerpc/kernel/uprobes.c
> +++ b/arch/powerpc/kernel/uprobes.c
> @@ -112,7 +112,7 @@ int arch_uprobe_post_xol(struct arch_uprobe *auprobe,
> struct pt_regs *regs)
> * support doesn't exist and have to fix-up the next instruction
> * to be executed.
> */
> - regs->nip = utask->vaddr + MAX_UINSN_BYTES;
> + regs->nip = utask->vaddr + ppc_inst_len(auprobe->insn);
>
> user_disable_single_step(current);
> return 0;
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 13/21] powerpc/xmon: Use a function for reading instructions
2020-04-06 8:09 ` [PATCH v5 13/21] powerpc/xmon: Use a function for reading instructions Jordan Niethe
@ 2020-04-07 11:30 ` Balamuruhan S
2020-04-08 2:18 ` Jordan Niethe
0 siblings, 1 reply; 71+ messages in thread
From: Balamuruhan S @ 2020-04-07 11:30 UTC (permalink / raw)
To: Jordan Niethe, linuxppc-dev; +Cc: alistair, npiggin, dja
On Mon, 2020-04-06 at 18:09 +1000, Jordan Niethe wrote:
> Currently in xmon, mread() is used for reading instructions. In
> preparation for prefixed instructions, create and use a new function,
> mread_instr(), especially for reading instructions.
>
> Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> ---
> v5: New to series, seperated from "Add prefixed instructions to
> instruction data type"
> ---
> arch/powerpc/xmon/xmon.c | 24 ++++++++++++++++++++----
> 1 file changed, 20 insertions(+), 4 deletions(-)
>
> diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
> index 5e3949322a6c..6f4cf01a58c1 100644
> --- a/arch/powerpc/xmon/xmon.c
> +++ b/arch/powerpc/xmon/xmon.c
> @@ -125,6 +125,7 @@ extern unsigned int bpt_table[NBPTS * BPT_WORDS];
> static int cmds(struct pt_regs *);
> static int mread(unsigned long, void *, int);
> static int mwrite(unsigned long, void *, int);
> +static int mread_instr(unsigned long, struct ppc_inst *);
> static int handle_fault(struct pt_regs *);
> static void byterev(unsigned char *, int);
> static void memex(void);
> @@ -899,7 +900,7 @@ static void insert_bpts(void)
> for (i = 0; i < NBPTS; ++i, ++bp) {
> if ((bp->enabled & (BP_TRAP|BP_CIABR)) == 0)
> continue;
> - if (mread(bp->address, &instr, 4) != 4) {
> + if (!mread_instr(bp->address, &instr)) {
Are these checks made based on whether `ppc_inst_len()` returns bool from
mread_instr() ?
-- Bala
> printf("Couldn't read instruction at %lx, "
> "disabling breakpoint there\n", bp->address);
> bp->enabled = 0;
> @@ -949,7 +950,7 @@ static void remove_bpts(void)
> for (i = 0; i < NBPTS; ++i, ++bp) {
> if ((bp->enabled & (BP_TRAP|BP_CIABR)) != BP_TRAP)
> continue;
> - if (mread(bp->address, &instr, 4) == 4
> + if (mread_instr(bp->address, &instr)
> && ppc_inst_equal(instr, ppc_inst(bpinstr))
> && patch_instruction(
> (struct ppc_inst *)bp->address, ppc_inst_read(bp-
> >instr)) != 0)
> @@ -1165,7 +1166,7 @@ static int do_step(struct pt_regs *regs)
> force_enable_xmon();
> /* check we are in 64-bit kernel mode, translation enabled */
> if ((regs->msr & (MSR_64BIT|MSR_PR|MSR_IR)) == (MSR_64BIT|MSR_IR)) {
> - if (mread(regs->nip, &instr, 4) == 4) {
> + if (mread_instr(regs->nip, &instr)) {
> stepped = emulate_step(regs, instr);
> if (stepped < 0) {
> printf("Couldn't single-step %s instruction\n",
> @@ -1332,7 +1333,7 @@ static long check_bp_loc(unsigned long addr)
> printf("Breakpoints may only be placed at kernel addresses\n");
> return 0;
> }
> - if (!mread(addr, &instr, sizeof(instr))) {
> + if (!mread_instr(addr, &instr)) {
> printf("Can't read instruction at address %lx\n", addr);
> return 0;
> }
> @@ -2125,6 +2126,21 @@ mwrite(unsigned long adrs, void *buf, int size)
> return n;
> }
>
> +static int
> +mread_instr(unsigned long adrs, struct ppc_inst *instr)
> +{
> + if (setjmp(bus_error_jmp) == 0) {
> + catch_memory_errors = 1;
> + sync();
> + *instr = ppc_inst_read((struct ppc_inst *)adrs);
> + sync();
> + /* wait a little while to see if we get a machine check */
> + __delay(200);
> + }
> + catch_memory_errors = 0;
> + return ppc_inst_len(*instr);
> +}
> +
> static int fault_type;
> static int fault_except;
> static char *fault_chars[] = { "--", "**", "##" };
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 09/21] powerpc: Use a datatype for instructions
2020-04-07 10:30 ` Balamuruhan S
@ 2020-04-08 2:11 ` Jordan Niethe
0 siblings, 0 replies; 71+ messages in thread
From: Jordan Niethe @ 2020-04-08 2:11 UTC (permalink / raw)
To: Balamuruhan S
Cc: Alistair Popple, linuxppc-dev, Nicholas Piggin, Daniel Axtens
On Tue, Apr 7, 2020 at 8:30 PM Balamuruhan S <bala24@linux.ibm.com> wrote:
>
> On Mon, 2020-04-06 at 18:09 +1000, Jordan Niethe wrote:
> > Currently unsigned ints are used to represent instructions on powerpc.
> > This has worked well as instructions have always been 4 byte words.
> > However, a future ISA version will introduce some changes to
> > instructions that mean this scheme will no longer work as well. This
> > change is Prefixed Instructions. A prefixed instruction is made up of a
> > word prefix followed by a word suffix to make an 8 byte double word
> > instruction. No matter the endianess of the system the prefix always
> > comes first. Prefixed instructions are only planned for powerpc64.
> >
> > Introduce a ppc_inst type to represent both prefixed and word
> > instructions on powerpc64 while keeping it possible to exclusively have
> > word instructions on powerpc32, A latter patch will expand the type to
> > include prefixed instructions but for now just typedef it to a u32.
> >
> > Later patches will introduce helper functions and macros for
> > manipulating the instructions so that powerpc64 and powerpc32 might
> > maintain separate type definitions.
> >
> > Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> > ---
> > v4: New to series
> > v5: Add to epapr_paravirt.c, kgdb.c
> > ---
> > arch/powerpc/include/asm/code-patching.h | 32 ++++-----
> > arch/powerpc/include/asm/inst.h | 20 +++---
> > arch/powerpc/include/asm/sstep.h | 5 +-
> > arch/powerpc/include/asm/uprobes.h | 5 +-
> > arch/powerpc/kernel/align.c | 4 +-
> > arch/powerpc/kernel/epapr_paravirt.c | 4 +-
> > arch/powerpc/kernel/hw_breakpoint.c | 4 +-
> > arch/powerpc/kernel/jump_label.c | 2 +-
> > arch/powerpc/kernel/kgdb.c | 4 +-
> > arch/powerpc/kernel/kprobes.c | 8 +--
> > arch/powerpc/kernel/mce_power.c | 5 +-
> > arch/powerpc/kernel/optprobes.c | 40 ++++++------
> > arch/powerpc/kernel/setup_32.c | 2 +-
> > arch/powerpc/kernel/trace/ftrace.c | 83 ++++++++++++------------
> > arch/powerpc/kernel/vecemu.c | 5 +-
> > arch/powerpc/lib/code-patching.c | 69 ++++++++++----------
> > arch/powerpc/lib/feature-fixups.c | 48 +++++++-------
> > arch/powerpc/lib/sstep.c | 4 +-
> > arch/powerpc/lib/test_emulate_step.c | 9 +--
> > arch/powerpc/perf/core-book3s.c | 4 +-
> > arch/powerpc/xmon/xmon.c | 24 +++----
> > 21 files changed, 196 insertions(+), 185 deletions(-)
> >
> > diff --git a/arch/powerpc/include/asm/code-patching.h
> > b/arch/powerpc/include/asm/code-patching.h
> > index 48e021957ee5..eacc9102c251 100644
> > --- a/arch/powerpc/include/asm/code-patching.h
> > +++ b/arch/powerpc/include/asm/code-patching.h
> > @@ -23,33 +23,33 @@
> > #define BRANCH_ABSOLUTE 0x2
> >
> > bool is_offset_in_branch_range(long offset);
> > -int create_branch(unsigned int *instr, const unsigned int *addr,
> > +int create_branch(struct ppc_inst *instr, const struct ppc_inst *addr,
> > unsigned long target, int flags);
> > -int create_cond_branch(unsigned int *instr, const unsigned int *addr,
> > +int create_cond_branch(struct ppc_inst *instr, const struct ppc_inst *addr,
> > unsigned long target, int flags);
> > -int patch_branch(unsigned int *addr, unsigned long target, int flags);
> > -int patch_instruction(unsigned int *addr, unsigned int instr);
> > -int raw_patch_instruction(unsigned int *addr, unsigned int instr);
> > +int patch_branch(struct ppc_inst *addr, unsigned long target, int flags);
> > +int patch_instruction(struct ppc_inst *addr, struct ppc_inst instr);
> > +int raw_patch_instruction(struct ppc_inst *addr, struct ppc_inst instr);
> >
> > static inline unsigned long patch_site_addr(s32 *site)
> > {
> > return (unsigned long)site + *site;
> > }
> >
> > -static inline int patch_instruction_site(s32 *site, unsigned int instr)
> > +static inline int patch_instruction_site(s32 *site, struct ppc_inst instr)
> > {
> > - return patch_instruction((unsigned int *)patch_site_addr(site), instr);
> > + return patch_instruction((struct ppc_inst *)patch_site_addr(site),
> > instr);
> > }
> >
> > static inline int patch_branch_site(s32 *site, unsigned long target, int
> > flags)
> > {
> > - return patch_branch((unsigned int *)patch_site_addr(site), target,
> > flags);
> > + return patch_branch((struct ppc_inst *)patch_site_addr(site), target,
> > flags);
> > }
> >
> > static inline int modify_instruction(unsigned int *addr, unsigned int clr,
> > unsigned int set)
> > {
> > - return patch_instruction(addr, ppc_inst((*addr & ~clr) | set));
> > + return patch_instruction((struct ppc_inst *)addr, ppc_inst((*addr &
> > ~clr) | set));
> > }
> >
> > static inline int modify_instruction_site(s32 *site, unsigned int clr,
> > unsigned int set)
> > @@ -57,13 +57,13 @@ static inline int modify_instruction_site(s32 *site,
> > unsigned int clr, unsigned
> > return modify_instruction((unsigned int *)patch_site_addr(site), clr,
> > set);
> > }
> >
> > -int instr_is_relative_branch(unsigned int instr);
> > -int instr_is_relative_link_branch(unsigned int instr);
> > -int instr_is_branch_to_addr(const unsigned int *instr, unsigned long addr);
> > -unsigned long branch_target(const unsigned int *instr);
> > -int translate_branch(unsigned int *instr, const unsigned int *dest,
> > - const unsigned int *src);
> > -extern bool is_conditional_branch(unsigned int instr);
> > +int instr_is_relative_branch(struct ppc_inst instr);
> > +int instr_is_relative_link_branch(struct ppc_inst instr);
> > +int instr_is_branch_to_addr(const struct ppc_inst *instr, unsigned long
> > addr);
> > +unsigned long branch_target(const struct ppc_inst *instr);
> > +int translate_branch(struct ppc_inst *instr, const struct ppc_inst *dest,
> > + const struct ppc_inst *src);
> > +extern bool is_conditional_branch(struct ppc_inst instr);
> > #ifdef CONFIG_PPC_BOOK3E_64
> > void __patch_exception(int exc, unsigned long addr);
> > #define patch_exception(exc, name) do { \
> > diff --git a/arch/powerpc/include/asm/inst.h
> > b/arch/powerpc/include/asm/inst.h
> > index 54ee46b0a7c9..a71decf5f871 100644
> > --- a/arch/powerpc/include/asm/inst.h
> > +++ b/arch/powerpc/include/asm/inst.h
> > @@ -6,26 +6,30 @@
> > * Instruction data type for POWER
> > */
> >
> > -#define ppc_inst(x) (x)
> > +struct ppc_inst {
> > + u32 val;
> > +} __packed;
> >
> > -static inline u32 ppc_inst_val(u32 x)
> > +#define ppc_inst(x) ((struct ppc_inst){ .val = x })
> > +
> > +static inline u32 ppc_inst_val(struct ppc_inst x)
> > {
> > - return x;
> > + return x.val;
> > }
> >
> > -static inline int ppc_inst_opcode(u32 x)
> > +static inline int ppc_inst_opcode(struct ppc_inst x)
> > {
> > - return x >> 26;
> > + return x.val >> 26;
> > }
> >
> > -static inline u32 ppc_inst_swab(u32 x)
> > +static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
> > {
> > return ppc_inst(swab32(ppc_inst_val(x)));
> > }
> >
> > -static inline bool ppc_inst_equal(u32 x, u32 y)
> > +static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
> > {
> > - return x == y;
> > + return !memcmp(&x, &y, sizeof(struct ppc_inst));
> > }
> >
> > #endif /* _ASM_INST_H */
> > diff --git a/arch/powerpc/include/asm/sstep.h
> > b/arch/powerpc/include/asm/sstep.h
> > index 26d729562fe2..c3ce903ac488 100644
> > --- a/arch/powerpc/include/asm/sstep.h
> > +++ b/arch/powerpc/include/asm/sstep.h
> > @@ -2,6 +2,7 @@
> > /*
> > * Copyright (C) 2004 Paul Mackerras <paulus@au.ibm.com>, IBM
> > */
> > +#include <asm/inst.h>
> >
> > struct pt_regs;
> >
> > @@ -132,7 +133,7 @@ union vsx_reg {
> > * otherwise.
> > */
> > extern int analyse_instr(struct instruction_op *op, const struct pt_regs
> > *regs,
> > - unsigned int instr);
> > + struct ppc_inst instr);
> >
> > /*
> > * Emulate an instruction that can be executed just by updating
> > @@ -149,7 +150,7 @@ void emulate_update_regs(struct pt_regs *reg, struct
> > instruction_op *op);
> > * 0 if it could not be emulated, or -1 for an instruction that
> > * should not be emulated (rfid, mtmsrd clearing MSR_RI, etc.).
> > */
> > -extern int emulate_step(struct pt_regs *regs, unsigned int instr);
> > +extern int emulate_step(struct pt_regs *regs, struct ppc_inst instr);
> >
> > /*
> > * Emulate a load or store instruction by reading/writing the
> > diff --git a/arch/powerpc/include/asm/uprobes.h
> > b/arch/powerpc/include/asm/uprobes.h
> > index 2bbdf27d09b5..7e3b329ba2d3 100644
> > --- a/arch/powerpc/include/asm/uprobes.h
> > +++ b/arch/powerpc/include/asm/uprobes.h
> > @@ -11,6 +11,7 @@
> >
> > #include <linux/notifier.h>
> > #include <asm/probes.h>
> > +#include <asm/inst.h>
> >
> > typedef ppc_opcode_t uprobe_opcode_t;
> >
> > @@ -23,8 +24,8 @@ typedef ppc_opcode_t uprobe_opcode_t;
> >
> > struct arch_uprobe {
> > union {
> > - u32 insn;
> > - u32 ixol;
> > + struct ppc_inst insn;
> > + struct ppc_inst ixol;
> > };
> > };
> >
> > diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
> > index 46870cf6a6dc..66a6d1de7799 100644
> > --- a/arch/powerpc/kernel/align.c
> > +++ b/arch/powerpc/kernel/align.c
> > @@ -294,7 +294,7 @@ static int emulate_spe(struct pt_regs *regs, unsigned int
> > reg,
> >
> > int fix_alignment(struct pt_regs *regs)
> > {
> > - unsigned int instr;
> > + struct ppc_inst instr;
> > struct instruction_op op;
> > int r, type;
> >
> > @@ -304,7 +304,7 @@ int fix_alignment(struct pt_regs *regs)
> > */
> > CHECK_FULL_REGS(regs);
> >
> > - if (unlikely(__get_user(instr, (unsigned int __user *)regs->nip)))
> > + if (unlikely(__get_user(instr.val, (unsigned int __user *)regs->nip)))
>
>
> don't we have to use the helper `ppc_inst_val()` here to retrieve instr.val ?
__get_user() is loading into instr.val, so using ppc_inst_val() would not work.
>
> I see couple of other places we directly retrieve as instr.val.
> if we need to change it, then all of them should go to patch 6,
Those other places also are for the __get_user() macros I think.
> [PATCH v5 06/21] powerpc: Use an accessor for instructions
>
>
> > return -EFAULT;
> > if ((regs->msr & MSR_LE) != (MSR_KERNEL & MSR_LE)) {
> > /* We don't handle PPC little-endian any more... */
> > diff --git a/arch/powerpc/kernel/epapr_paravirt.c
> > b/arch/powerpc/kernel/epapr_paravirt.c
> > index c53e863fb484..c42aa3926632 100644
> > --- a/arch/powerpc/kernel/epapr_paravirt.c
> > +++ b/arch/powerpc/kernel/epapr_paravirt.c
> > @@ -38,9 +38,9 @@ static int __init early_init_dt_scan_epapr(unsigned long
> > node,
> >
> > for (i = 0; i < (len / 4); i++) {
> > u32 inst = be32_to_cpu(insts[i]);
> > - patch_instruction(epapr_hypercall_start + i, ppc_inst(inst));
> > + patch_instruction((struct ppc_inst *)(epapr_hypercall_start +
> > i), ppc_inst(inst));
> > #if !defined(CONFIG_64BIT) || defined(CONFIG_PPC_BOOK3E_64)
> > - patch_instruction(epapr_ev_idle_start + i, ppc_inst(inst));
> > + patch_instruction((struct ppc_inst *)(epapr_ev_idle_start + i),
> > ppc_inst(inst));
> > #endif
> > }
> >
> > diff --git a/arch/powerpc/kernel/hw_breakpoint.c
> > b/arch/powerpc/kernel/hw_breakpoint.c
> > index 79f51f182a83..542f65ccf68b 100644
> > --- a/arch/powerpc/kernel/hw_breakpoint.c
> > +++ b/arch/powerpc/kernel/hw_breakpoint.c
> > @@ -244,12 +244,12 @@ dar_range_overlaps(unsigned long dar, int size, struct
> > arch_hw_breakpoint *info)
> > static bool stepping_handler(struct pt_regs *regs, struct perf_event *bp,
> > struct arch_hw_breakpoint *info)
> > {
> > - unsigned int instr = ppc_inst(0);
> > + struct ppc_inst instr = ppc_inst(0);
> > int ret, type, size;
> > struct instruction_op op;
> > unsigned long addr = info->address;
> >
> > - if (__get_user_inatomic(instr, (unsigned int *)regs->nip))
> > + if (__get_user_inatomic(instr.val, (unsigned int *)regs->nip))
>
>
> [...] reference to above
>
>
> > goto fail;
> >
> > ret = analyse_instr(&op, regs, instr);
> > diff --git a/arch/powerpc/kernel/jump_label.c
> > b/arch/powerpc/kernel/jump_label.c
> > index daa4afce7ec8..144858027fa3 100644
> > --- a/arch/powerpc/kernel/jump_label.c
> > +++ b/arch/powerpc/kernel/jump_label.c
> > @@ -11,7 +11,7 @@
> > void arch_jump_label_transform(struct jump_entry *entry,
> > enum jump_label_type type)
> > {
> > - u32 *addr = (u32 *)(unsigned long)entry->code;
> > + struct ppc_inst *addr = (struct ppc_inst *)(unsigned long)entry->code;
> >
> > if (type == JUMP_LABEL_JMP)
> > patch_branch(addr, entry->target, 0);
> > diff --git a/arch/powerpc/kernel/kgdb.c b/arch/powerpc/kernel/kgdb.c
> > index a6b38a19133f..652b2852bea3 100644
> > --- a/arch/powerpc/kernel/kgdb.c
> > +++ b/arch/powerpc/kernel/kgdb.c
> > @@ -419,7 +419,7 @@ int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
> > {
> > int err;
> > unsigned int instr;
> > - unsigned int *addr = (unsigned int *)bpt->bpt_addr;
> > + struct ppc_inst *addr = (struct ppc_inst *)bpt->bpt_addr;
> >
> > err = probe_kernel_address(addr, instr);
> > if (err)
> > @@ -438,7 +438,7 @@ int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
> > {
> > int err;
> > unsigned int instr = *(unsigned int *)bpt->saved_instr;
> > - unsigned int *addr = (unsigned int *)bpt->bpt_addr;
> > + struct ppc_inst *addr = (struct ppc_inst *)bpt->bpt_addr;
> >
> > err = patch_instruction(addr, ppc_inst(instr));
> > if (err)
> > diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
> > index 8420b1944164..9ed996cb0589 100644
> > --- a/arch/powerpc/kernel/kprobes.c
> > +++ b/arch/powerpc/kernel/kprobes.c
> > @@ -106,7 +106,7 @@ kprobe_opcode_t *kprobe_lookup_name(const char *name,
> > unsigned int offset)
> > int arch_prepare_kprobe(struct kprobe *p)
> > {
> > int ret = 0;
> > - kprobe_opcode_t insn = *p->addr;
> > + struct ppc_inst insn = *(struct ppc_inst *)p->addr;
> >
> > if ((unsigned long)p->addr & 0x03) {
> > printk("Attempt to register kprobe at an unaligned address\n");
> > @@ -139,13 +139,13 @@ NOKPROBE_SYMBOL(arch_prepare_kprobe);
> >
> > void arch_arm_kprobe(struct kprobe *p)
> > {
> > - patch_instruction(p->addr, ppc_inst(BREAKPOINT_INSTRUCTION));
> > + patch_instruction((struct ppc_inst *)p->addr,
> > ppc_inst(BREAKPOINT_INSTRUCTION));
> > }
> > NOKPROBE_SYMBOL(arch_arm_kprobe);
> >
> > void arch_disarm_kprobe(struct kprobe *p)
> > {
> > - patch_instruction(p->addr, ppc_inst(p->opcode));
> > + patch_instruction((struct ppc_inst *)p->addr, ppc_inst(p->opcode));
> > }
> > NOKPROBE_SYMBOL(arch_disarm_kprobe);
> >
> > @@ -217,7 +217,7 @@ NOKPROBE_SYMBOL(arch_prepare_kretprobe);
> > static int try_to_emulate(struct kprobe *p, struct pt_regs *regs)
> > {
> > int ret;
> > - unsigned int insn = *p->ainsn.insn;
> > + struct ppc_inst insn = *(struct ppc_inst *)p->ainsn.insn;
> >
> > /* regs->nip is also adjusted if emulate_step returns 1 */
> > ret = emulate_step(regs, insn);
> > diff --git a/arch/powerpc/kernel/mce_power.c
> > b/arch/powerpc/kernel/mce_power.c
> > index 1cbf7f1a4e3d..7118b46a6543 100644
> > --- a/arch/powerpc/kernel/mce_power.c
> > +++ b/arch/powerpc/kernel/mce_power.c
> > @@ -20,6 +20,7 @@
> > #include <asm/sstep.h>
> > #include <asm/exception-64s.h>
> > #include <asm/extable.h>
> > +#include <asm/inst.h>
> >
> > /*
> > * Convert an address related to an mm to a PFN. NOTE: we are in real
> > @@ -365,7 +366,7 @@ static int mce_find_instr_ea_and_phys(struct pt_regs
> > *regs, uint64_t *addr,
> > * in real-mode is tricky and can lead to recursive
> > * faults
> > */
> > - int instr;
> > + struct ppc_inst instr;
> > unsigned long pfn, instr_addr;
> > struct instruction_op op;
> > struct pt_regs tmp = *regs;
> > @@ -373,7 +374,7 @@ static int mce_find_instr_ea_and_phys(struct pt_regs
> > *regs, uint64_t *addr,
> > pfn = addr_to_pfn(regs, regs->nip);
> > if (pfn != ULONG_MAX) {
> > instr_addr = (pfn << PAGE_SHIFT) + (regs->nip & ~PAGE_MASK);
> > - instr = *(unsigned int *)(instr_addr);
> > + instr = *(struct ppc_inst *)(instr_addr);
> > if (!analyse_instr(&op, &tmp, instr)) {
> > pfn = addr_to_pfn(regs, op.ea);
> > *addr = op.ea;
> > diff --git a/arch/powerpc/kernel/optprobes.c
> > b/arch/powerpc/kernel/optprobes.c
> > index 3b33ebf18859..b61bbcee84f4 100644
> > --- a/arch/powerpc/kernel/optprobes.c
> > +++ b/arch/powerpc/kernel/optprobes.c
> > @@ -100,8 +100,8 @@ static unsigned long can_optimize(struct kprobe *p)
> > * Ensure that the instruction is not a conditional branch,
> > * and that can be emulated.
> > */
> > - if (!is_conditional_branch(*p->ainsn.insn) &&
> > - analyse_instr(&op, ®s, *p->ainsn.insn) == 1) {
> > + if (!is_conditional_branch(*(struct ppc_inst *)p->ainsn.insn) &&
> > + analyse_instr(&op, ®s, *(struct ppc_inst *)p-
> > >ainsn.insn) == 1) {
> > emulate_update_regs(®s, &op);
> > nip = regs.nip;
> > }
> > @@ -148,12 +148,12 @@ void arch_remove_optimized_kprobe(struct
> > optimized_kprobe *op)
> > void patch_imm32_load_insns(unsigned int val, kprobe_opcode_t *addr)
> > {
> > /* addis r4,0,(insn)@h */
> > - patch_instruction(addr, ppc_inst(PPC_INST_ADDIS | ___PPC_RT(4) |
> > + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ADDIS |
> > ___PPC_RT(4) |
> > ((val >> 16) & 0xffff)));
> > addr++;
> >
> > /* ori r4,r4,(insn)@l */
> > - patch_instruction(addr, ppc_inst(PPC_INST_ORI | ___PPC_RA(4) |
> > + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI |
> > ___PPC_RA(4) |
> > ___PPC_RS(4) | (val & 0xffff)));
> > }
> >
> > @@ -164,34 +164,34 @@ void patch_imm32_load_insns(unsigned int val,
> > kprobe_opcode_t *addr)
> > void patch_imm64_load_insns(unsigned long val, kprobe_opcode_t *addr)
> > {
> > /* lis r3,(op)@highest */
> > - patch_instruction(addr, ppc_inst(PPC_INST_ADDIS | ___PPC_RT(3) |
> > + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ADDIS |
> > ___PPC_RT(3) |
> > ((val >> 48) & 0xffff)));
> > addr++;
> >
> > /* ori r3,r3,(op)@higher */
> > - patch_instruction(addr, ppc_inst(PPC_INST_ORI | ___PPC_RA(3) |
> > + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI |
> > ___PPC_RA(3) |
> > ___PPC_RS(3) | ((val >> 32) & 0xffff)));
> > addr++;
> >
> > /* rldicr r3,r3,32,31 */
> > - patch_instruction(addr, ppc_inst(PPC_INST_RLDICR | ___PPC_RA(3) |
> > + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_RLDICR |
> > ___PPC_RA(3) |
> > ___PPC_RS(3) | __PPC_SH64(32) | __PPC_ME64(31)));
> > addr++;
> >
> > /* oris r3,r3,(op)@h */
> > - patch_instruction(addr, ppc_inst(PPC_INST_ORIS | ___PPC_RA(3) |
> > + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORIS |
> > ___PPC_RA(3) |
> > ___PPC_RS(3) | ((val >> 16) & 0xffff)));
> > addr++;
> >
> > /* ori r3,r3,(op)@l */
> > - patch_instruction(addr, ppc_inst(PPC_INST_ORI | ___PPC_RA(3) |
> > + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI |
> > ___PPC_RA(3) |
> > ___PPC_RS(3) | (val & 0xffff)));
> > }
> >
> > int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe
> > *p)
> > {
> > - kprobe_opcode_t *buff, branch_op_callback, branch_emulate_step;
> > - kprobe_opcode_t *op_callback_addr, *emulate_step_addr;
> > + struct ppc_inst branch_op_callback, branch_emulate_step;
> > + kprobe_opcode_t *op_callback_addr, *emulate_step_addr, *buff;
> > long b_offset;
> > unsigned long nip, size;
> > int rc, i;
> > @@ -231,7 +231,7 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe
> > *op, struct kprobe *p)
> > size = (TMPL_END_IDX * sizeof(kprobe_opcode_t)) / sizeof(int);
> > pr_devel("Copying template to %p, size %lu\n", buff, size);
> > for (i = 0; i < size; i++) {
> > - rc = patch_instruction(buff + i,
> > ppc_inst(*(optprobe_template_entry + i)));
> > + rc = patch_instruction((struct ppc_inst *)(buff + i),
> > ppc_inst(*(optprobe_template_entry + i)));
> > if (rc < 0)
> > goto error;
> > }
> > @@ -253,20 +253,20 @@ int arch_prepare_optimized_kprobe(struct
> > optimized_kprobe *op, struct kprobe *p)
> > }
> >
> > rc = create_branch(&branch_op_callback,
> > - (unsigned int *)buff + TMPL_CALL_HDLR_IDX,
> > + (struct ppc_inst *)(buff + TMPL_CALL_HDLR_IDX),
> > (unsigned long)op_callback_addr,
> > BRANCH_SET_LINK);
> >
> > rc |= create_branch(&branch_emulate_step,
> > - (unsigned int *)buff + TMPL_EMULATE_IDX,
> > + (struct ppc_inst *)(buff + TMPL_EMULATE_IDX),
> > (unsigned long)emulate_step_addr,
> > BRANCH_SET_LINK);
> >
> > if (rc)
> > goto error;
> >
> > - patch_instruction(buff + TMPL_CALL_HDLR_IDX, branch_op_callback);
> > - patch_instruction(buff + TMPL_EMULATE_IDX, branch_emulate_step);
> > + patch_instruction((struct ppc_inst *)(buff + TMPL_CALL_HDLR_IDX),
> > branch_op_callback);
> > + patch_instruction((struct ppc_inst *)(buff + TMPL_EMULATE_IDX),
> > branch_emulate_step);
> >
> > /*
> > * 3. load instruction to be emulated into relevant register, and
> > @@ -276,7 +276,7 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe
> > *op, struct kprobe *p)
> > /*
> > * 4. branch back from trampoline
> > */
> > - patch_branch(buff + TMPL_RET_IDX, (unsigned long)nip, 0);
> > + patch_branch((void *)(buff + TMPL_RET_IDX), (unsigned long)nip, 0);
>
>
> why do we cast it differently here ?
That is a mistake.
>
>
> >
> > flush_icache_range((unsigned long)buff,
> > (unsigned long)(&buff[TMPL_END_IDX]));
> > @@ -308,7 +308,7 @@ int arch_check_optimized_kprobe(struct optimized_kprobe
> > *op)
> >
> > void arch_optimize_kprobes(struct list_head *oplist)
> > {
> > - unsigned int instr;
> > + struct ppc_inst instr;
> > struct optimized_kprobe *op;
> > struct optimized_kprobe *tmp;
> >
> > @@ -320,9 +320,9 @@ void arch_optimize_kprobes(struct list_head *oplist)
> > memcpy(op->optinsn.copied_insn, op->kp.addr,
> > RELATIVEJUMP_SIZE);
> > create_branch(&instr,
> > - (unsigned int *)op->kp.addr,
> > + (struct ppc_inst *)op->kp.addr,
> > (unsigned long)op->optinsn.insn, 0);
> > - patch_instruction(op->kp.addr, instr);
> > + patch_instruction((struct ppc_inst *)op->kp.addr, instr);
> > list_del_init(&op->list);
> > }
> > }
> > diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
> > index c1bdd462c5c0..989809e58234 100644
> > --- a/arch/powerpc/kernel/setup_32.c
> > +++ b/arch/powerpc/kernel/setup_32.c
> > @@ -76,7 +76,7 @@ EXPORT_SYMBOL(DMA_MODE_WRITE);
> > notrace void __init machine_init(u64 dt_ptr)
> > {
> > unsigned int *addr = (unsigned int
> > *)patch_site_addr(&patch__memset_nocache);
> > - unsigned long insn;
> > + struct ppc_inst insn;
> >
> > /* Configure static keys first, now that we're relocated. */
> > setup_feature_keys();
> > diff --git a/arch/powerpc/kernel/trace/ftrace.c
> > b/arch/powerpc/kernel/trace/ftrace.c
> > index 784b5746cc55..442c62fb68ff 100644
> > --- a/arch/powerpc/kernel/trace/ftrace.c
> > +++ b/arch/powerpc/kernel/trace/ftrace.c
> > @@ -41,23 +41,23 @@
> > #define NUM_FTRACE_TRAMPS 8
> > static unsigned long ftrace_tramps[NUM_FTRACE_TRAMPS];
> >
> > -static unsigned int
> > +static struct ppc_inst
> > ftrace_call_replace(unsigned long ip, unsigned long addr, int link)
> > {
> > - unsigned int op;
> > + struct ppc_inst op;
> >
> > addr = ppc_function_entry((void *)addr);
> >
> > /* if (link) set op to 'bl' else 'b' */
> > - create_branch(&op, (unsigned int *)ip, addr, link ? 1 : 0);
> > + create_branch(&op, (struct ppc_inst *)ip, addr, link ? 1 : 0);
> >
> > return op;
> > }
> >
> > static int
> > -ftrace_modify_code(unsigned long ip, unsigned int old, unsigned int new)
> > +ftrace_modify_code(unsigned long ip, struct ppc_inst old, struct ppc_inst
> > new)
> > {
> > - unsigned int replaced;
> > + struct ppc_inst replaced;
> >
> > /*
> > * Note:
> > @@ -79,7 +79,7 @@ ftrace_modify_code(unsigned long ip, unsigned int old,
> > unsigned int new)
> > }
> >
> > /* replace the text with the new text */
> > - if (patch_instruction((unsigned int *)ip, new))
> > + if (patch_instruction((struct ppc_inst *)ip, new))
> > return -EPERM;
> >
> > return 0;
> > @@ -90,24 +90,24 @@ ftrace_modify_code(unsigned long ip, unsigned int old,
> > unsigned int new)
> > */
> > static int test_24bit_addr(unsigned long ip, unsigned long addr)
> > {
> > - unsigned int op;
> > + struct ppc_inst op;
> > addr = ppc_function_entry((void *)addr);
> >
> > /* use the create_branch to verify that this offset can be branched */
> > - return create_branch(&op, (unsigned int *)ip, addr, 0) == 0;
> > + return create_branch(&op, (struct ppc_inst *)ip, addr, 0) == 0;
> > }
> >
> > -static int is_bl_op(unsigned int op)
> > +static int is_bl_op(struct ppc_inst op)
> > {
> > return (ppc_inst_val(op) & 0xfc000003) == 0x48000001;
> > }
> >
> > -static int is_b_op(unsigned int op)
> > +static int is_b_op(struct ppc_inst op)
> > {
> > return (ppc_inst_val(op) & 0xfc000003) == 0x48000000;
> > }
> >
> > -static unsigned long find_bl_target(unsigned long ip, unsigned int op)
> > +static unsigned long find_bl_target(unsigned long ip, struct ppc_inst op)
> > {
> > int offset;
> >
> > @@ -127,7 +127,7 @@ __ftrace_make_nop(struct module *mod,
> > {
> > unsigned long entry, ptr, tramp;
> > unsigned long ip = rec->ip;
> > - unsigned int op, pop;
> > + struct ppc_inst op, pop;
> >
> > /* read where this goes */
> > if (probe_kernel_read(&op, (void *)ip, sizeof(int))) {
> > @@ -207,7 +207,7 @@ __ftrace_make_nop(struct module *mod,
> > }
> > #endif /* CONFIG_MPROFILE_KERNEL */
> >
> > - if (patch_instruction((unsigned int *)ip, pop)) {
> > + if (patch_instruction((struct ppc_inst *)ip, pop)) {
> > pr_err("Patching NOP failed.\n");
> > return -EPERM;
> > }
> > @@ -220,7 +220,7 @@ static int
> > __ftrace_make_nop(struct module *mod,
> > struct dyn_ftrace *rec, unsigned long addr)
> > {
> > - unsigned int op;
> > + struct ppc_inst op;
> > unsigned int jmp[4];
> > unsigned long ip = rec->ip;
> > unsigned long tramp;
> > @@ -279,7 +279,7 @@ __ftrace_make_nop(struct module *mod,
> >
> > op = ppc_inst(PPC_INST_NOP);
> >
> > - if (patch_instruction((unsigned int *)ip, op))
> > + if (patch_instruction((struct ppc_inst *)ip, op))
> > return -EPERM;
> >
> > return 0;
> > @@ -290,7 +290,7 @@ __ftrace_make_nop(struct module *mod,
> > static unsigned long find_ftrace_tramp(unsigned long ip)
> > {
> > int i;
> > - unsigned int instr;
> > + struct ppc_inst instr;
> >
> > /*
> > * We have the compiler generated long_branch tramps at the end
> > @@ -327,9 +327,10 @@ static int add_ftrace_tramp(unsigned long tramp)
> > */
> > static int setup_mcount_compiler_tramp(unsigned long tramp)
> > {
> > - int i, op;
> > + int i;
> > + struct ppc_inst op;
> > unsigned long ptr;
> > - unsigned int instr;
> > + struct ppc_inst instr;
> > static unsigned long ftrace_plt_tramps[NUM_FTRACE_TRAMPS];
> >
> > /* Is this a known long jump tramp? */
> > @@ -378,7 +379,7 @@ static int setup_mcount_compiler_tramp(unsigned long
> > tramp)
> > return -1;
> > }
> >
> > - if (patch_branch((unsigned int *)tramp, ptr, 0)) {
> > + if (patch_branch((struct ppc_inst *)tramp, ptr, 0)) {
> > pr_debug("REL24 out of range!\n");
> > return -1;
> > }
> > @@ -394,7 +395,7 @@ static int setup_mcount_compiler_tramp(unsigned long
> > tramp)
> > static int __ftrace_make_nop_kernel(struct dyn_ftrace *rec, unsigned long
> > addr)
> > {
> > unsigned long tramp, ip = rec->ip;
> > - unsigned int op;
> > + struct ppc_inst op;
> >
> > /* Read where this goes */
> > if (probe_kernel_read(&op, (void *)ip, sizeof(int))) {
> > @@ -422,7 +423,7 @@ static int __ftrace_make_nop_kernel(struct dyn_ftrace
> > *rec, unsigned long addr)
> > }
> > }
> >
> > - if (patch_instruction((unsigned int *)ip, ppc_inst(PPC_INST_NOP))) {
> > + if (patch_instruction((struct ppc_inst *)ip, ppc_inst(PPC_INST_NOP))) {
> > pr_err("Patching NOP failed.\n");
> > return -EPERM;
> > }
> > @@ -434,7 +435,7 @@ int ftrace_make_nop(struct module *mod,
> > struct dyn_ftrace *rec, unsigned long addr)
> > {
> > unsigned long ip = rec->ip;
> > - unsigned int old, new;
> > + struct ppc_inst old, new;
> >
> > /*
> > * If the calling address is more that 24 bits away,
> > @@ -487,7 +488,7 @@ int ftrace_make_nop(struct module *mod,
> > */
> > #ifndef CONFIG_MPROFILE_KERNEL
> > static int
> > -expected_nop_sequence(void *ip, unsigned int op0, unsigned int op1)
> > +expected_nop_sequence(void *ip, struct ppc_inst op0, struct ppc_inst op1)
> > {
> > /*
> > * We expect to see:
> > @@ -504,7 +505,7 @@ expected_nop_sequence(void *ip, unsigned int op0,
> > unsigned int op1)
> > }
> > #else
> > static int
> > -expected_nop_sequence(void *ip, unsigned int op0, unsigned int op1)
> > +expected_nop_sequence(void *ip, struct ppc_inst op0, struct ppc_inst op1)
> > {
> > /* look for patched "NOP" on ppc64 with -mprofile-kernel */
> > if (!ppc_inst_equal(op0, ppc_inst(PPC_INST_NOP)))
> > @@ -516,8 +517,8 @@ expected_nop_sequence(void *ip, unsigned int op0,
> > unsigned int op1)
> > static int
> > __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
> > {
> > - unsigned int op[2];
> > - unsigned int instr;
> > + struct ppc_inst op[2];
> > + struct ppc_inst instr;
> > void *ip = (void *)rec->ip;
> > unsigned long entry, ptr, tramp;
> > struct module *mod = rec->arch.mod;
> > @@ -528,7 +529,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long
> > addr)
> >
> > if (!expected_nop_sequence(ip, op[0], op[1])) {
> > pr_err("Unexpected call sequence at %p: %x %x\n",
> > - ip, op[0], op[1]);
> > + ip, ppc_inst_val(op[0]), ppc_inst_val(op[1]));
>
>
> shouldn't this change be part of patch 6,
>
> [PATCH v5 06/21] powerpc: Use an accessor for instructions
Yes it should be.
>
>
> > return -EINVAL;
> > }
> >
> > @@ -582,7 +583,7 @@ static int
> > __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
> > {
> > int err;
> > - unsigned int op;
> > + struct ppc_inst op;
> > unsigned long ip = rec->ip;
> >
> > /* read where this goes */
> > @@ -602,7 +603,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long
> > addr)
> > }
> >
> > /* create the branch to the trampoline */
> > - err = create_branch(&op, (unsigned int *)ip,
> > + err = create_branch(&op, (struct ppc_inst *)ip,
> > rec->arch.mod->arch.tramp, BRANCH_SET_LINK);
> > if (!err) {
> > pr_err("REL24 out of range!\n");
> > @@ -621,7 +622,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long
> > addr)
> >
> > static int __ftrace_make_call_kernel(struct dyn_ftrace *rec, unsigned long
> > addr)
> > {
> > - unsigned int op;
> > + struct ppc_inst op;
> > void *ip = (void *)rec->ip;
> > unsigned long tramp, entry, ptr;
> >
> > @@ -669,7 +670,7 @@ static int __ftrace_make_call_kernel(struct dyn_ftrace
> > *rec, unsigned long addr)
> > int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
> > {
> > unsigned long ip = rec->ip;
> > - unsigned int old, new;
> > + struct ppc_inst old, new;
> >
> > /*
> > * If the calling address is more that 24 bits away,
> > @@ -708,7 +709,7 @@ static int
> > __ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
> > unsigned long addr)
> > {
> > - unsigned int op;
> > + struct ppc_inst op;
> > unsigned long ip = rec->ip;
> > unsigned long entry, ptr, tramp;
> > struct module *mod = rec->arch.mod;
> > @@ -756,7 +757,7 @@ __ftrace_modify_call(struct dyn_ftrace *rec, unsigned
> > long old_addr,
> > /* The new target may be within range */
> > if (test_24bit_addr(ip, addr)) {
> > /* within range */
> > - if (patch_branch((unsigned int *)ip, addr, BRANCH_SET_LINK)) {
> > + if (patch_branch((struct ppc_inst *)ip, addr, BRANCH_SET_LINK))
> > {
> > pr_err("REL24 out of range!\n");
> > return -EINVAL;
> > }
> > @@ -784,12 +785,12 @@ __ftrace_modify_call(struct dyn_ftrace *rec, unsigned
> > long old_addr,
> > }
> >
> > /* Ensure branch is within 24 bits */
> > - if (create_branch(&op, (unsigned int *)ip, tramp, BRANCH_SET_LINK)) {
> > + if (create_branch(&op, (struct ppc_inst *)ip, tramp, BRANCH_SET_LINK))
> > {
> > pr_err("Branch out of range\n");
> > return -EINVAL;
> > }
> >
> > - if (patch_branch((unsigned int *)ip, tramp, BRANCH_SET_LINK)) {
> > + if (patch_branch((struct ppc_inst *)ip, tramp, BRANCH_SET_LINK)) {
> > pr_err("REL24 out of range!\n");
> > return -EINVAL;
> > }
> > @@ -802,7 +803,7 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned
> > long old_addr,
> > unsigned long addr)
> > {
> > unsigned long ip = rec->ip;
> > - unsigned int old, new;
> > + struct ppc_inst old, new;
> >
> > /*
> > * If the calling address is more that 24 bits away,
> > @@ -842,10 +843,10 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned
> > long old_addr,
> > int ftrace_update_ftrace_func(ftrace_func_t func)
> > {
> > unsigned long ip = (unsigned long)(&ftrace_call);
> > - unsigned int old, new;
> > + struct ppc_inst old, new;
> > int ret;
> >
> > - old = *(unsigned int *)&ftrace_call;
> > + old = *(struct ppc_inst *)&ftrace_call;
> > new = ftrace_call_replace(ip, (unsigned long)func, 1);
> > ret = ftrace_modify_code(ip, old, new);
> >
> > @@ -853,7 +854,7 @@ int ftrace_update_ftrace_func(ftrace_func_t func)
> > /* Also update the regs callback function */
> > if (!ret) {
> > ip = (unsigned long)(&ftrace_regs_call);
> > - old = *(unsigned int *)&ftrace_regs_call;
> > + old = *(struct ppc_inst *)&ftrace_regs_call;
> > new = ftrace_call_replace(ip, (unsigned long)func, 1);
> > ret = ftrace_modify_code(ip, old, new);
> > }
> > @@ -927,7 +928,7 @@ int ftrace_enable_ftrace_graph_caller(void)
> > unsigned long ip = (unsigned long)(&ftrace_graph_call);
> > unsigned long addr = (unsigned long)(&ftrace_graph_caller);
> > unsigned long stub = (unsigned long)(&ftrace_graph_stub);
> > - unsigned int old, new;
> > + struct ppc_inst old, new;
> >
> > old = ftrace_call_replace(ip, stub, 0);
> > new = ftrace_call_replace(ip, addr, 0);
> > @@ -940,7 +941,7 @@ int ftrace_disable_ftrace_graph_caller(void)
> > unsigned long ip = (unsigned long)(&ftrace_graph_call);
> > unsigned long addr = (unsigned long)(&ftrace_graph_caller);
> > unsigned long stub = (unsigned long)(&ftrace_graph_stub);
> > - unsigned int old, new;
> > + struct ppc_inst old, new;
> >
> > old = ftrace_call_replace(ip, addr, 0);
> > new = ftrace_call_replace(ip, stub, 0);
> > diff --git a/arch/powerpc/kernel/vecemu.c b/arch/powerpc/kernel/vecemu.c
> > index c8d21e812d8c..bbf536e10902 100644
> > --- a/arch/powerpc/kernel/vecemu.c
> > +++ b/arch/powerpc/kernel/vecemu.c
> > @@ -261,11 +261,12 @@ static unsigned int rfin(unsigned int x)
> >
> > int emulate_altivec(struct pt_regs *regs)
> > {
> > - unsigned int instr, i, word;
> > + struct ppc_inst instr;
> > + unsigned int i, word;
> > unsigned int va, vb, vc, vd;
> > vector128 *vrs;
> >
> > - if (get_user(instr, (unsigned int __user *) regs->nip))
> > + if (get_user(instr.val, (unsigned int __user *) regs->nip))
>
>
> [...] reference to above for using helper.
>
>
> > return -EFAULT;
> >
> > word = ppc_inst_val(instr);
> > diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-
> > patching.c
> > index 33654c6334a9..91be4a0b51cb 100644
> > --- a/arch/powerpc/lib/code-patching.c
> > +++ b/arch/powerpc/lib/code-patching.c
> > @@ -19,12 +19,12 @@
> > #include <asm/setup.h>
> > #include <asm/inst.h>
> >
> > -static int __patch_instruction(unsigned int *exec_addr, unsigned int instr,
> > - unsigned int *patch_addr)
> > +static int __patch_instruction(struct ppc_inst *exec_addr, struct ppc_inst
> > instr,
> > + struct ppc_inst *patch_addr)
> > {
> > int err = 0;
> >
> > - __put_user_asm(instr, patch_addr, err, "stw");
> > + __put_user_asm(ppc_inst_val(instr), patch_addr, err, "stw");
> > if (err)
> > return err;
> >
> > @@ -34,7 +34,7 @@ static int __patch_instruction(unsigned int *exec_addr,
> > unsigned int instr,
> > return 0;
> > }
> >
> > -int raw_patch_instruction(unsigned int *addr, unsigned int instr)
> > +int raw_patch_instruction(struct ppc_inst *addr, struct ppc_inst instr)
> > {
> > return __patch_instruction(addr, instr, addr);
> > }
> > @@ -137,10 +137,10 @@ static inline int unmap_patch_area(unsigned long addr)
> > return 0;
> > }
> >
> > -static int do_patch_instruction(unsigned int *addr, unsigned int instr)
> > +static int do_patch_instruction(struct ppc_inst *addr, struct ppc_inst
> > instr)
> > {
> > int err;
> > - unsigned int *patch_addr = NULL;
> > + struct ppc_inst *patch_addr = NULL;
> > unsigned long flags;
> > unsigned long text_poke_addr;
> > unsigned long kaddr = (unsigned long)addr;
> > @@ -177,14 +177,14 @@ static int do_patch_instruction(unsigned int *addr,
> > unsigned int instr)
> > }
> > #else /* !CONFIG_STRICT_KERNEL_RWX */
> >
> > -static int do_patch_instruction(unsigned int *addr, unsigned int instr)
> > +static int do_patch_instruction(struct ppc_inst *addr, struct ppc_inst
> > instr)
> > {
> > return raw_patch_instruction(addr, instr);
> > }
> >
> > #endif /* CONFIG_STRICT_KERNEL_RWX */
> >
> > -int patch_instruction(unsigned int *addr, unsigned int instr)
> > +int patch_instruction(struct ppc_inst *addr, struct ppc_inst instr)
> > {
> > /* Make sure we aren't patching a freed init section */
> > if (init_mem_is_free && init_section_contains(addr, 4)) {
> > @@ -195,9 +195,9 @@ int patch_instruction(unsigned int *addr, unsigned int
> > instr)
> > }
> > NOKPROBE_SYMBOL(patch_instruction);
> >
> > -int patch_branch(unsigned int *addr, unsigned long target, int flags)
> > +int patch_branch(struct ppc_inst *addr, unsigned long target, int flags)
> > {
> > - unsigned int instr;
> > + struct ppc_inst instr;
> >
> > create_branch(&instr, addr, target, flags);
> > return patch_instruction(addr, instr);
> > @@ -229,7 +229,7 @@ bool is_offset_in_branch_range(long offset)
> > * Helper to check if a given instruction is a conditional branch
> > * Derived from the conditional checks in analyse_instr()
> > */
> > -bool is_conditional_branch(unsigned int instr)
> > +bool is_conditional_branch(struct ppc_inst instr)
> > {
> > unsigned int opcode = ppc_inst_opcode(instr);
> >
> > @@ -247,13 +247,13 @@ bool is_conditional_branch(unsigned int instr)
> > }
> > NOKPROBE_SYMBOL(is_conditional_branch);
> >
> > -int create_branch(unsigned int *instr,
> > - const unsigned int *addr,
> > +int create_branch(struct ppc_inst *instr,
> > + const struct ppc_inst *addr,
> > unsigned long target, int flags)
> > {
> > long offset;
> >
> > - *instr = 0;
> > + *instr = ppc_inst(0);
> > offset = target;
> > if (! (flags & BRANCH_ABSOLUTE))
> > offset = offset - (unsigned long)addr;
> > @@ -263,12 +263,12 @@ int create_branch(unsigned int *instr,
> > return 1;
> >
> > /* Mask out the flags and target, so they don't step on each other. */
> > - *instr = 0x48000000 | (flags & 0x3) | (offset & 0x03FFFFFC);
> > + *instr = ppc_inst(0x48000000 | (flags & 0x3) | (offset & 0x03FFFFFC));
> >
> > return 0;
> > }
> >
> > -int create_cond_branch(unsigned int *instr, const unsigned int *addr,
> > +int create_cond_branch(struct ppc_inst *instr, const struct ppc_inst *addr,
> > unsigned long target, int flags)
> > {
> > long offset;
> > @@ -282,27 +282,27 @@ int create_cond_branch(unsigned int *instr, const
> > unsigned int *addr,
> > return 1;
> >
> > /* Mask out the flags and target, so they don't step on each other. */
> > - *instr = 0x40000000 | (flags & 0x3FF0003) | (offset & 0xFFFC);
> > + *instr = ppc_inst(0x40000000 | (flags & 0x3FF0003) | (offset &
> > 0xFFFC));
> >
> > return 0;
> > }
> >
> > -static unsigned int branch_opcode(unsigned int instr)
> > +static unsigned int branch_opcode(struct ppc_inst instr)
> > {
> > return ppc_inst_opcode(instr) & 0x3F;
> > }
> >
> > -static int instr_is_branch_iform(unsigned int instr)
> > +static int instr_is_branch_iform(struct ppc_inst instr)
> > {
> > return branch_opcode(instr) == 18;
> > }
> >
> > -static int instr_is_branch_bform(unsigned int instr)
> > +static int instr_is_branch_bform(struct ppc_inst instr)
> > {
> > return branch_opcode(instr) == 16;
> > }
> >
> > -int instr_is_relative_branch(unsigned int instr)
> > +int instr_is_relative_branch(struct ppc_inst instr)
> > {
> > if (ppc_inst_val(instr) & BRANCH_ABSOLUTE)
> > return 0;
> > @@ -310,12 +310,12 @@ int instr_is_relative_branch(unsigned int instr)
> > return instr_is_branch_iform(instr) || instr_is_branch_bform(instr);
> > }
> >
> > -int instr_is_relative_link_branch(unsigned int instr)
> > +int instr_is_relative_link_branch(struct ppc_inst instr)
> > {
> > return instr_is_relative_branch(instr) && (ppc_inst_val(instr) &
> > BRANCH_SET_LINK);
> > }
> >
> > -static unsigned long branch_iform_target(const unsigned int *instr)
> > +static unsigned long branch_iform_target(const struct ppc_inst *instr)
> > {
> > signed long imm;
> >
> > @@ -331,7 +331,7 @@ static unsigned long branch_iform_target(const unsigned
> > int *instr)
> > return (unsigned long)imm;
> > }
> >
> > -static unsigned long branch_bform_target(const unsigned int *instr)
> > +static unsigned long branch_bform_target(const struct ppc_inst *instr)
> > {
> > signed long imm;
> >
> > @@ -347,7 +347,7 @@ static unsigned long branch_bform_target(const unsigned
> > int *instr)
> > return (unsigned long)imm;
> > }
> >
> > -unsigned long branch_target(const unsigned int *instr)
> > +unsigned long branch_target(const struct ppc_inst *instr)
> > {
> > if (instr_is_branch_iform(*instr))
> > return branch_iform_target(instr);
> > @@ -357,7 +357,7 @@ unsigned long branch_target(const unsigned int *instr)
> > return 0;
> > }
> >
> > -int instr_is_branch_to_addr(const unsigned int *instr, unsigned long addr)
> > +int instr_is_branch_to_addr(const struct ppc_inst *instr, unsigned long
> > addr)
> > {
> > if (instr_is_branch_iform(*instr) || instr_is_branch_bform(*instr))
> > return branch_target(instr) == addr;
> > @@ -365,7 +365,7 @@ int instr_is_branch_to_addr(const unsigned int *instr,
> > unsigned long addr)
> > return 0;
> > }
> >
> > -int translate_branch(unsigned int *instr, const unsigned int *dest, const
> > unsigned int *src)
> > +int translate_branch(struct ppc_inst *instr, const struct ppc_inst *dest,
> > const struct ppc_inst *src)
> > {
> > unsigned long target;
> >
> > @@ -408,7 +408,7 @@ static void __init test_trampoline(void)
> > static void __init test_branch_iform(void)
> > {
> > int err;
> > - unsigned int instr;
> > + struct ppc_inst instr;
> > unsigned long addr;
> >
> > addr = (unsigned long)&instr;
> > @@ -483,12 +483,12 @@ static void __init test_branch_iform(void)
> >
> > static void __init test_create_function_call(void)
> > {
> > - unsigned int *iptr;
> > + struct ppc_inst *iptr;
> > unsigned long dest;
> > - unsigned int instr;
> > + struct ppc_inst instr;
> >
> > /* Check we can create a function call */
> > - iptr = (unsigned int *)ppc_function_entry(test_trampoline);
> > + iptr = (struct ppc_inst *)ppc_function_entry(test_trampoline);
> > dest = ppc_function_entry(test_create_function_call);
> > create_branch(&instr, iptr, dest, BRANCH_SET_LINK);
> > patch_instruction(iptr, instr);
> > @@ -499,7 +499,8 @@ static void __init test_branch_bform(void)
> > {
> > int err;
> > unsigned long addr;
> > - unsigned int *iptr, instr, flags;
> > + struct ppc_inst *iptr, instr;
> > + unsigned int flags;
> >
> > iptr = &instr;
> > addr = (unsigned long)iptr;
> > @@ -569,8 +570,8 @@ static void __init test_branch_bform(void)
> > static void __init test_translate_branch(void)
> > {
> > unsigned long addr;
> > - unsigned int *p, *q;
> > - unsigned int instr;
> > + struct ppc_inst *p, *q;
> > + struct ppc_inst instr;
> > void *buf;
> >
> > buf = vmalloc(PAGE_ALIGN(0x2000000 + 1));
> > diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-
> > fixups.c
> > index 6e7479b8887a..8c5d0db77013 100644
> > --- a/arch/powerpc/lib/feature-fixups.c
> > +++ b/arch/powerpc/lib/feature-fixups.c
> > @@ -32,26 +32,26 @@ struct fixup_entry {
> > long alt_end_off;
> > };
> >
> > -static unsigned int *calc_addr(struct fixup_entry *fcur, long offset)
> > +static struct ppc_inst *calc_addr(struct fixup_entry *fcur, long offset)
> > {
> > /*
> > * We store the offset to the code as a negative offset from
> > * the start of the alt_entry, to support the VDSO. This
> > * routine converts that back into an actual address.
> > */
> > - return (unsigned int *)((unsigned long)fcur + offset);
> > + return (struct ppc_inst *)((unsigned long)fcur + offset);
> > }
> >
> > -static int patch_alt_instruction(unsigned int *src, unsigned int *dest,
> > - unsigned int *alt_start, unsigned int
> > *alt_end)
> > +static int patch_alt_instruction(struct ppc_inst *src, struct ppc_inst
> > *dest,
> > + struct ppc_inst *alt_start, struct ppc_inst
> > *alt_end)
> > {
> > int err;
> > - unsigned int instr;
> > + struct ppc_inst instr;
> >
> > instr = *src;
> >
> > if (instr_is_relative_branch(*src)) {
> > - unsigned int *target = (unsigned int *)branch_target(src);
> > + struct ppc_inst *target = (struct ppc_inst
> > *)branch_target(src);
> >
> > /* Branch within the section doesn't need translating */
> > if (target < alt_start || target > alt_end) {
> > @@ -68,7 +68,7 @@ static int patch_alt_instruction(unsigned int *src,
> > unsigned int *dest,
> >
> > static int patch_feature_section(unsigned long value, struct fixup_entry
> > *fcur)
> > {
> > - unsigned int *start, *end, *alt_start, *alt_end, *src, *dest;
> > + struct ppc_inst *start, *end, *alt_start, *alt_end, *src, *dest;
> >
> > start = calc_addr(fcur, fcur->start_off);
> > end = calc_addr(fcur, fcur->end_off);
> > @@ -147,15 +147,15 @@ static void do_stf_entry_barrier_fixups(enum
> > stf_barrier_type types)
> >
> > pr_devel("patching dest %lx\n", (unsigned long)dest);
> >
> > - patch_instruction(dest, ppc_inst(instrs[0]));
> > + patch_instruction((struct ppc_inst *)dest,
> > ppc_inst(instrs[0]));
>
>
> we had already declared them as struct ppc_inst *
True.
>
>
> >
> > if (types & STF_BARRIER_FALLBACK)
> > - patch_branch(dest + 1, (unsigned
> > long)&stf_barrier_fallback,
> > + patch_branch((struct ppc_inst *)(dest + 1), (unsigned
> > long)&stf_barrier_fallback,
> > BRANCH_SET_LINK);
> > else
> > - patch_instruction(dest + 1, ppc_inst(instrs[1]));
> > + patch_instruction((struct ppc_inst *)(dest + 1),
> > ppc_inst(instrs[1]));
> >
> > - patch_instruction(dest + 2, ppc_inst(instrs[2]));
> > + patch_instruction((struct ppc_inst *)(dest + 2),
> > ppc_inst(instrs[2]));
> > }
> >
> > printk(KERN_DEBUG "stf-barrier: patched %d entry locations (%s
> > barrier)\n", i,
> > @@ -208,12 +208,12 @@ static void do_stf_exit_barrier_fixups(enum
> > stf_barrier_type types)
> >
> > pr_devel("patching dest %lx\n", (unsigned long)dest);
> >
> > - patch_instruction(dest, ppc_inst(instrs[0]));
> > - patch_instruction(dest + 1, ppc_inst(instrs[1]));
> > - patch_instruction(dest + 2, ppc_inst(instrs[2]));
> > - patch_instruction(dest + 3, ppc_inst(instrs[3]));
> > - patch_instruction(dest + 4, ppc_inst(instrs[4]));
> > - patch_instruction(dest + 5, ppc_inst(instrs[5]));
> > + patch_instruction((struct ppc_inst *)dest,
> > ppc_inst(instrs[0]));
> > + patch_instruction((struct ppc_inst *)(dest + 1),
> > ppc_inst(instrs[1]));
> > + patch_instruction((struct ppc_inst *)(dest + 2),
> > ppc_inst(instrs[2]));
> > + patch_instruction((struct ppc_inst *)(dest + 3),
> > ppc_inst(instrs[3]));
> > + patch_instruction((struct ppc_inst *)(dest + 4),
> > ppc_inst(instrs[4]));
> > + patch_instruction((struct ppc_inst *)(dest + 5),
> > ppc_inst(instrs[5]));
> > }
> > printk(KERN_DEBUG "stf-barrier: patched %d exit locations (%s
> > barrier)\n", i,
> > (types == STF_BARRIER_NONE) ? "no" :
> > @@ -261,9 +261,9 @@ void do_rfi_flush_fixups(enum l1d_flush_type types)
> >
> > pr_devel("patching dest %lx\n", (unsigned long)dest);
> >
> > - patch_instruction(dest, ppc_inst(instrs[0]));
> > - patch_instruction(dest + 1, ppc_inst(instrs[1]));
> > - patch_instruction(dest + 2, ppc_inst(instrs[2]));
> > + patch_instruction((struct ppc_inst *)dest,
> > ppc_inst(instrs[0]));
> > + patch_instruction((struct ppc_inst *)(dest + 1),
> > ppc_inst(instrs[1]));
> > + patch_instruction((struct ppc_inst *)(dest + 2),
> > ppc_inst(instrs[2]));
> > }
> >
> > printk(KERN_DEBUG "rfi-flush: patched %d locations (%s flush)\n", i,
> > @@ -296,7 +296,7 @@ void do_barrier_nospec_fixups_range(bool enable, void
> > *fixup_start, void *fixup_
> > dest = (void *)start + *start;
> >
> > pr_devel("patching dest %lx\n", (unsigned long)dest);
> > - patch_instruction(dest, ppc_inst(instr));
> > + patch_instruction((struct ppc_inst *)dest, ppc_inst(instr));
> > }
> >
> > printk(KERN_DEBUG "barrier-nospec: patched %d locations\n", i);
> > @@ -339,8 +339,8 @@ void do_barrier_nospec_fixups_range(bool enable, void
> > *fixup_start, void *fixup_
> > dest = (void *)start + *start;
> >
> > pr_devel("patching dest %lx\n", (unsigned long)dest);
> > - patch_instruction(dest, ppc_inst(instr[0]));
> > - patch_instruction(dest + 1, ppc_inst(instr[1]));
> > + patch_instruction((struct ppc_inst *)dest, ppc_inst(instr[0]));
> > + patch_instruction((struct ppc_inst *)(dest + 1),
> > ppc_inst(instr[1]));
> > }
> >
> > printk(KERN_DEBUG "barrier-nospec: patched %d locations\n", i);
> > @@ -373,7 +373,7 @@ void do_btb_flush_fixups(void)
> > void do_lwsync_fixups(unsigned long value, void *fixup_start, void
> > *fixup_end)
> > {
> > long *start, *end;
> > - unsigned int *dest;
> > + struct ppc_inst *dest;
> >
> > if (!(value & CPU_FTR_LWSYNC))
> > return ;
> > diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
> > index 26e37176692e..52ddd3122dc8 100644
> > --- a/arch/powerpc/lib/sstep.c
> > +++ b/arch/powerpc/lib/sstep.c
> > @@ -1163,7 +1163,7 @@ static nokprobe_inline int trap_compare(long v1, long
> > v2)
> > * otherwise.
> > */
> > int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
> > - unsigned int instr)
> > + struct ppc_inst instr)
>
>
> we need to take care of `instr` inside this function as well to adopt
> the helpers to work with it.
>
> -- Bala
>
>
> > {
> > unsigned int opcode, ra, rb, rc, rd, spr, u;
> > unsigned long int imm;
> > @@ -3103,7 +3103,7 @@ NOKPROBE_SYMBOL(emulate_loadstore);
> > * or -1 if the instruction is one that should not be stepped,
> > * such as an rfid, or a mtmsrd that would clear MSR_RI.
> > */
> > -int emulate_step(struct pt_regs *regs, unsigned int instr)
> > +int emulate_step(struct pt_regs *regs, struct ppc_inst instr)
> > {
> > struct instruction_op op;
> > int r, err, type;
> > diff --git a/arch/powerpc/lib/test_emulate_step.c
> > b/arch/powerpc/lib/test_emulate_step.c
> > index 16387a9bfda0..60b159b60545 100644
> > --- a/arch/powerpc/lib/test_emulate_step.c
> > +++ b/arch/powerpc/lib/test_emulate_step.c
> > @@ -461,7 +461,7 @@ struct compute_test {
> > struct {
> > char *descr;
> > unsigned long flags;
> > - unsigned int instr;
> > + struct ppc_inst instr;
> > struct pt_regs regs;
> > } subtests[MAX_SUBTESTS + 1];
> > };
> > @@ -842,7 +842,7 @@ static struct compute_test compute_tests[] = {
> > };
> >
> > static int __init emulate_compute_instr(struct pt_regs *regs,
> > - unsigned int instr)
> > + struct ppc_inst instr)
> > {
> > struct instruction_op op;
> >
> > @@ -860,7 +860,7 @@ static int __init emulate_compute_instr(struct pt_regs
> > *regs,
> > }
> >
> > static int __init execute_compute_instr(struct pt_regs *regs,
> > - unsigned int instr)
> > + struct ppc_inst instr)
> > {
> > extern int exec_instr(struct pt_regs *regs);
> > extern s32 patch__exec_instr;
> > @@ -891,7 +891,8 @@ static void __init run_tests_compute(void)
> > unsigned long flags;
> > struct compute_test *test;
> > struct pt_regs *regs, exp, got;
> > - unsigned int i, j, k, instr;
> > + unsigned int i, j, k;
> > + struct ppc_inst instr;
> > bool ignore_gpr, ignore_xer, ignore_ccr, passed;
> >
> > for (i = 0; i < ARRAY_SIZE(compute_tests); i++) {
> > diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-
> > book3s.c
> > index 3086055bf681..2d2580a4bfb5 100644
> > --- a/arch/powerpc/perf/core-book3s.c
> > +++ b/arch/powerpc/perf/core-book3s.c
> > @@ -421,14 +421,14 @@ static __u64 power_pmu_bhrb_to(u64 addr)
> > if (probe_kernel_read(&instr, (void *)addr, sizeof(instr)))
> > return 0;
> >
> > - return branch_target(&instr);
> > + return branch_target((struct ppc_inst *)&instr);
> > }
> >
> > /* Userspace: need copy instruction here then translate it */
> > if (probe_user_read(&instr, (unsigned int __user *)addr,
> > sizeof(instr)))
> > return 0;
> >
> > - target = branch_target(&instr);
> > + target = branch_target((struct ppc_inst *)&instr);
> > if ((!target) || (instr & BRANCH_ABSOLUTE))
> > return target;
> >
> > diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
> > index f6c87d3d53ea..e3d8e1b8ce01 100644
> > --- a/arch/powerpc/xmon/xmon.c
> > +++ b/arch/powerpc/xmon/xmon.c
> > @@ -99,7 +99,7 @@ static long *xmon_fault_jmp[NR_CPUS];
> > /* Breakpoint stuff */
> > struct bpt {
> > unsigned long address;
> > - unsigned int *instr;
> > + struct ppc_inst *instr;
> > atomic_t ref_count;
> > int enabled;
> > unsigned long pad;
> > @@ -117,7 +117,7 @@ static unsigned bpinstr = 0x7fe00008; /* trap */
> >
> > #define BP_NUM(bp) ((bp) - bpts + 1)
> >
> > -#define BPT_SIZE (sizeof(unsigned int) * 2)
> > +#define BPT_SIZE (sizeof(struct ppc_inst) * 2)
> > #define BPT_WORDS (BPT_SIZE / sizeof(unsigned int))
> > extern unsigned int bpt_table[NBPTS * BPT_WORDS];
> >
> > @@ -879,8 +879,8 @@ static struct bpt *new_breakpoint(unsigned long a)
> > for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
> > if (!bp->enabled && atomic_read(&bp->ref_count) == 0) {
> > bp->address = a;
> > - bp->instr = bpt_table + ((bp - bpts) * BPT_WORDS);
> > - patch_instruction(bp->instr + 1, bpinstr);
> > + bp->instr = (void *)(bpt_table + ((bp - bpts) *
> > BPT_WORDS));
> > + patch_instruction(bp->instr + 1, ppc_inst(bpinstr));
> > return bp;
> > }
> > }
> > @@ -892,7 +892,7 @@ static struct bpt *new_breakpoint(unsigned long a)
> > static void insert_bpts(void)
> > {
> > int i;
> > - unsigned int instr;
> > + struct ppc_inst instr;
> > struct bpt *bp;
> >
> > bp = bpts;
> > @@ -914,8 +914,8 @@ static void insert_bpts(void)
> > patch_instruction(bp->instr, instr);
> > if (bp->enabled & BP_CIABR)
> > continue;
> > - if (patch_instruction((unsigned int *)bp->address,
> > - bpinstr) != 0) {
> > + if (patch_instruction((struct ppc_inst *)bp->address,
> > + ppc_inst(bpinstr)) !=
> > 0) {
> > printf("Couldn't write instruction at %lx, "
> > "disabling breakpoint there\n", bp->address);
> > bp->enabled &= ~BP_TRAP;
> > @@ -943,7 +943,7 @@ static void remove_bpts(void)
> > {
> > int i;
> > struct bpt *bp;
> > - unsigned instr;
> > + struct ppc_inst instr;
> >
> > bp = bpts;
> > for (i = 0; i < NBPTS; ++i, ++bp) {
> > @@ -952,7 +952,7 @@ static void remove_bpts(void)
> > if (mread(bp->address, &instr, 4) == 4
> > && ppc_inst_equal(instr, ppc_inst(bpinstr))
> > && patch_instruction(
> > - (unsigned int *)bp->address, bp->instr[0]) != 0)
> > + (struct ppc_inst *)bp->address, bp->instr[0]) != 0)
> > printf("Couldn't remove breakpoint at %lx\n",
> > bp->address);
> > }
> > @@ -1159,7 +1159,7 @@ static int do_step(struct pt_regs *regs)
> > */
> > static int do_step(struct pt_regs *regs)
> > {
> > - unsigned int instr;
> > + struct ppc_inst instr;
> > int stepped;
> >
> > force_enable_xmon();
> > @@ -1325,7 +1325,7 @@ csum(void)
> > */
> > static long check_bp_loc(unsigned long addr)
> > {
> > - unsigned int instr;
> > + struct ppc_inst instr;
> >
> > addr &= ~3;
> > if (!is_kernel_addr(addr)) {
> > @@ -2846,7 +2846,7 @@ generic_inst_dump(unsigned long adr, long count, int
> > praddr,
> > {
> > int nr, dotted;
> > unsigned long first_adr;
> > - unsigned int inst, last_inst = ppc_inst(0);
> > + struct ppc_inst inst, last_inst = ppc_inst(0);
> > unsigned char val[4];
> >
> > dotted = 0;
>
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 11/21] powerpc: Define and use __get_user_instr{, inatomic}()
2020-04-07 10:48 ` Balamuruhan S
@ 2020-04-08 2:13 ` Jordan Niethe
0 siblings, 0 replies; 71+ messages in thread
From: Jordan Niethe @ 2020-04-08 2:13 UTC (permalink / raw)
To: Balamuruhan S
Cc: Alistair Popple, linuxppc-dev, Nicholas Piggin, Daniel Axtens
On Tue, Apr 7, 2020 at 8:48 PM Balamuruhan S <bala24@linux.ibm.com> wrote:
>
> On Mon, 2020-04-06 at 18:09 +1000, Jordan Niethe wrote:
> > Define specific __get_user_instr() and __get_user_instr_inatomic()
> > macros for reading instructions from user space.
> >
> > Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> > ---
> > arch/powerpc/include/asm/uaccess.h | 5 +++++
> > arch/powerpc/kernel/align.c | 2 +-
> > arch/powerpc/kernel/hw_breakpoint.c | 2 +-
> > arch/powerpc/kernel/vecemu.c | 2 +-
> > 4 files changed, 8 insertions(+), 3 deletions(-)
> >
> > diff --git a/arch/powerpc/include/asm/uaccess.h
> > b/arch/powerpc/include/asm/uaccess.h
> > index 2f500debae21..c0a35e4586a5 100644
> > --- a/arch/powerpc/include/asm/uaccess.h
> > +++ b/arch/powerpc/include/asm/uaccess.h
> > @@ -105,6 +105,11 @@ 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)))
> >
> > +#define __get_user_instr(x, ptr) \
> > + __get_user_nocheck((x).val, (u32 *)(ptr), sizeof(u32), true)
> > +
> > +#define __get_user_instr_inatomic(x, ptr) \
> > + __get_user_nosleep((x).val, (u32 *)(ptr), sizeof(u32))
>
>
> should we use ppc_inst_val() ?
The __get_user() macros load a value into the given variable, so we
can not use ppc_inst_val().
>
> -- Bala
>
>
> > extern long __put_user_bad(void);
> >
> > /*
> > diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
> > index 66a6d1de7799..65cdfd41e3a1 100644
> > --- a/arch/powerpc/kernel/align.c
> > +++ b/arch/powerpc/kernel/align.c
> > @@ -304,7 +304,7 @@ int fix_alignment(struct pt_regs *regs)
> > */
> > CHECK_FULL_REGS(regs);
> >
> > - if (unlikely(__get_user(instr.val, (unsigned int __user *)regs->nip)))
> > + if (unlikely(__get_user_instr(instr, (void __user *)regs->nip)))
> > return -EFAULT;
> > if ((regs->msr & MSR_LE) != (MSR_KERNEL & MSR_LE)) {
> > /* We don't handle PPC little-endian any more... */
> > diff --git a/arch/powerpc/kernel/hw_breakpoint.c
> > b/arch/powerpc/kernel/hw_breakpoint.c
> > index 542f65ccf68b..cebab14e2788 100644
> > --- a/arch/powerpc/kernel/hw_breakpoint.c
> > +++ b/arch/powerpc/kernel/hw_breakpoint.c
> > @@ -249,7 +249,7 @@ static bool stepping_handler(struct pt_regs *regs, struct
> > perf_event *bp,
> > struct instruction_op op;
> > unsigned long addr = info->address;
> >
> > - if (__get_user_inatomic(instr.val, (unsigned int *)regs->nip))
> > + if (__get_user_instr_inatomic(instr, (void __user *)regs->nip))
> > goto fail;
> >
> > ret = analyse_instr(&op, regs, instr);
> > diff --git a/arch/powerpc/kernel/vecemu.c b/arch/powerpc/kernel/vecemu.c
> > index bbf536e10902..c82ede46d71b 100644
> > --- a/arch/powerpc/kernel/vecemu.c
> > +++ b/arch/powerpc/kernel/vecemu.c
> > @@ -266,7 +266,7 @@ int emulate_altivec(struct pt_regs *regs)
> > unsigned int va, vb, vc, vd;
> > vector128 *vrs;
> >
> > - if (get_user(instr.val, (unsigned int __user *) regs->nip))
> > + if (__get_user_instr(instr, (void __user *) regs->nip))
> > return -EFAULT;
> >
> > word = ppc_inst_val(instr);
>
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 12/21] powerpc: Introduce a function for reporting instruction length
2020-04-07 11:14 ` Balamuruhan S
@ 2020-04-08 2:14 ` Jordan Niethe
0 siblings, 0 replies; 71+ messages in thread
From: Jordan Niethe @ 2020-04-08 2:14 UTC (permalink / raw)
To: Balamuruhan S
Cc: Alistair Popple, linuxppc-dev, Nicholas Piggin, Daniel Axtens
On Tue, Apr 7, 2020 at 9:15 PM Balamuruhan S <bala24@linux.ibm.com> wrote:
>
> On Mon, 2020-04-06 at 18:09 +1000, Jordan Niethe wrote:
> > Currently all instructions have the same length, but in preparation for
> > prefixed instructions introduce a function for returning instruction
> > length.
> >
> > Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> > ---
> > arch/powerpc/include/asm/inst.h | 5 +++++
> > arch/powerpc/kernel/kprobes.c | 6 ++++--
> > arch/powerpc/kernel/uprobes.c | 2 +-
> > 3 files changed, 10 insertions(+), 3 deletions(-)
> >
> > diff --git a/arch/powerpc/include/asm/inst.h
> > b/arch/powerpc/include/asm/inst.h
> > index 369b35ce964c..70b37a35a91a 100644
> > --- a/arch/powerpc/include/asm/inst.h
> > +++ b/arch/powerpc/include/asm/inst.h
> > @@ -17,6 +17,11 @@ static inline u32 ppc_inst_val(struct ppc_inst x)
> > return x.val;
> > }
> >
> > +static inline bool ppc_inst_len(struct ppc_inst x)
>
>
> return type shouldn't be a bool, `size_t` instead.
Thank you.
>
> -- Bala
>
> > +{
> > + return sizeof(struct ppc_inst);
> > +}
> > +
> > static inline int ppc_inst_opcode(struct ppc_inst x)
> > {
> > return x.val >> 26;
> > diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
> > index ff53e5ef7e40..8d17cfdcdc54 100644
> > --- a/arch/powerpc/kernel/kprobes.c
> > +++ b/arch/powerpc/kernel/kprobes.c
> > @@ -474,14 +474,16 @@ NOKPROBE_SYMBOL(trampoline_probe_handler);
> > */
> > int kprobe_post_handler(struct pt_regs *regs)
> > {
> > + int len;
> > struct kprobe *cur = kprobe_running();
> > struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
> >
> > if (!cur || user_mode(regs))
> > return 0;
> >
> > + len = ppc_inst_len(ppc_inst_read((struct ppc_inst *)cur->ainsn.insn));
> > /* make sure we got here for instruction we have a kprobe on */
> > - if (((unsigned long)cur->ainsn.insn + 4) != regs->nip)
> > + if (((unsigned long)cur->ainsn.insn + len) != regs->nip)
> > return 0;
> >
> > if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) {
> > @@ -490,7 +492,7 @@ int kprobe_post_handler(struct pt_regs *regs)
> > }
> >
> > /* Adjust nip to after the single-stepped instruction */
> > - regs->nip = (unsigned long)cur->addr + 4;
> > + regs->nip = (unsigned long)cur->addr + len;
> > regs->msr |= kcb->kprobe_saved_msr;
> >
> > /*Restore back the original saved kprobes variables and continue. */
> > diff --git a/arch/powerpc/kernel/uprobes.c b/arch/powerpc/kernel/uprobes.c
> > index 31c870287f2b..8e63afa012ba 100644
> > --- a/arch/powerpc/kernel/uprobes.c
> > +++ b/arch/powerpc/kernel/uprobes.c
> > @@ -112,7 +112,7 @@ int arch_uprobe_post_xol(struct arch_uprobe *auprobe,
> > struct pt_regs *regs)
> > * support doesn't exist and have to fix-up the next instruction
> > * to be executed.
> > */
> > - regs->nip = utask->vaddr + MAX_UINSN_BYTES;
> > + regs->nip = utask->vaddr + ppc_inst_len(auprobe->insn);
> >
> > user_disable_single_step(current);
> > return 0;
>
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 13/21] powerpc/xmon: Use a function for reading instructions
2020-04-07 11:30 ` Balamuruhan S
@ 2020-04-08 2:18 ` Jordan Niethe
2020-04-09 5:04 ` Balamuruhan S
0 siblings, 1 reply; 71+ messages in thread
From: Jordan Niethe @ 2020-04-08 2:18 UTC (permalink / raw)
To: Balamuruhan S
Cc: Alistair Popple, linuxppc-dev, Nicholas Piggin, Daniel Axtens
On Tue, Apr 7, 2020 at 9:31 PM Balamuruhan S <bala24@linux.ibm.com> wrote:
>
> On Mon, 2020-04-06 at 18:09 +1000, Jordan Niethe wrote:
> > Currently in xmon, mread() is used for reading instructions. In
> > preparation for prefixed instructions, create and use a new function,
> > mread_instr(), especially for reading instructions.
> >
> > Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> > ---
> > v5: New to series, seperated from "Add prefixed instructions to
> > instruction data type"
> > ---
> > arch/powerpc/xmon/xmon.c | 24 ++++++++++++++++++++----
> > 1 file changed, 20 insertions(+), 4 deletions(-)
> >
> > diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
> > index 5e3949322a6c..6f4cf01a58c1 100644
> > --- a/arch/powerpc/xmon/xmon.c
> > +++ b/arch/powerpc/xmon/xmon.c
> > @@ -125,6 +125,7 @@ extern unsigned int bpt_table[NBPTS * BPT_WORDS];
> > static int cmds(struct pt_regs *);
> > static int mread(unsigned long, void *, int);
> > static int mwrite(unsigned long, void *, int);
> > +static int mread_instr(unsigned long, struct ppc_inst *);
> > static int handle_fault(struct pt_regs *);
> > static void byterev(unsigned char *, int);
> > static void memex(void);
> > @@ -899,7 +900,7 @@ static void insert_bpts(void)
> > for (i = 0; i < NBPTS; ++i, ++bp) {
> > if ((bp->enabled & (BP_TRAP|BP_CIABR)) == 0)
> > continue;
> > - if (mread(bp->address, &instr, 4) != 4) {
> > + if (!mread_instr(bp->address, &instr)) {
>
>
> Are these checks made based on whether `ppc_inst_len()` returns bool from
> mread_instr() ?
No, it was meant to be the length itself returned with a length of 0
indicating an error. I will need to fix that.
>
> -- Bala
>
>
> > printf("Couldn't read instruction at %lx, "
> > "disabling breakpoint there\n", bp->address);
> > bp->enabled = 0;
> > @@ -949,7 +950,7 @@ static void remove_bpts(void)
> > for (i = 0; i < NBPTS; ++i, ++bp) {
> > if ((bp->enabled & (BP_TRAP|BP_CIABR)) != BP_TRAP)
> > continue;
> > - if (mread(bp->address, &instr, 4) == 4
> > + if (mread_instr(bp->address, &instr)
> > && ppc_inst_equal(instr, ppc_inst(bpinstr))
> > && patch_instruction(
> > (struct ppc_inst *)bp->address, ppc_inst_read(bp-
> > >instr)) != 0)
> > @@ -1165,7 +1166,7 @@ static int do_step(struct pt_regs *regs)
> > force_enable_xmon();
> > /* check we are in 64-bit kernel mode, translation enabled */
> > if ((regs->msr & (MSR_64BIT|MSR_PR|MSR_IR)) == (MSR_64BIT|MSR_IR)) {
> > - if (mread(regs->nip, &instr, 4) == 4) {
> > + if (mread_instr(regs->nip, &instr)) {
> > stepped = emulate_step(regs, instr);
> > if (stepped < 0) {
> > printf("Couldn't single-step %s instruction\n",
> > @@ -1332,7 +1333,7 @@ static long check_bp_loc(unsigned long addr)
> > printf("Breakpoints may only be placed at kernel addresses\n");
> > return 0;
> > }
> > - if (!mread(addr, &instr, sizeof(instr))) {
> > + if (!mread_instr(addr, &instr)) {
> > printf("Can't read instruction at address %lx\n", addr);
> > return 0;
> > }
> > @@ -2125,6 +2126,21 @@ mwrite(unsigned long adrs, void *buf, int size)
> > return n;
> > }
> >
> > +static int
> > +mread_instr(unsigned long adrs, struct ppc_inst *instr)
> > +{
> > + if (setjmp(bus_error_jmp) == 0) {
> > + catch_memory_errors = 1;
> > + sync();
> > + *instr = ppc_inst_read((struct ppc_inst *)adrs);
> > + sync();
> > + /* wait a little while to see if we get a machine check */
> > + __delay(200);
> > + }
> > + catch_memory_errors = 0;
> > + return ppc_inst_len(*instr);
> > +}
> > +
> > static int fault_type;
> > static int fault_except;
> > static char *fault_chars[] = { "--", "**", "##" };
>
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 18/21] powerpc64: Add prefixed instructions to instruction data type
2020-04-06 10:25 ` Christophe Leroy
2020-04-06 11:13 ` Jordan Niethe
@ 2020-04-08 18:11 ` Segher Boessenkool
2020-04-08 18:43 ` Christophe Leroy
1 sibling, 1 reply; 71+ messages in thread
From: Segher Boessenkool @ 2020-04-08 18:11 UTC (permalink / raw)
To: Christophe Leroy
Cc: Alistair Popple, npiggin, bala24, Jordan Niethe, linuxppc-dev, dja
On Mon, Apr 06, 2020 at 12:25:27PM +0200, Christophe Leroy wrote:
> > if (ppc_inst_prefixed(x) != ppc_inst_prefixed(y))
> > return false;
> > else if (ppc_inst_prefixed(x))
> > return !memcmp(&x, &y, sizeof(struct ppc_inst));
>
> Are we sure memcmp() is a good candidate for the comparison ? Can we do
> simpler ? Especially, I understood a prefixed instruction is a 64 bits
> properly aligned instruction, can we do a simple u64 compare ? Or is GCC
> intelligent enough to do that without calling memcmp() function which is
> heavy ?
A prefixed insn is *not* 8-byte aligned, it is 4-byte aligned, fwiw.
memcmp() isn't as heavy as you fear, not with a non-ancient GCC at least.
But this could be written in a nicer way, sure :-)
Segher
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 05/21] powerpc: Use a function for getting the instruction op code
2020-04-06 8:09 ` [PATCH v5 05/21] powerpc: Use a function for getting the instruction op code Jordan Niethe
2020-04-06 8:22 ` Christophe Leroy
2020-04-07 7:04 ` Balamuruhan S
@ 2020-04-08 18:21 ` Segher Boessenkool
2020-04-09 4:48 ` Jordan Niethe
2 siblings, 1 reply; 71+ messages in thread
From: Segher Boessenkool @ 2020-04-08 18:21 UTC (permalink / raw)
To: Jordan Niethe; +Cc: alistair, dja, linuxppc-dev, npiggin, bala24
Hi!
On Mon, Apr 06, 2020 at 06:09:20PM +1000, Jordan Niethe wrote:
> +static inline int ppc_inst_opcode(u32 x)
> +{
> + return x >> 26;
> +}
Maybe you should have "primary opcode" in this function name?
Segher
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 18/21] powerpc64: Add prefixed instructions to instruction data type
2020-04-08 18:11 ` Segher Boessenkool
@ 2020-04-08 18:43 ` Christophe Leroy
0 siblings, 0 replies; 71+ messages in thread
From: Christophe Leroy @ 2020-04-08 18:43 UTC (permalink / raw)
To: Segher Boessenkool
Cc: Alistair Popple, npiggin, bala24, Jordan Niethe, linuxppc-dev, dja
Le 08/04/2020 à 20:11, Segher Boessenkool a écrit :
> On Mon, Apr 06, 2020 at 12:25:27PM +0200, Christophe Leroy wrote:
>>> if (ppc_inst_prefixed(x) != ppc_inst_prefixed(y))
>>> return false;
>>> else if (ppc_inst_prefixed(x))
>>> return !memcmp(&x, &y, sizeof(struct ppc_inst));
>>
>> Are we sure memcmp() is a good candidate for the comparison ? Can we do
>> simpler ? Especially, I understood a prefixed instruction is a 64 bits
>> properly aligned instruction, can we do a simple u64 compare ? Or is GCC
>> intelligent enough to do that without calling memcmp() function which is
>> heavy ?
>
> A prefixed insn is *not* 8-byte aligned, it is 4-byte aligned, fwiw.
Ah, yes, I read too fast https://patchwork.ozlabs.org/patch/1266721/
It's not 64 bits, it is 64 bytes.
>
> memcmp() isn't as heavy as you fear, not with a non-ancient GCC at least.
> But this could be written in a nicer way, sure :-)
>
>
> Segher
>
Christophe
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 05/21] powerpc: Use a function for getting the instruction op code
2020-04-08 18:21 ` Segher Boessenkool
@ 2020-04-09 4:48 ` Jordan Niethe
0 siblings, 0 replies; 71+ messages in thread
From: Jordan Niethe @ 2020-04-09 4:48 UTC (permalink / raw)
To: Segher Boessenkool
Cc: Alistair Popple, Daniel Axtens, linuxppc-dev, Nicholas Piggin,
Balamuruhan S
On Thu, Apr 9, 2020 at 4:21 AM Segher Boessenkool
<segher@kernel.crashing.org> wrote:
>
> Hi!
>
> On Mon, Apr 06, 2020 at 06:09:20PM +1000, Jordan Niethe wrote:
> > +static inline int ppc_inst_opcode(u32 x)
> > +{
> > + return x >> 26;
> > +}
>
> Maybe you should have "primary opcode" in this function name?
Thanks, that is a good idea.
>
>
> Segher
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 13/21] powerpc/xmon: Use a function for reading instructions
2020-04-08 2:18 ` Jordan Niethe
@ 2020-04-09 5:04 ` Balamuruhan S
2020-04-09 5:14 ` Jordan Niethe
0 siblings, 1 reply; 71+ messages in thread
From: Balamuruhan S @ 2020-04-09 5:04 UTC (permalink / raw)
To: Jordan Niethe
Cc: Alistair Popple, linuxppc-dev, Nicholas Piggin, Daniel Axtens
On Wed, 2020-04-08 at 12:18 +1000, Jordan Niethe wrote:
> On Tue, Apr 7, 2020 at 9:31 PM Balamuruhan S <bala24@linux.ibm.com> wrote:
> > On Mon, 2020-04-06 at 18:09 +1000, Jordan Niethe wrote:
> > > Currently in xmon, mread() is used for reading instructions. In
> > > preparation for prefixed instructions, create and use a new function,
> > > mread_instr(), especially for reading instructions.
> > >
> > > Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> > > ---
> > > v5: New to series, seperated from "Add prefixed instructions to
> > > instruction data type"
> > > ---
> > > arch/powerpc/xmon/xmon.c | 24 ++++++++++++++++++++----
> > > 1 file changed, 20 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
> > > index 5e3949322a6c..6f4cf01a58c1 100644
> > > --- a/arch/powerpc/xmon/xmon.c
> > > +++ b/arch/powerpc/xmon/xmon.c
> > > @@ -125,6 +125,7 @@ extern unsigned int bpt_table[NBPTS * BPT_WORDS];
> > > static int cmds(struct pt_regs *);
> > > static int mread(unsigned long, void *, int);
> > > static int mwrite(unsigned long, void *, int);
> > > +static int mread_instr(unsigned long, struct ppc_inst *);
> > > static int handle_fault(struct pt_regs *);
> > > static void byterev(unsigned char *, int);
> > > static void memex(void);
> > > @@ -899,7 +900,7 @@ static void insert_bpts(void)
> > > for (i = 0; i < NBPTS; ++i, ++bp) {
> > > if ((bp->enabled & (BP_TRAP|BP_CIABR)) == 0)
> > > continue;
> > > - if (mread(bp->address, &instr, 4) != 4) {
> > > + if (!mread_instr(bp->address, &instr)) {
> >
> > Are these checks made based on whether `ppc_inst_len()` returns bool from
> > mread_instr() ?
> No, it was meant to be the length itself returned with a length of 0
> indicating an error. I will need to fix that.
I doubt it would return 0, whether we read instruction or not ppc_inst_len()
would always return sizeof(struct ppc_inst).
can we do something like,
static int
mread_instr(unsigned long adrs, struct ppc_inst *instr)
{
int size = 0;
if (setjmp(bus_error_jmp) == 0) {
catch_memory_errors = 1;
sync();
*instr = ppc_inst_read((struct ppc_inst *)adrs);
sync();
/* wait a little while to see if we get a machine check */
__delay(200);
size = ppc_inst_len(instr);
}
catch_memory_errors = 0;
return size;
}
-- Bala
> > -- Bala
> >
> >
> > > printf("Couldn't read instruction at %lx, "
> > > "disabling breakpoint there\n", bp-
> > > >address);
> > > bp->enabled = 0;
> > > @@ -949,7 +950,7 @@ static void remove_bpts(void)
> > > for (i = 0; i < NBPTS; ++i, ++bp) {
> > > if ((bp->enabled & (BP_TRAP|BP_CIABR)) != BP_TRAP)
> > > continue;
> > > - if (mread(bp->address, &instr, 4) == 4
> > > + if (mread_instr(bp->address, &instr)
> > > && ppc_inst_equal(instr, ppc_inst(bpinstr))
> > > && patch_instruction(
> > > (struct ppc_inst *)bp->address, ppc_inst_read(bp-
> > > > instr)) != 0)
> > > @@ -1165,7 +1166,7 @@ static int do_step(struct pt_regs *regs)
> > > force_enable_xmon();
> > > /* check we are in 64-bit kernel mode, translation enabled */
> > > if ((regs->msr & (MSR_64BIT|MSR_PR|MSR_IR)) == (MSR_64BIT|MSR_IR))
> > > {
> > > - if (mread(regs->nip, &instr, 4) == 4) {
> > > + if (mread_instr(regs->nip, &instr)) {
> > > stepped = emulate_step(regs, instr);
> > > if (stepped < 0) {
> > > printf("Couldn't single-step %s
> > > instruction\n",
> > > @@ -1332,7 +1333,7 @@ static long check_bp_loc(unsigned long addr)
> > > printf("Breakpoints may only be placed at kernel
> > > addresses\n");
> > > return 0;
> > > }
> > > - if (!mread(addr, &instr, sizeof(instr))) {
> > > + if (!mread_instr(addr, &instr)) {
> > > printf("Can't read instruction at address %lx\n", addr);
> > > return 0;
> > > }
> > > @@ -2125,6 +2126,21 @@ mwrite(unsigned long adrs, void *buf, int size)
> > > return n;
> > > }
> > >
> > > +static int
> > > +mread_instr(unsigned long adrs, struct ppc_inst *instr)
> > > +{
> > > + if (setjmp(bus_error_jmp) == 0) {
> > > + catch_memory_errors = 1;
> > > + sync();
> > > + *instr = ppc_inst_read((struct ppc_inst *)adrs);
> > > + sync();
> > > + /* wait a little while to see if we get a machine check */
> > > + __delay(200);
> > > + }
> > > + catch_memory_errors = 0;
> > > + return ppc_inst_len(*instr);
> > > +}
> > > +
> > > static int fault_type;
> > > static int fault_except;
> > > static char *fault_chars[] = { "--", "**", "##" };
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 13/21] powerpc/xmon: Use a function for reading instructions
2020-04-09 5:04 ` Balamuruhan S
@ 2020-04-09 5:14 ` Jordan Niethe
0 siblings, 0 replies; 71+ messages in thread
From: Jordan Niethe @ 2020-04-09 5:14 UTC (permalink / raw)
To: Balamuruhan S
Cc: Alistair Popple, linuxppc-dev, Nicholas Piggin, Daniel Axtens
On Thu, Apr 9, 2020 at 3:04 PM Balamuruhan S <bala24@linux.ibm.com> wrote:
>
> On Wed, 2020-04-08 at 12:18 +1000, Jordan Niethe wrote:
> > On Tue, Apr 7, 2020 at 9:31 PM Balamuruhan S <bala24@linux.ibm.com> wrote:
> > > On Mon, 2020-04-06 at 18:09 +1000, Jordan Niethe wrote:
> > > > Currently in xmon, mread() is used for reading instructions. In
> > > > preparation for prefixed instructions, create and use a new function,
> > > > mread_instr(), especially for reading instructions.
> > > >
> > > > Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> > > > ---
> > > > v5: New to series, seperated from "Add prefixed instructions to
> > > > instruction data type"
> > > > ---
> > > > arch/powerpc/xmon/xmon.c | 24 ++++++++++++++++++++----
> > > > 1 file changed, 20 insertions(+), 4 deletions(-)
> > > >
> > > > diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
> > > > index 5e3949322a6c..6f4cf01a58c1 100644
> > > > --- a/arch/powerpc/xmon/xmon.c
> > > > +++ b/arch/powerpc/xmon/xmon.c
> > > > @@ -125,6 +125,7 @@ extern unsigned int bpt_table[NBPTS * BPT_WORDS];
> > > > static int cmds(struct pt_regs *);
> > > > static int mread(unsigned long, void *, int);
> > > > static int mwrite(unsigned long, void *, int);
> > > > +static int mread_instr(unsigned long, struct ppc_inst *);
> > > > static int handle_fault(struct pt_regs *);
> > > > static void byterev(unsigned char *, int);
> > > > static void memex(void);
> > > > @@ -899,7 +900,7 @@ static void insert_bpts(void)
> > > > for (i = 0; i < NBPTS; ++i, ++bp) {
> > > > if ((bp->enabled & (BP_TRAP|BP_CIABR)) == 0)
> > > > continue;
> > > > - if (mread(bp->address, &instr, 4) != 4) {
> > > > + if (!mread_instr(bp->address, &instr)) {
> > >
> > > Are these checks made based on whether `ppc_inst_len()` returns bool from
> > > mread_instr() ?
> > No, it was meant to be the length itself returned with a length of 0
> > indicating an error. I will need to fix that.
>
>
> I doubt it would return 0, whether we read instruction or not ppc_inst_len()
> would always return sizeof(struct ppc_inst).
Yes, sorry I meant I would have to change the function so that it
would return 0.
>
> can we do something like,
>
> static int
> mread_instr(unsigned long adrs, struct ppc_inst *instr)
> {
> int size = 0;
> if (setjmp(bus_error_jmp) == 0) {
> catch_memory_errors = 1;
> sync();
> *instr = ppc_inst_read((struct ppc_inst *)adrs);
> sync();
> /* wait a little while to see if we get a machine check */
> __delay(200);
> size = ppc_inst_len(instr);
> }
> catch_memory_errors = 0;
> return size;
> }
Yeah that looks right.
>
> -- Bala
> > > -- Bala
> > >
> > >
> > > > printf("Couldn't read instruction at %lx, "
> > > > "disabling breakpoint there\n", bp-
> > > > >address);
> > > > bp->enabled = 0;
> > > > @@ -949,7 +950,7 @@ static void remove_bpts(void)
> > > > for (i = 0; i < NBPTS; ++i, ++bp) {
> > > > if ((bp->enabled & (BP_TRAP|BP_CIABR)) != BP_TRAP)
> > > > continue;
> > > > - if (mread(bp->address, &instr, 4) == 4
> > > > + if (mread_instr(bp->address, &instr)
> > > > && ppc_inst_equal(instr, ppc_inst(bpinstr))
> > > > && patch_instruction(
> > > > (struct ppc_inst *)bp->address, ppc_inst_read(bp-
> > > > > instr)) != 0)
> > > > @@ -1165,7 +1166,7 @@ static int do_step(struct pt_regs *regs)
> > > > force_enable_xmon();
> > > > /* check we are in 64-bit kernel mode, translation enabled */
> > > > if ((regs->msr & (MSR_64BIT|MSR_PR|MSR_IR)) == (MSR_64BIT|MSR_IR))
> > > > {
> > > > - if (mread(regs->nip, &instr, 4) == 4) {
> > > > + if (mread_instr(regs->nip, &instr)) {
> > > > stepped = emulate_step(regs, instr);
> > > > if (stepped < 0) {
> > > > printf("Couldn't single-step %s
> > > > instruction\n",
> > > > @@ -1332,7 +1333,7 @@ static long check_bp_loc(unsigned long addr)
> > > > printf("Breakpoints may only be placed at kernel
> > > > addresses\n");
> > > > return 0;
> > > > }
> > > > - if (!mread(addr, &instr, sizeof(instr))) {
> > > > + if (!mread_instr(addr, &instr)) {
> > > > printf("Can't read instruction at address %lx\n", addr);
> > > > return 0;
> > > > }
> > > > @@ -2125,6 +2126,21 @@ mwrite(unsigned long adrs, void *buf, int size)
> > > > return n;
> > > > }
> > > >
> > > > +static int
> > > > +mread_instr(unsigned long adrs, struct ppc_inst *instr)
> > > > +{
> > > > + if (setjmp(bus_error_jmp) == 0) {
> > > > + catch_memory_errors = 1;
> > > > + sync();
> > > > + *instr = ppc_inst_read((struct ppc_inst *)adrs);
> > > > + sync();
> > > > + /* wait a little while to see if we get a machine check */
> > > > + __delay(200);
> > > > + }
> > > > + catch_memory_errors = 0;
> > > > + return ppc_inst_len(*instr);
> > > > +}
> > > > +
> > > > static int fault_type;
> > > > static int fault_except;
> > > > static char *fault_chars[] = { "--", "**", "##" };
>
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 02/21] powerpc/xmon: Move out-of-line instructions to text section
2020-04-06 8:09 ` [PATCH v5 02/21] powerpc/xmon: Move out-of-line instructions to text section Jordan Niethe
2020-04-07 6:45 ` Balamuruhan S
@ 2020-04-09 6:11 ` Christophe Leroy
2020-04-09 7:26 ` Jordan Niethe
1 sibling, 1 reply; 71+ messages in thread
From: Christophe Leroy @ 2020-04-09 6:11 UTC (permalink / raw)
To: Jordan Niethe, linuxppc-dev; +Cc: bala24, alistair, dja, npiggin
Le 06/04/2020 à 10:09, Jordan Niethe a écrit :
> To execute an instruction out of line after a breakpoint, the NIP is set
> to the address of struct bpt::instr. Here a copy of the instruction that
> was replaced with a breakpoint is kept, along with a trap so normal flow
> can be resumed after XOLing. The struct bpt's are located within the
> data section. This is problematic as the data section may be marked as
> no execute.
>
> Instead of each struct bpt holding the instructions to be XOL'd, make a
> new array, bpt_table[], with enough space to hold instructions for the
> number of supported breakpoints. Place this array in the text section.
> Make struct bpt::instr a pointer to the instructions in bpt_table[]
> associated with that breakpoint. This association is a simple mapping:
> bpts[n] -> bpt_table[n * words per breakpoint]. Currently we only need
> the copied instruction followed by a trap, so 2 words per breakpoint.
>
> Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> ---
> v4: New to series
> v5: - Do not use __section(), use a .space directive in .S file
I was going to comment to use __section() instead of creating a
dedicated .S file.
Why did you change that in v5 ?
> - Simplify in_breakpoint_table() calculation
> - Define BPT_SIZE
> ---
> arch/powerpc/xmon/Makefile | 2 +-
> arch/powerpc/xmon/xmon.c | 23 +++++++++++++----------
> arch/powerpc/xmon/xmon_bpts.S | 8 ++++++++
> arch/powerpc/xmon/xmon_bpts.h | 8 ++++++++
> 4 files changed, 30 insertions(+), 11 deletions(-)
> create mode 100644 arch/powerpc/xmon/xmon_bpts.S
> create mode 100644 arch/powerpc/xmon/xmon_bpts.h
>
> diff --git a/arch/powerpc/xmon/Makefile b/arch/powerpc/xmon/Makefile
> index c3842dbeb1b7..515a13ea6f28 100644
> --- a/arch/powerpc/xmon/Makefile
> +++ b/arch/powerpc/xmon/Makefile
> @@ -21,7 +21,7 @@ endif
>
> ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC)
>
> -obj-y += xmon.o nonstdio.o spr_access.o
> +obj-y += xmon.o nonstdio.o spr_access.o xmon_bpts.o
>
> ifdef CONFIG_XMON_DISASSEMBLY
> obj-y += ppc-dis.o ppc-opc.o
> diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
> index 02e3bd62cab4..049375206510 100644
> --- a/arch/powerpc/xmon/xmon.c
> +++ b/arch/powerpc/xmon/xmon.c
> @@ -62,6 +62,7 @@
>
> #include "nonstdio.h"
> #include "dis-asm.h"
> +#include "xmon_bpts.h"
>
> #ifdef CONFIG_SMP
> static cpumask_t cpus_in_xmon = CPU_MASK_NONE;
> @@ -97,7 +98,7 @@ static long *xmon_fault_jmp[NR_CPUS];
> /* Breakpoint stuff */
> struct bpt {
> unsigned long address;
> - unsigned int instr[2];
> + unsigned int *instr;
> atomic_t ref_count;
> int enabled;
> unsigned long pad;
> @@ -108,7 +109,6 @@ struct bpt {
> #define BP_TRAP 2
> #define BP_DABR 4
>
> -#define NBPTS 256
> static struct bpt bpts[NBPTS];
> static struct bpt dabr;
> static struct bpt *iabr;
> @@ -116,6 +116,10 @@ static unsigned bpinstr = 0x7fe00008; /* trap */
>
> #define BP_NUM(bp) ((bp) - bpts + 1)
>
> +#define BPT_SIZE (sizeof(unsigned int) * 2)
> +#define BPT_WORDS (BPT_SIZE / sizeof(unsigned int))
Wouldn't it make more sense to do the following ? :
#define BPT_WORDS 2
#define BPT_SIZE (BPT_WORDS * sizeof(unsigned int))
> +extern unsigned int bpt_table[NBPTS * BPT_WORDS];
Should go in xmon_bpts.h if we keep the definition in xmon_bpts.S
> +
> /* Prototypes */
> static int cmds(struct pt_regs *);
> static int mread(unsigned long, void *, int);
> @@ -853,15 +857,13 @@ static struct bpt *in_breakpoint_table(unsigned long nip, unsigned long *offp)
> {
> unsigned long off;
>
> - off = nip - (unsigned long) bpts;
> - if (off >= sizeof(bpts))
> + off = nip - (unsigned long) bpt_table;
> + if (off >= sizeof(bpt_table))
> return NULL;
> - off %= sizeof(struct bpt);
> - if (off != offsetof(struct bpt, instr[0])
> - && off != offsetof(struct bpt, instr[1]))
> + *offp = off % BPT_SIZE;
Can we use logical operation instead ?
*offp = off & (BPT_SIZE - 1);
> + if (*offp != 0 && *offp != 4)
Could be:
if (off & 3)
> return NULL;
> - *offp = off - offsetof(struct bpt, instr[0]);
> - return (struct bpt *) (nip - off);
> + return bpts + (off / BPT_SIZE);
> }
>
> static struct bpt *new_breakpoint(unsigned long a)
> @@ -876,7 +878,8 @@ static struct bpt *new_breakpoint(unsigned long a)
> for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
> if (!bp->enabled && atomic_read(&bp->ref_count) == 0) {
> bp->address = a;
> - patch_instruction(&bp->instr[1], bpinstr);
> + bp->instr = bpt_table + ((bp - bpts) * BPT_WORDS);
> + patch_instruction(bp->instr + 1, bpinstr);
> return bp;
> }
> }
> diff --git a/arch/powerpc/xmon/xmon_bpts.S b/arch/powerpc/xmon/xmon_bpts.S
> new file mode 100644
> index 000000000000..ebb2dbc70ca8
> --- /dev/null
> +++ b/arch/powerpc/xmon/xmon_bpts.S
> @@ -0,0 +1,8 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#include <asm/ppc_asm.h>
> +#include <asm/asm-compat.h>
> +#include "xmon_bpts.h"
> +
> +.global bpt_table
> +bpt_table:
> + .space NBPTS * 8
Should use BPT_SIZE instead of raw coding 8.
> diff --git a/arch/powerpc/xmon/xmon_bpts.h b/arch/powerpc/xmon/xmon_bpts.h
> new file mode 100644
> index 000000000000..840e70be7945
> --- /dev/null
> +++ b/arch/powerpc/xmon/xmon_bpts.h
> @@ -0,0 +1,8 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef XMON_BPTS_H
> +#define XMON_BPTS_H
> +
> +#define NBPTS 256
> +
> +#endif /* XMON_BPTS_H */
> +
>
I think it would be better to split this patch in two patches:
1/ First patch to move breakpoints out of struct bpt into a bpt_table.
2/ Second patch to move bpt_table into .text section.
Christophe
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 00/21] Initial Prefixed Instruction support
2020-04-06 8:09 [PATCH v5 00/21] Initial Prefixed Instruction support Jordan Niethe
` (20 preceding siblings ...)
2020-04-06 8:09 ` [PATCH v5 21/21] powerpc sstep: Add support for prefixed fixed-point arithmetic Jordan Niethe
@ 2020-04-09 6:39 ` Christophe Leroy
2020-04-09 7:28 ` Jordan Niethe
21 siblings, 1 reply; 71+ messages in thread
From: Christophe Leroy @ 2020-04-09 6:39 UTC (permalink / raw)
To: Jordan Niethe, linuxppc-dev; +Cc: bala24, alistair, dja, npiggin
On 04/06/2020 08:09 AM, Jordan Niethe wrote:
> A future revision of the ISA will introduce prefixed instructions. A
> prefixed instruction is composed of a 4-byte prefix followed by a
> 4-byte suffix.
>
> All prefixes have the major opcode 1. A prefix will never be a valid
> word instruction. A suffix may be an existing word instruction or a
> new instruction.
>
> This series enables prefixed instructions and extends the instruction
> emulation to support them. Then the places where prefixed instructions
> might need to be emulated are updated.
>
> v5 is based on feedback from Nick Piggins, Michael Ellerman, Balamuruhan
> Suriyakumar and Alistair Popple.
> The major changes:
> - The ppc instruction type is now a struct
> - Series now just based on next
> - ppc_inst_masked() dropped
> - Space for xmon breakpoints allocated in an assembly file
> - "Add prefixed instructions to instruction data type" patch seperated in
> to smaller patches
> - Calling convention for create_branch() is changed
> - Some places which had not been updated to use the data type are now updated
Build fails. I have not investigated why:
CC arch/powerpc/kernel/process.o
In file included from ./arch/powerpc/include/asm/code-patching.h:14:0,
from arch/powerpc/kernel/process.c:60:
./arch/powerpc/include/asm/inst.h:69:38: error: unknown type name ‘ppc_inst’
static inline bool ppc_inst_prefixed(ppc_inst x)
^
./arch/powerpc/include/asm/inst.h:79:19: error: redefinition of
‘ppc_inst_val’
static inline u32 ppc_inst_val(struct ppc_inst x)
^
./arch/powerpc/include/asm/inst.h:21:19: note: previous definition of
‘ppc_inst_val’ was here
static inline u32 ppc_inst_val(struct ppc_inst x)
^
./arch/powerpc/include/asm/inst.h: In function ‘ppc_inst_len’:
./arch/powerpc/include/asm/inst.h:103:10: error: implicit declaration of
function ‘ppc_inst_prefixed’ [-Werror=implicit-function-declaration]
return (ppc_inst_prefixed(x)) ? 8 : 4;
^
Christophe
>
> v4 is based on feedback from Nick Piggins, Christophe Leroy and Daniel Axtens.
> The major changes:
> - Move xmon breakpoints from data section to text section
> - Introduce a data type for instructions on powerpc
>
> v3 is based on feedback from Christophe Leroy. The major changes:
> - Completely replacing store_inst() with patch_instruction() in
> xmon
> - Improve implementation of mread_instr() to not use mread().
> - Base the series on top of
> https://patchwork.ozlabs.org/patch/1232619/ as this will effect
> kprobes.
> - Some renaming and simplification of conditionals.
>
> v2 incorporates feedback from Daniel Axtens and and Balamuruhan
> S. The major changes are:
> - Squashing together all commits about SRR1 bits
> - Squashing all commits for supporting prefixed load stores
> - Changing abbreviated references to sufx/prfx -> suffix/prefix
> - Introducing macros for returning the length of an instruction
> - Removing sign extension flag from pstd/pld in sstep.c
> - Dropping patch "powerpc/fault: Use analyse_instr() to check for
> store with updates to sp" from the series, it did not really fit
> with prefixed enablement in the first place and as reported by Greg
> Kurz did not work correctly.
>
>
> Alistair Popple (1):
> powerpc: Enable Prefixed Instructions
>
> Jordan Niethe (20):
> powerpc/xmon: Remove store_inst() for patch_instruction()
> powerpc/xmon: Move out-of-line instructions to text section
> powerpc: Change calling convention for create_branch() et. al.
> powerpc: Use a macro for creating instructions from u32s
> powerpc: Use a function for getting the instruction op code
> powerpc: Use an accessor for instructions
> powerpc: Use a function for byte swapping instructions
> powerpc: Introduce functions for instruction equality
> powerpc: Use a datatype for instructions
> powerpc: Use a function for reading instructions
> powerpc: Define and use __get_user_instr{,inatomic}()
> powerpc: Introduce a function for reporting instruction length
> powerpc/xmon: Use a function for reading instructions
> powerpc/xmon: Move insertion of breakpoint for xol'ing
> powerpc: Make test_translate_branch() independent of instruction
> length
> powerpc: Define new SRR1 bits for a future ISA version
> powerpc64: Add prefixed instructions to instruction data type
> powerpc: Support prefixed instructions in alignment handler
> powerpc sstep: Add support for prefixed load/stores
> powerpc sstep: Add support for prefixed fixed-point arithmetic
>
> arch/powerpc/include/asm/code-patching.h | 37 +-
> arch/powerpc/include/asm/inst.h | 106 ++++++
> arch/powerpc/include/asm/kprobes.h | 2 +-
> arch/powerpc/include/asm/reg.h | 7 +-
> arch/powerpc/include/asm/sstep.h | 15 +-
> arch/powerpc/include/asm/uaccess.h | 28 ++
> arch/powerpc/include/asm/uprobes.h | 7 +-
> arch/powerpc/kernel/align.c | 13 +-
> arch/powerpc/kernel/epapr_paravirt.c | 5 +-
> arch/powerpc/kernel/hw_breakpoint.c | 5 +-
> arch/powerpc/kernel/jump_label.c | 5 +-
> arch/powerpc/kernel/kgdb.c | 9 +-
> arch/powerpc/kernel/kprobes.c | 24 +-
> arch/powerpc/kernel/mce_power.c | 5 +-
> arch/powerpc/kernel/module_64.c | 3 +-
> arch/powerpc/kernel/optprobes.c | 91 +++--
> arch/powerpc/kernel/optprobes_head.S | 3 +
> arch/powerpc/kernel/security.c | 9 +-
> arch/powerpc/kernel/setup_32.c | 4 +-
> arch/powerpc/kernel/trace/ftrace.c | 190 ++++++----
> arch/powerpc/kernel/traps.c | 20 +-
> arch/powerpc/kernel/uprobes.c | 3 +-
> arch/powerpc/kernel/vecemu.c | 20 +-
> arch/powerpc/kvm/book3s_hv_nested.c | 2 +-
> arch/powerpc/kvm/book3s_hv_rm_mmu.c | 2 +-
> arch/powerpc/kvm/emulate_loadstore.c | 2 +-
> arch/powerpc/lib/code-patching.c | 289 +++++++-------
> arch/powerpc/lib/feature-fixups.c | 69 ++--
> arch/powerpc/lib/sstep.c | 455 ++++++++++++++++-------
> arch/powerpc/lib/test_emulate_step.c | 56 +--
> arch/powerpc/perf/core-book3s.c | 4 +-
> arch/powerpc/xmon/Makefile | 2 +-
> arch/powerpc/xmon/xmon.c | 94 +++--
> arch/powerpc/xmon/xmon_bpts.S | 10 +
> arch/powerpc/xmon/xmon_bpts.h | 8 +
> 35 files changed, 1042 insertions(+), 562 deletions(-)
> create mode 100644 arch/powerpc/include/asm/inst.h
> create mode 100644 arch/powerpc/xmon/xmon_bpts.S
> create mode 100644 arch/powerpc/xmon/xmon_bpts.h
>
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 02/21] powerpc/xmon: Move out-of-line instructions to text section
2020-04-09 6:11 ` Christophe Leroy
@ 2020-04-09 7:26 ` Jordan Niethe
0 siblings, 0 replies; 71+ messages in thread
From: Jordan Niethe @ 2020-04-09 7:26 UTC (permalink / raw)
To: Christophe Leroy
Cc: Alistair Popple, Nicholas Piggin, Balamuruhan S, linuxppc-dev,
Daniel Axtens
On Thu, Apr 9, 2020 at 4:11 PM Christophe Leroy <christophe.leroy@c-s.fr> wrote:
>
>
>
> Le 06/04/2020 à 10:09, Jordan Niethe a écrit :
> > To execute an instruction out of line after a breakpoint, the NIP is set
> > to the address of struct bpt::instr. Here a copy of the instruction that
> > was replaced with a breakpoint is kept, along with a trap so normal flow
> > can be resumed after XOLing. The struct bpt's are located within the
> > data section. This is problematic as the data section may be marked as
> > no execute.
> >
> > Instead of each struct bpt holding the instructions to be XOL'd, make a
> > new array, bpt_table[], with enough space to hold instructions for the
> > number of supported breakpoints. Place this array in the text section.
> > Make struct bpt::instr a pointer to the instructions in bpt_table[]
> > associated with that breakpoint. This association is a simple mapping:
> > bpts[n] -> bpt_table[n * words per breakpoint]. Currently we only need
> > the copied instruction followed by a trap, so 2 words per breakpoint.
> >
> > Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> > ---
> > v4: New to series
> > v5: - Do not use __section(), use a .space directive in .S file
>
> I was going to comment to use __section() instead of creating a
> dedicated .S file.
>
> Why did you change that in v5 ?
I noticed with some toolchains I was getting this message:
Warning: setting incorrect section attributes for .text.xmon_bpts
I was talking with mpe about it and he said that the usual way for
doing things like this was with .space in a .S file so I changed to
that way.
>
> > - Simplify in_breakpoint_table() calculation
> > - Define BPT_SIZE
> > ---
> > arch/powerpc/xmon/Makefile | 2 +-
> > arch/powerpc/xmon/xmon.c | 23 +++++++++++++----------
> > arch/powerpc/xmon/xmon_bpts.S | 8 ++++++++
> > arch/powerpc/xmon/xmon_bpts.h | 8 ++++++++
> > 4 files changed, 30 insertions(+), 11 deletions(-)
> > create mode 100644 arch/powerpc/xmon/xmon_bpts.S
> > create mode 100644 arch/powerpc/xmon/xmon_bpts.h
> >
> > diff --git a/arch/powerpc/xmon/Makefile b/arch/powerpc/xmon/Makefile
> > index c3842dbeb1b7..515a13ea6f28 100644
> > --- a/arch/powerpc/xmon/Makefile
> > +++ b/arch/powerpc/xmon/Makefile
> > @@ -21,7 +21,7 @@ endif
> >
> > ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC)
> >
> > -obj-y += xmon.o nonstdio.o spr_access.o
> > +obj-y += xmon.o nonstdio.o spr_access.o xmon_bpts.o
> >
> > ifdef CONFIG_XMON_DISASSEMBLY
> > obj-y += ppc-dis.o ppc-opc.o
> > diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
> > index 02e3bd62cab4..049375206510 100644
> > --- a/arch/powerpc/xmon/xmon.c
> > +++ b/arch/powerpc/xmon/xmon.c
> > @@ -62,6 +62,7 @@
> >
> > #include "nonstdio.h"
> > #include "dis-asm.h"
> > +#include "xmon_bpts.h"
> >
> > #ifdef CONFIG_SMP
> > static cpumask_t cpus_in_xmon = CPU_MASK_NONE;
> > @@ -97,7 +98,7 @@ static long *xmon_fault_jmp[NR_CPUS];
> > /* Breakpoint stuff */
> > struct bpt {
> > unsigned long address;
> > - unsigned int instr[2];
> > + unsigned int *instr;
> > atomic_t ref_count;
> > int enabled;
> > unsigned long pad;
> > @@ -108,7 +109,6 @@ struct bpt {
> > #define BP_TRAP 2
> > #define BP_DABR 4
> >
> > -#define NBPTS 256
> > static struct bpt bpts[NBPTS];
> > static struct bpt dabr;
> > static struct bpt *iabr;
> > @@ -116,6 +116,10 @@ static unsigned bpinstr = 0x7fe00008; /* trap */
> >
> > #define BP_NUM(bp) ((bp) - bpts + 1)
> >
> > +#define BPT_SIZE (sizeof(unsigned int) * 2)
> > +#define BPT_WORDS (BPT_SIZE / sizeof(unsigned int))
>
> Wouldn't it make more sense to do the following ? :
>
> #define BPT_WORDS 2
> #define BPT_SIZE (BPT_WORDS * sizeof(unsigned int))
I defined it like that so when we changed unsigned int -> struct
ppc_inst it would be the correct size whether or not the struct
included a suffix.
Otherwise it would be more straightforward to do it like that.
>
> > +extern unsigned int bpt_table[NBPTS * BPT_WORDS];
>
> Should go in xmon_bpts.h if we keep the definition in xmon_bpts.S
Right.
>
> > +
> > /* Prototypes */
> > static int cmds(struct pt_regs *);
> > static int mread(unsigned long, void *, int);
> > @@ -853,15 +857,13 @@ static struct bpt *in_breakpoint_table(unsigned long nip, unsigned long *offp)
> > {
> > unsigned long off;
> >
> > - off = nip - (unsigned long) bpts;
> > - if (off >= sizeof(bpts))
> > + off = nip - (unsigned long) bpt_table;
> > + if (off >= sizeof(bpt_table))
> > return NULL;
> > - off %= sizeof(struct bpt);
> > - if (off != offsetof(struct bpt, instr[0])
> > - && off != offsetof(struct bpt, instr[1]))
> > + *offp = off % BPT_SIZE;
>
> Can we use logical operation instead ?
Sure, I was just adapting how it was already but that would probably be clearer.
>
> *offp = off & (BPT_SIZE - 1);
>
> > + if (*offp != 0 && *offp != 4)
>
> Could be:
> if (off & 3)
>
> > return NULL;
> > - *offp = off - offsetof(struct bpt, instr[0]);
> > - return (struct bpt *) (nip - off);
> > + return bpts + (off / BPT_SIZE);
> > }
> >
> > static struct bpt *new_breakpoint(unsigned long a)
> > @@ -876,7 +878,8 @@ static struct bpt *new_breakpoint(unsigned long a)
> > for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
> > if (!bp->enabled && atomic_read(&bp->ref_count) == 0) {
> > bp->address = a;
> > - patch_instruction(&bp->instr[1], bpinstr);
> > + bp->instr = bpt_table + ((bp - bpts) * BPT_WORDS);
> > + patch_instruction(bp->instr + 1, bpinstr);
> > return bp;
> > }
> > }
> > diff --git a/arch/powerpc/xmon/xmon_bpts.S b/arch/powerpc/xmon/xmon_bpts.S
> > new file mode 100644
> > index 000000000000..ebb2dbc70ca8
> > --- /dev/null
> > +++ b/arch/powerpc/xmon/xmon_bpts.S
> > @@ -0,0 +1,8 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +#include <asm/ppc_asm.h>
> > +#include <asm/asm-compat.h>
> > +#include "xmon_bpts.h"
> > +
> > +.global bpt_table
> > +bpt_table:
> > + .space NBPTS * 8
>
> Should use BPT_SIZE instead of raw coding 8.
Right.
>
> > diff --git a/arch/powerpc/xmon/xmon_bpts.h b/arch/powerpc/xmon/xmon_bpts.h
> > new file mode 100644
> > index 000000000000..840e70be7945
> > --- /dev/null
> > +++ b/arch/powerpc/xmon/xmon_bpts.h
> > @@ -0,0 +1,8 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +#ifndef XMON_BPTS_H
> > +#define XMON_BPTS_H
> > +
> > +#define NBPTS 256
> > +
> > +#endif /* XMON_BPTS_H */
> > +
> >
>
> I think it would be better to split this patch in two patches:
> 1/ First patch to move breakpoints out of struct bpt into a bpt_table.
> 2/ Second patch to move bpt_table into .text section.
Bala suggested so too, I will separate them next time.
>
> Christophe
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 00/21] Initial Prefixed Instruction support
2020-04-09 6:39 ` [PATCH v5 00/21] Initial Prefixed Instruction support Christophe Leroy
@ 2020-04-09 7:28 ` Jordan Niethe
0 siblings, 0 replies; 71+ messages in thread
From: Jordan Niethe @ 2020-04-09 7:28 UTC (permalink / raw)
To: Christophe Leroy
Cc: Alistair Popple, Nicholas Piggin, Balamuruhan S, linuxppc-dev,
Daniel Axtens
On Thu, Apr 9, 2020 at 4:39 PM Christophe Leroy <christophe.leroy@c-s.fr> wrote:
>
>
>
> On 04/06/2020 08:09 AM, Jordan Niethe wrote:
> > A future revision of the ISA will introduce prefixed instructions. A
> > prefixed instruction is composed of a 4-byte prefix followed by a
> > 4-byte suffix.
> >
> > All prefixes have the major opcode 1. A prefix will never be a valid
> > word instruction. A suffix may be an existing word instruction or a
> > new instruction.
> >
> > This series enables prefixed instructions and extends the instruction
> > emulation to support them. Then the places where prefixed instructions
> > might need to be emulated are updated.
> >
> > v5 is based on feedback from Nick Piggins, Michael Ellerman, Balamuruhan
> > Suriyakumar and Alistair Popple.
> > The major changes:
> > - The ppc instruction type is now a struct
> > - Series now just based on next
> > - ppc_inst_masked() dropped
> > - Space for xmon breakpoints allocated in an assembly file
> > - "Add prefixed instructions to instruction data type" patch seperated in
> > to smaller patches
> > - Calling convention for create_branch() is changed
> > - Some places which had not been updated to use the data type are now updated
>
> Build fails. I have not investigated why:
Thanks, I will check it out.
>
> CC arch/powerpc/kernel/process.o
> In file included from ./arch/powerpc/include/asm/code-patching.h:14:0,
> from arch/powerpc/kernel/process.c:60:
> ./arch/powerpc/include/asm/inst.h:69:38: error: unknown type name ‘ppc_inst’
> static inline bool ppc_inst_prefixed(ppc_inst x)
> ^
> ./arch/powerpc/include/asm/inst.h:79:19: error: redefinition of
> ‘ppc_inst_val’
> static inline u32 ppc_inst_val(struct ppc_inst x)
> ^
> ./arch/powerpc/include/asm/inst.h:21:19: note: previous definition of
> ‘ppc_inst_val’ was here
> static inline u32 ppc_inst_val(struct ppc_inst x)
> ^
> ./arch/powerpc/include/asm/inst.h: In function ‘ppc_inst_len’:
> ./arch/powerpc/include/asm/inst.h:103:10: error: implicit declaration of
> function ‘ppc_inst_prefixed’ [-Werror=implicit-function-declaration]
> return (ppc_inst_prefixed(x)) ? 8 : 4;
> ^
>
> Christophe
>
> >
> > v4 is based on feedback from Nick Piggins, Christophe Leroy and Daniel Axtens.
> > The major changes:
> > - Move xmon breakpoints from data section to text section
> > - Introduce a data type for instructions on powerpc
> >
> > v3 is based on feedback from Christophe Leroy. The major changes:
> > - Completely replacing store_inst() with patch_instruction() in
> > xmon
> > - Improve implementation of mread_instr() to not use mread().
> > - Base the series on top of
> > https://patchwork.ozlabs.org/patch/1232619/ as this will effect
> > kprobes.
> > - Some renaming and simplification of conditionals.
> >
> > v2 incorporates feedback from Daniel Axtens and and Balamuruhan
> > S. The major changes are:
> > - Squashing together all commits about SRR1 bits
> > - Squashing all commits for supporting prefixed load stores
> > - Changing abbreviated references to sufx/prfx -> suffix/prefix
> > - Introducing macros for returning the length of an instruction
> > - Removing sign extension flag from pstd/pld in sstep.c
> > - Dropping patch "powerpc/fault: Use analyse_instr() to check for
> > store with updates to sp" from the series, it did not really fit
> > with prefixed enablement in the first place and as reported by Greg
> > Kurz did not work correctly.
> >
> >
> > Alistair Popple (1):
> > powerpc: Enable Prefixed Instructions
> >
> > Jordan Niethe (20):
> > powerpc/xmon: Remove store_inst() for patch_instruction()
> > powerpc/xmon: Move out-of-line instructions to text section
> > powerpc: Change calling convention for create_branch() et. al.
> > powerpc: Use a macro for creating instructions from u32s
> > powerpc: Use a function for getting the instruction op code
> > powerpc: Use an accessor for instructions
> > powerpc: Use a function for byte swapping instructions
> > powerpc: Introduce functions for instruction equality
> > powerpc: Use a datatype for instructions
> > powerpc: Use a function for reading instructions
> > powerpc: Define and use __get_user_instr{,inatomic}()
> > powerpc: Introduce a function for reporting instruction length
> > powerpc/xmon: Use a function for reading instructions
> > powerpc/xmon: Move insertion of breakpoint for xol'ing
> > powerpc: Make test_translate_branch() independent of instruction
> > length
> > powerpc: Define new SRR1 bits for a future ISA version
> > powerpc64: Add prefixed instructions to instruction data type
> > powerpc: Support prefixed instructions in alignment handler
> > powerpc sstep: Add support for prefixed load/stores
> > powerpc sstep: Add support for prefixed fixed-point arithmetic
> >
> > arch/powerpc/include/asm/code-patching.h | 37 +-
> > arch/powerpc/include/asm/inst.h | 106 ++++++
> > arch/powerpc/include/asm/kprobes.h | 2 +-
> > arch/powerpc/include/asm/reg.h | 7 +-
> > arch/powerpc/include/asm/sstep.h | 15 +-
> > arch/powerpc/include/asm/uaccess.h | 28 ++
> > arch/powerpc/include/asm/uprobes.h | 7 +-
> > arch/powerpc/kernel/align.c | 13 +-
> > arch/powerpc/kernel/epapr_paravirt.c | 5 +-
> > arch/powerpc/kernel/hw_breakpoint.c | 5 +-
> > arch/powerpc/kernel/jump_label.c | 5 +-
> > arch/powerpc/kernel/kgdb.c | 9 +-
> > arch/powerpc/kernel/kprobes.c | 24 +-
> > arch/powerpc/kernel/mce_power.c | 5 +-
> > arch/powerpc/kernel/module_64.c | 3 +-
> > arch/powerpc/kernel/optprobes.c | 91 +++--
> > arch/powerpc/kernel/optprobes_head.S | 3 +
> > arch/powerpc/kernel/security.c | 9 +-
> > arch/powerpc/kernel/setup_32.c | 4 +-
> > arch/powerpc/kernel/trace/ftrace.c | 190 ++++++----
> > arch/powerpc/kernel/traps.c | 20 +-
> > arch/powerpc/kernel/uprobes.c | 3 +-
> > arch/powerpc/kernel/vecemu.c | 20 +-
> > arch/powerpc/kvm/book3s_hv_nested.c | 2 +-
> > arch/powerpc/kvm/book3s_hv_rm_mmu.c | 2 +-
> > arch/powerpc/kvm/emulate_loadstore.c | 2 +-
> > arch/powerpc/lib/code-patching.c | 289 +++++++-------
> > arch/powerpc/lib/feature-fixups.c | 69 ++--
> > arch/powerpc/lib/sstep.c | 455 ++++++++++++++++-------
> > arch/powerpc/lib/test_emulate_step.c | 56 +--
> > arch/powerpc/perf/core-book3s.c | 4 +-
> > arch/powerpc/xmon/Makefile | 2 +-
> > arch/powerpc/xmon/xmon.c | 94 +++--
> > arch/powerpc/xmon/xmon_bpts.S | 10 +
> > arch/powerpc/xmon/xmon_bpts.h | 8 +
> > 35 files changed, 1042 insertions(+), 562 deletions(-)
> > create mode 100644 arch/powerpc/include/asm/inst.h
> > create mode 100644 arch/powerpc/xmon/xmon_bpts.S
> > create mode 100644 arch/powerpc/xmon/xmon_bpts.h
> >
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 18/21] powerpc64: Add prefixed instructions to instruction data type
2020-04-06 8:09 ` [PATCH v5 18/21] powerpc64: Add prefixed instructions to instruction data type Jordan Niethe
2020-04-06 9:52 ` Alistair Popple
2020-04-06 11:04 ` kbuild test robot
@ 2020-04-13 12:04 ` Balamuruhan S
2020-04-15 4:40 ` Jordan Niethe
2 siblings, 1 reply; 71+ messages in thread
From: Balamuruhan S @ 2020-04-13 12:04 UTC (permalink / raw)
To: Jordan Niethe, linuxppc-dev; +Cc: alistair, npiggin, dja
On Mon, 2020-04-06 at 18:09 +1000, Jordan Niethe wrote:
> 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>
> ---
> v4: New to series
> v5: - Distinguish normal instructions from prefixed instructions with a
> 0xff marker for the suffix.
> - __patch_instruction() using std for prefixed instructions
> ---
> arch/powerpc/include/asm/inst.h | 71 ++++++++++++++++++++++++++--
> arch/powerpc/include/asm/kprobes.h | 2 +-
> arch/powerpc/include/asm/uaccess.h | 31 ++++++++++--
> arch/powerpc/include/asm/uprobes.h | 2 +-
> arch/powerpc/kernel/optprobes.c | 42 ++++++++--------
> arch/powerpc/kernel/optprobes_head.S | 3 ++
> arch/powerpc/kernel/trace/ftrace.c | 26 +++++++++-
> arch/powerpc/lib/code-patching.c | 19 +++++---
> arch/powerpc/lib/feature-fixups.c | 5 +-
> arch/powerpc/lib/sstep.c | 4 +-
> arch/powerpc/xmon/xmon.c | 6 +--
> arch/powerpc/xmon/xmon_bpts.S | 4 +-
> 12 files changed, 171 insertions(+), 44 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/inst.h
> b/arch/powerpc/include/asm/inst.h
> index 70b37a35a91a..7e23e7146c66 100644
> --- a/arch/powerpc/include/asm/inst.h
> +++ b/arch/powerpc/include/asm/inst.h
> @@ -8,23 +8,67 @@
>
> struct ppc_inst {
> u32 val;
> +#ifdef __powerpc64__
> + u32 suffix;
> +#endif /* __powerpc64__ */
> } __packed;
>
> -#define ppc_inst(x) ((struct ppc_inst){ .val = x })
> +static inline int ppc_inst_opcode(struct ppc_inst x)
> +{
> + return x.val >> 26;
why don't we wrap here and in `ppc_inst_opcode()` in patch 9 using
`ppc_inst_val()` ?
> +}
>
> static inline u32 ppc_inst_val(struct ppc_inst x)
There is another same definition below for the same function in
#else part of __powerpc64__ ifdef.
> {
> return x.val;
> }
>
> -static inline bool ppc_inst_len(struct ppc_inst x)
> +#ifdef __powerpc64__
> +#define ppc_inst(x) ((struct ppc_inst){ .val = (x), .suffix = 0xff })
> +
> +#define ppc_inst_prefix(x, y) ((struct ppc_inst){ .val = (x), .suffix = (y)
> })
> +
> +static inline u32 ppc_inst_suffix(struct ppc_inst x)
> {
> - return sizeof(struct ppc_inst);
> + return x.suffix;
> }
>
> -static inline int ppc_inst_opcode(struct ppc_inst x)
> +static inline bool ppc_inst_prefixed(struct ppc_inst x) {
> + return ((ppc_inst_val(x) >> 26) == 1) && ppc_inst_suffix(x) != 0xff;
> +}
> +
> +static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
> {
> - return x.val >> 26;
> + return ppc_inst_prefix(swab32(ppc_inst_val(x)),
> + swab32(ppc_inst_suffix(x)));
> +}
> +
> +static inline struct ppc_inst ppc_inst_read(const struct ppc_inst *ptr)
> +{
> + u32 val, suffix = 0xff;
> + val = *(u32 *)ptr;
> + if ((val >> 26) == 1)
> + suffix = *((u32 *)ptr + 1);
> + return ppc_inst_prefix(val, suffix);
> +}
> +
> +static inline void ppc_inst_write(struct ppc_inst *ptr, struct ppc_inst x)
> +{
> + if (ppc_inst_prefixed(x)) {
> + *(u32 *)ptr = x.val;
> + *((u32 *)ptr + 1) = x.suffix;
> + } else {
> + *(u32 *)ptr = x.val;
can we wrap here as well with `ppc_inst_val()` and `ppc_inst_suffix()` ?
> + }
> +}
> +
> +#else
> +
> +#define ppc_inst(x) ((struct ppc_inst){ .val = x })
> +
> +static inline bool ppc_inst_prefixed(ppc_inst x)
> +{
> + return 0;
Is it return !!0 or return false ?
> }
>
> static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
> @@ -32,14 +76,31 @@ static inline struct ppc_inst ppc_inst_swab(struct
> ppc_inst x)
> return ppc_inst(swab32(ppc_inst_val(x)));
> }
>
> +static inline u32 ppc_inst_val(struct ppc_inst x)
[...] duplicate definition that is defined outside __powerpc64__ above.
> +{
> + return x.val;
> +}
> +
> static inline struct ppc_inst ppc_inst_read(const struct ppc_inst *ptr)
> {
> return *ptr;
> }
>
> +static inline void ppc_inst_write(struct ppc_inst *ptr, struct ppc_inst x)
> +{
> + *ptr = x;
> +}
> +
> +#endif /* __powerpc64__ */
> +
> static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
> {
> return !memcmp(&x, &y, sizeof(struct ppc_inst));
> }
>
> +static inline int ppc_inst_len(struct ppc_inst x)
> +{
> + return (ppc_inst_prefixed(x)) ? 8 : 4;
> +}
> +
> #endif /* _ASM_INST_H */
> diff --git a/arch/powerpc/include/asm/kprobes.h
> b/arch/powerpc/include/asm/kprobes.h
> index 66b3f2983b22..4fc0e15e23a5 100644
> --- a/arch/powerpc/include/asm/kprobes.h
> +++ b/arch/powerpc/include/asm/kprobes.h
> @@ -43,7 +43,7 @@ extern kprobe_opcode_t optprobe_template_ret[];
> extern kprobe_opcode_t optprobe_template_end[];
>
> /* Fixed instruction size for powerpc */
> -#define MAX_INSN_SIZE 1
> +#define MAX_INSN_SIZE 2
> #define MAX_OPTIMIZED_LENGTH sizeof(kprobe_opcode_t) /* 4 bytes */
> #define MAX_OPTINSN_SIZE (optprobe_template_end -
> optprobe_template_entry)
> #define RELATIVEJUMP_SIZE sizeof(kprobe_opcode_t) /* 4 bytes */
> diff --git a/arch/powerpc/include/asm/uaccess.h
> b/arch/powerpc/include/asm/uaccess.h
> index c0a35e4586a5..5a3f486ddf02 100644
> --- a/arch/powerpc/include/asm/uaccess.h
> +++ b/arch/powerpc/include/asm/uaccess.h
> @@ -105,11 +105,34 @@ 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)))
>
> -#define __get_user_instr(x, ptr) \
> - __get_user_nocheck((x).val, (u32 *)(ptr), sizeof(u32), true)
> +#define __get_user_instr(x, ptr) \
> +({ \
> + long __gui_ret = 0; \
> + unsigned int prefix, suffix; \
> + __gui_ret = __get_user(prefix, (unsigned int __user *)ptr);
> \
> + if (!__gui_ret && (prefix >> 26) == 1) { \
> + __gui_ret = __get_user(suffix, (unsigned int __user *)ptr + 1);
> \
> + (x) = ppc_inst_prefix(prefix, suffix); \
> + } else { \
> + (x) = ppc_inst(prefix); \
> + } \
> + __gui_ret; \
> +})
> +
> +#define __get_user_instr_inatomic(x, ptr) \
> +({ \
> + long __gui_ret = 0; \
> + unsigned int prefix, suffix; \
> + __gui_ret = __get_user_inatomic(prefix, (unsigned int __user *)ptr);
> \
> + if (!__gui_ret && (prefix >> 26) == 1) { \
> + __gui_ret = __get_user_inatomic(suffix, (unsigned int __user
> *)ptr + 1); \
> + (x) = ppc_inst_prefix(prefix, suffix); \
> + } else { \
> + (x) = ppc_inst(prefix); \
> + } \
> + __gui_ret; \
> +})
>
> -#define __get_user_instr_inatomic(x, ptr) \
> - __get_user_nosleep((x).val, (u32 *)(ptr), sizeof(u32))
> extern long __put_user_bad(void);
>
> /*
> diff --git a/arch/powerpc/include/asm/uprobes.h
> b/arch/powerpc/include/asm/uprobes.h
> index 7e3b329ba2d3..5bf65f5d44a9 100644
> --- a/arch/powerpc/include/asm/uprobes.h
> +++ b/arch/powerpc/include/asm/uprobes.h
> @@ -15,7 +15,7 @@
>
> typedef ppc_opcode_t uprobe_opcode_t;
>
> -#define MAX_UINSN_BYTES 4
> +#define MAX_UINSN_BYTES 8
> #define UPROBE_XOL_SLOT_BYTES (MAX_UINSN_BYTES)
>
> /* The following alias is needed for reference from arch-agnostic code */
> diff --git a/arch/powerpc/kernel/optprobes.c
> b/arch/powerpc/kernel/optprobes.c
> index 684640b8fa2e..689daf430161 100644
> --- a/arch/powerpc/kernel/optprobes.c
> +++ b/arch/powerpc/kernel/optprobes.c
> @@ -159,38 +159,38 @@ void patch_imm32_load_insns(unsigned int val,
> kprobe_opcode_t *addr)
>
> /*
> * Generate instructions to load provided immediate 64-bit value
> - * to register 'r3' and patch these instructions at 'addr'.
> + * to register 'reg' and patch these instructions at 'addr'.
> */
> -void patch_imm64_load_insns(unsigned long val, kprobe_opcode_t *addr)
> +void patch_imm64_load_insns(unsigned long val, int reg, kprobe_opcode_t
> *addr)
> {
> - /* lis r3,(op)@highest */
> - patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ADDIS |
> ___PPC_RT(3) |
> + /* lis reg,(op)@highest */
> + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ADDIS |
> ___PPC_RT(reg) |
> ((val >> 48) & 0xffff)));
> addr++;
>
> - /* ori r3,r3,(op)@higher */
> - patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI |
> ___PPC_RA(3) |
> - ___PPC_RS(3) | ((val >> 32) & 0xffff)));
> + /* ori reg,reg,(op)@higher */
> + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI |
> ___PPC_RA(reg) |
> + ___PPC_RS(reg) | ((val >> 32) & 0xffff)));
> addr++;
>
> - /* rldicr r3,r3,32,31 */
> - patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_RLDICR |
> ___PPC_RA(3) |
> - ___PPC_RS(3) | __PPC_SH64(32) | __PPC_ME64(31)));
> + /* rldicr reg,reg,32,31 */
> + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_RLDICR |
> ___PPC_RA(reg) |
> + ___PPC_RS(reg) | __PPC_SH64(32) | __PPC_ME64(31)));
> addr++;
>
> - /* oris r3,r3,(op)@h */
> - patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORIS |
> ___PPC_RA(3) |
> - ___PPC_RS(3) | ((val >> 16) & 0xffff)));
> + /* oris reg,reg,(op)@h */
> + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORIS |
> ___PPC_RA(reg) |
> + ___PPC_RS(reg) | ((val >> 16) & 0xffff)));
> addr++;
>
> - /* ori r3,r3,(op)@l */
> - patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI |
> ___PPC_RA(3) |
> - ___PPC_RS(3) | (val & 0xffff)));
> + /* ori reg,reg,(op)@l */
> + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI |
> ___PPC_RA(reg) |
> + ___PPC_RS(reg) | (val & 0xffff)));
> }
>
> int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe
> *p)
> {
> - struct ppc_inst branch_op_callback, branch_emulate_step;
> + struct ppc_inst branch_op_callback, branch_emulate_step, temp;
> kprobe_opcode_t *op_callback_addr, *emulate_step_addr, *buff;
> long b_offset;
> unsigned long nip, size;
> @@ -240,7 +240,7 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe
> *op, struct kprobe *p)
> * Fixup the template with instructions to:
> * 1. load the address of the actual probepoint
> */
> - patch_imm64_load_insns((unsigned long)op, buff + TMPL_OP_IDX);
> + patch_imm64_load_insns((unsigned long)op, 3, buff + TMPL_OP_IDX);
>
> /*
> * 2. branch to optimized_callback() and emulate_step()
> @@ -271,7 +271,11 @@ int arch_prepare_optimized_kprobe(struct
> optimized_kprobe *op, struct kprobe *p)
> /*
> * 3. load instruction to be emulated into relevant register, and
> */
> - patch_imm32_load_insns(*p->ainsn.insn, buff + TMPL_INSN_IDX);
> + temp = ppc_inst_read((struct ppc_inst *)p->ainsn.insn);
> + patch_imm64_load_insns(ppc_inst_val(temp) |
> + ((u64)ppc_inst_suffix(temp) << 32),
did we check building for ppc32 ?
I doubt we might hit build failure as `ppc_inst_suffix()` macro is not defined.
> + 4,
> + buff + TMPL_INSN_IDX);
>
> /*
> * 4. branch back from trampoline
> diff --git a/arch/powerpc/kernel/optprobes_head.S
> b/arch/powerpc/kernel/optprobes_head.S
> index cf383520843f..ff8ba4d3824d 100644
> --- a/arch/powerpc/kernel/optprobes_head.S
> +++ b/arch/powerpc/kernel/optprobes_head.S
> @@ -94,6 +94,9 @@ optprobe_template_insn:
> /* 2, Pass instruction to be emulated in r4 */
> nop
> nop
> + nop
> + nop
> + nop
>
> .global optprobe_template_call_emulate
> optprobe_template_call_emulate:
> diff --git a/arch/powerpc/kernel/trace/ftrace.c
> b/arch/powerpc/kernel/trace/ftrace.c
> index e78742613b36..16041a5c86d5 100644
> --- a/arch/powerpc/kernel/trace/ftrace.c
> +++ b/arch/powerpc/kernel/trace/ftrace.c
> @@ -41,11 +41,35 @@
> #define NUM_FTRACE_TRAMPS 8
> static unsigned long ftrace_tramps[NUM_FTRACE_TRAMPS];
>
> +#ifdef __powerpc64__
> static long
> probe_kernel_read_inst(struct ppc_inst *inst, const void *src)
> {
> - return probe_kernel_read((void *)inst, src, MCOUNT_INSN_SIZE);
> + u32 val, suffix = 0;
don't we need to initialize suffix with 0xff ?
> + long err;
> +
> + err = probe_kernel_read((void *)&val,
> + src, sizeof(val));
> + if (err)
> + return err;
> +
> + if ((val >> 26) == 1)
> + err = probe_kernel_read((void *)&suffix,
> + src + 4, MCOUNT_INSN_SIZE);
> + if (err)
> + return err;
> +
> + *inst = ppc_inst_prefix(val, suffix);
> +
> + return 0;
> }
> +#else
> +static long
> +probe_kernel_read_inst(struct ppc_inst *inst, const void *src)
> +{
> + return probe_kernel_read((void *)inst, src, MCOUNT_INSN_SIZE)
> +}
> +#endif
>
> static struct ppc_inst
> ftrace_call_replace(unsigned long ip, unsigned long addr, int link)
> diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-
> patching.c
> index c329ad657302..b4007e03d8fa 100644
> --- a/arch/powerpc/lib/code-patching.c
> +++ b/arch/powerpc/lib/code-patching.c
> @@ -24,12 +24,19 @@ static int __patch_instruction(struct ppc_inst
> *exec_addr, struct ppc_inst instr
> {
> int err = 0;
>
> - __put_user_asm(ppc_inst_val(instr), patch_addr, err, "stw");
> - if (err)
> - return err;
> -
> - asm ("dcbst 0, %0; sync; icbi 0,%1; sync; isync" :: "r" (patch_addr),
> - "r" (exec_addr));
> + if (!ppc_inst_prefixed(instr)) {
> + __put_user_asm(ppc_inst_val(instr), patch_addr, err, "stw");
> + if (err)
> + return err;
> + asm ("dcbst 0, %0; sync; icbi 0,%1; sync; isync" :: "r"
> (patch_addr),
> + "r"
> (exec_addr));
> + } else {
> + __put_user_asm((u64)ppc_inst_suffix(instr) << 32 |
> ppc_inst_val(instr), patch_addr, err, "std");
> + if (err)
> + return err;
> + asm ("dcbst 0, %0; sync; icbi 0,%1; sync; isync" :: "r"
> (patch_addr),
> + "r"
> (exec_addr));
> + }
can we keep these 2 lines out of conditions as it remains to be the same ?
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/feature-fixups.c b/arch/powerpc/lib/feature-
> fixups.c
> index f00dd13b1c3c..5519cec83cc8 100644
> --- a/arch/powerpc/lib/feature-fixups.c
> +++ b/arch/powerpc/lib/feature-fixups.c
> @@ -84,12 +84,13 @@ static int patch_feature_section(unsigned long value,
> struct fixup_entry *fcur)
> src = alt_start;
> dest = start;
>
> - for (; src < alt_end; src++, dest++) {
> + for (; src < alt_end; src = (void *)src +
> ppc_inst_len(ppc_inst_read(src)),
> + (dest = (void *)dest + ppc_inst_len(ppc_inst_read(dest)))) {
> if (patch_alt_instruction(src, dest, alt_start, alt_end))
> return 1;
> }
>
> - for (; dest < end; dest++)
> + for (; dest < end; dest = (void *)dest +
> ppc_inst_len(ppc_inst(PPC_INST_NOP)))
> raw_patch_instruction(dest, ppc_inst(PPC_INST_NOP));
>
> return 0;
> diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
> index 52ddd3122dc8..8b285bf11218 100644
> --- a/arch/powerpc/lib/sstep.c
> +++ b/arch/powerpc/lib/sstep.c
> @@ -1169,10 +1169,12 @@ int analyse_instr(struct instruction_op *op, const
> struct pt_regs *regs,
> unsigned long int imm;
> unsigned long int val, val2;
> unsigned int mb, me, sh;
> - unsigned int word;
> + unsigned int word, suffix;
> long ival;
>
> word = ppc_inst_val(instr);
> + suffix = ppc_inst_suffix(instr);
same here, I doubt it might break for ppc32.
-- Bala
> +
> op->type = COMPUTE;
>
> opcode = word >> 26;
> diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
> index 6f3bcdcfc9c7..b704aebb099a 100644
> --- a/arch/powerpc/xmon/xmon.c
> +++ b/arch/powerpc/xmon/xmon.c
> @@ -761,8 +761,8 @@ static int xmon_bpt(struct pt_regs *regs)
>
> /* Are we at the trap at bp->instr[1] for some bp? */
> bp = in_breakpoint_table(regs->nip, &offset);
> - if (bp != NULL && offset == 4) {
> - regs->nip = bp->address + 4;
> + if (bp != NULL && (offset == 4 || offset == 8)) {
> + regs->nip = bp->address + offset;
> atomic_dec(&bp->ref_count);
> return 1;
> }
> @@ -863,7 +863,7 @@ static struct bpt *in_breakpoint_table(unsigned long nip,
> unsigned long *offp)
> if (off >= sizeof(bpt_table))
> return NULL;
> *offp = off % BPT_SIZE;
> - if (*offp != 0 && *offp != 4)
> + if (*offp != 0 && *offp != 4 && *offp != 8)
> return NULL;
> return bpts + (off / BPT_SIZE);
> }
> diff --git a/arch/powerpc/xmon/xmon_bpts.S b/arch/powerpc/xmon/xmon_bpts.S
> index ebb2dbc70ca8..09058eb6abbd 100644
> --- a/arch/powerpc/xmon/xmon_bpts.S
> +++ b/arch/powerpc/xmon/xmon_bpts.S
> @@ -3,6 +3,8 @@
> #include <asm/asm-compat.h>
> #include "xmon_bpts.h"
>
> +/* Prefixed instructions can not cross 64 byte boundaries */
> +.align 6
> .global bpt_table
> bpt_table:
> - .space NBPTS * 8
> + .space NBPTS * 16
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 18/21] powerpc64: Add prefixed instructions to instruction data type
2020-04-13 12:04 ` Balamuruhan S
@ 2020-04-15 4:40 ` Jordan Niethe
2020-04-15 8:14 ` Balamuruhan S
0 siblings, 1 reply; 71+ messages in thread
From: Jordan Niethe @ 2020-04-15 4:40 UTC (permalink / raw)
To: Balamuruhan S
Cc: Alistair Popple, linuxppc-dev, Nicholas Piggin, Daniel Axtens
On Mon, Apr 13, 2020 at 10:04 PM Balamuruhan S <bala24@linux.ibm.com> wrote:
>
> On Mon, 2020-04-06 at 18:09 +1000, Jordan Niethe wrote:
> > 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>
> > ---
> > v4: New to series
> > v5: - Distinguish normal instructions from prefixed instructions with a
> > 0xff marker for the suffix.
> > - __patch_instruction() using std for prefixed instructions
> > ---
> > arch/powerpc/include/asm/inst.h | 71 ++++++++++++++++++++++++++--
> > arch/powerpc/include/asm/kprobes.h | 2 +-
> > arch/powerpc/include/asm/uaccess.h | 31 ++++++++++--
> > arch/powerpc/include/asm/uprobes.h | 2 +-
> > arch/powerpc/kernel/optprobes.c | 42 ++++++++--------
> > arch/powerpc/kernel/optprobes_head.S | 3 ++
> > arch/powerpc/kernel/trace/ftrace.c | 26 +++++++++-
> > arch/powerpc/lib/code-patching.c | 19 +++++---
> > arch/powerpc/lib/feature-fixups.c | 5 +-
> > arch/powerpc/lib/sstep.c | 4 +-
> > arch/powerpc/xmon/xmon.c | 6 +--
> > arch/powerpc/xmon/xmon_bpts.S | 4 +-
> > 12 files changed, 171 insertions(+), 44 deletions(-)
> >
> > diff --git a/arch/powerpc/include/asm/inst.h
> > b/arch/powerpc/include/asm/inst.h
> > index 70b37a35a91a..7e23e7146c66 100644
> > --- a/arch/powerpc/include/asm/inst.h
> > +++ b/arch/powerpc/include/asm/inst.h
> > @@ -8,23 +8,67 @@
> >
> > struct ppc_inst {
> > u32 val;
> > +#ifdef __powerpc64__
> > + u32 suffix;
> > +#endif /* __powerpc64__ */
> > } __packed;
> >
> > -#define ppc_inst(x) ((struct ppc_inst){ .val = x })
> > +static inline int ppc_inst_opcode(struct ppc_inst x)
> > +{
> > + return x.val >> 26;
>
>
> why don't we wrap here and in `ppc_inst_opcode()` in patch 9 using
> `ppc_inst_val()` ?
Will do.
>
>
> > +}
> >
> > static inline u32 ppc_inst_val(struct ppc_inst x)
>
>
> There is another same definition below for the same function in
> #else part of __powerpc64__ ifdef.
Thanks
>
>
> > {
> > return x.val;
> > }
> >
> > -static inline bool ppc_inst_len(struct ppc_inst x)
> > +#ifdef __powerpc64__
> > +#define ppc_inst(x) ((struct ppc_inst){ .val = (x), .suffix = 0xff })
> > +
> > +#define ppc_inst_prefix(x, y) ((struct ppc_inst){ .val = (x), .suffix = (y)
> > })
> > +
> > +static inline u32 ppc_inst_suffix(struct ppc_inst x)
> > {
> > - return sizeof(struct ppc_inst);
> > + return x.suffix;
> > }
> >
> > -static inline int ppc_inst_opcode(struct ppc_inst x)
> > +static inline bool ppc_inst_prefixed(struct ppc_inst x) {
> > + return ((ppc_inst_val(x) >> 26) == 1) && ppc_inst_suffix(x) != 0xff;
> > +}
> > +
> > +static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
> > {
> > - return x.val >> 26;
> > + return ppc_inst_prefix(swab32(ppc_inst_val(x)),
> > + swab32(ppc_inst_suffix(x)));
> > +}
> > +
> > +static inline struct ppc_inst ppc_inst_read(const struct ppc_inst *ptr)
> > +{
> > + u32 val, suffix = 0xff;
> > + val = *(u32 *)ptr;
> > + if ((val >> 26) == 1)
> > + suffix = *((u32 *)ptr + 1);
> > + return ppc_inst_prefix(val, suffix);
> > +}
> > +
> > +static inline void ppc_inst_write(struct ppc_inst *ptr, struct ppc_inst x)
> > +{
> > + if (ppc_inst_prefixed(x)) {
> > + *(u32 *)ptr = x.val;
> > + *((u32 *)ptr + 1) = x.suffix;
> > + } else {
> > + *(u32 *)ptr = x.val;
>
>
> can we wrap here as well with `ppc_inst_val()` and `ppc_inst_suffix()` ?
Yeah no reason not too.
>
>
> > + }
> > +}
> > +
> > +#else
> > +
> > +#define ppc_inst(x) ((struct ppc_inst){ .val = x })
> > +
> > +static inline bool ppc_inst_prefixed(ppc_inst x)
> > +{
> > + return 0;
>
>
> Is it return !!0 or return false ?
False probably will make more sense.
>
>
> > }
> >
> > static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
> > @@ -32,14 +76,31 @@ static inline struct ppc_inst ppc_inst_swab(struct
> > ppc_inst x)
> > return ppc_inst(swab32(ppc_inst_val(x)));
> > }
> >
> > +static inline u32 ppc_inst_val(struct ppc_inst x)
>
>
> [...] duplicate definition that is defined outside __powerpc64__ above.
>
>
> > +{
> > + return x.val;
> > +}
> > +
> > static inline struct ppc_inst ppc_inst_read(const struct ppc_inst *ptr)
> > {
> > return *ptr;
> > }
> >
> > +static inline void ppc_inst_write(struct ppc_inst *ptr, struct ppc_inst x)
> > +{
> > + *ptr = x;
> > +}
> > +
> > +#endif /* __powerpc64__ */
> > +
> > static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
> > {
> > return !memcmp(&x, &y, sizeof(struct ppc_inst));
> > }
> >
> > +static inline int ppc_inst_len(struct ppc_inst x)
> > +{
> > + return (ppc_inst_prefixed(x)) ? 8 : 4;
> > +}
> > +
> > #endif /* _ASM_INST_H */
> > diff --git a/arch/powerpc/include/asm/kprobes.h
> > b/arch/powerpc/include/asm/kprobes.h
> > index 66b3f2983b22..4fc0e15e23a5 100644
> > --- a/arch/powerpc/include/asm/kprobes.h
> > +++ b/arch/powerpc/include/asm/kprobes.h
> > @@ -43,7 +43,7 @@ extern kprobe_opcode_t optprobe_template_ret[];
> > extern kprobe_opcode_t optprobe_template_end[];
> >
> > /* Fixed instruction size for powerpc */
> > -#define MAX_INSN_SIZE 1
> > +#define MAX_INSN_SIZE 2
> > #define MAX_OPTIMIZED_LENGTH sizeof(kprobe_opcode_t) /* 4 bytes */
> > #define MAX_OPTINSN_SIZE (optprobe_template_end -
> > optprobe_template_entry)
> > #define RELATIVEJUMP_SIZE sizeof(kprobe_opcode_t) /* 4 bytes */
> > diff --git a/arch/powerpc/include/asm/uaccess.h
> > b/arch/powerpc/include/asm/uaccess.h
> > index c0a35e4586a5..5a3f486ddf02 100644
> > --- a/arch/powerpc/include/asm/uaccess.h
> > +++ b/arch/powerpc/include/asm/uaccess.h
> > @@ -105,11 +105,34 @@ 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)))
> >
> > -#define __get_user_instr(x, ptr) \
> > - __get_user_nocheck((x).val, (u32 *)(ptr), sizeof(u32), true)
> > +#define __get_user_instr(x, ptr) \
> > +({ \
> > + long __gui_ret = 0; \
> > + unsigned int prefix, suffix; \
> > + __gui_ret = __get_user(prefix, (unsigned int __user *)ptr);
> > \
> > + if (!__gui_ret && (prefix >> 26) == 1) { \
> > + __gui_ret = __get_user(suffix, (unsigned int __user *)ptr + 1);
> > \
> > + (x) = ppc_inst_prefix(prefix, suffix); \
> > + } else { \
> > + (x) = ppc_inst(prefix); \
> > + } \
> > + __gui_ret; \
> > +})
> > +
> > +#define __get_user_instr_inatomic(x, ptr) \
> > +({ \
> > + long __gui_ret = 0; \
> > + unsigned int prefix, suffix; \
> > + __gui_ret = __get_user_inatomic(prefix, (unsigned int __user *)ptr);
> > \
> > + if (!__gui_ret && (prefix >> 26) == 1) { \
> > + __gui_ret = __get_user_inatomic(suffix, (unsigned int __user
> > *)ptr + 1); \
> > + (x) = ppc_inst_prefix(prefix, suffix); \
> > + } else { \
> > + (x) = ppc_inst(prefix); \
> > + } \
> > + __gui_ret; \
> > +})
> >
> > -#define __get_user_instr_inatomic(x, ptr) \
> > - __get_user_nosleep((x).val, (u32 *)(ptr), sizeof(u32))
> > extern long __put_user_bad(void);
> >
> > /*
> > diff --git a/arch/powerpc/include/asm/uprobes.h
> > b/arch/powerpc/include/asm/uprobes.h
> > index 7e3b329ba2d3..5bf65f5d44a9 100644
> > --- a/arch/powerpc/include/asm/uprobes.h
> > +++ b/arch/powerpc/include/asm/uprobes.h
> > @@ -15,7 +15,7 @@
> >
> > typedef ppc_opcode_t uprobe_opcode_t;
> >
> > -#define MAX_UINSN_BYTES 4
> > +#define MAX_UINSN_BYTES 8
> > #define UPROBE_XOL_SLOT_BYTES (MAX_UINSN_BYTES)
> >
> > /* The following alias is needed for reference from arch-agnostic code */
> > diff --git a/arch/powerpc/kernel/optprobes.c
> > b/arch/powerpc/kernel/optprobes.c
> > index 684640b8fa2e..689daf430161 100644
> > --- a/arch/powerpc/kernel/optprobes.c
> > +++ b/arch/powerpc/kernel/optprobes.c
> > @@ -159,38 +159,38 @@ void patch_imm32_load_insns(unsigned int val,
> > kprobe_opcode_t *addr)
> >
> > /*
> > * Generate instructions to load provided immediate 64-bit value
> > - * to register 'r3' and patch these instructions at 'addr'.
> > + * to register 'reg' and patch these instructions at 'addr'.
> > */
> > -void patch_imm64_load_insns(unsigned long val, kprobe_opcode_t *addr)
> > +void patch_imm64_load_insns(unsigned long val, int reg, kprobe_opcode_t
> > *addr)
> > {
> > - /* lis r3,(op)@highest */
> > - patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ADDIS |
> > ___PPC_RT(3) |
> > + /* lis reg,(op)@highest */
> > + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ADDIS |
> > ___PPC_RT(reg) |
> > ((val >> 48) & 0xffff)));
> > addr++;
> >
> > - /* ori r3,r3,(op)@higher */
> > - patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI |
> > ___PPC_RA(3) |
> > - ___PPC_RS(3) | ((val >> 32) & 0xffff)));
> > + /* ori reg,reg,(op)@higher */
> > + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI |
> > ___PPC_RA(reg) |
> > + ___PPC_RS(reg) | ((val >> 32) & 0xffff)));
> > addr++;
> >
> > - /* rldicr r3,r3,32,31 */
> > - patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_RLDICR |
> > ___PPC_RA(3) |
> > - ___PPC_RS(3) | __PPC_SH64(32) | __PPC_ME64(31)));
> > + /* rldicr reg,reg,32,31 */
> > + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_RLDICR |
> > ___PPC_RA(reg) |
> > + ___PPC_RS(reg) | __PPC_SH64(32) | __PPC_ME64(31)));
> > addr++;
> >
> > - /* oris r3,r3,(op)@h */
> > - patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORIS |
> > ___PPC_RA(3) |
> > - ___PPC_RS(3) | ((val >> 16) & 0xffff)));
> > + /* oris reg,reg,(op)@h */
> > + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORIS |
> > ___PPC_RA(reg) |
> > + ___PPC_RS(reg) | ((val >> 16) & 0xffff)));
> > addr++;
> >
> > - /* ori r3,r3,(op)@l */
> > - patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI |
> > ___PPC_RA(3) |
> > - ___PPC_RS(3) | (val & 0xffff)));
> > + /* ori reg,reg,(op)@l */
> > + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI |
> > ___PPC_RA(reg) |
> > + ___PPC_RS(reg) | (val & 0xffff)));
> > }
> >
> > int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe
> > *p)
> > {
> > - struct ppc_inst branch_op_callback, branch_emulate_step;
> > + struct ppc_inst branch_op_callback, branch_emulate_step, temp;
> > kprobe_opcode_t *op_callback_addr, *emulate_step_addr, *buff;
> > long b_offset;
> > unsigned long nip, size;
> > @@ -240,7 +240,7 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe
> > *op, struct kprobe *p)
> > * Fixup the template with instructions to:
> > * 1. load the address of the actual probepoint
> > */
> > - patch_imm64_load_insns((unsigned long)op, buff + TMPL_OP_IDX);
> > + patch_imm64_load_insns((unsigned long)op, 3, buff + TMPL_OP_IDX);
> >
> > /*
> > * 2. branch to optimized_callback() and emulate_step()
> > @@ -271,7 +271,11 @@ int arch_prepare_optimized_kprobe(struct
> > optimized_kprobe *op, struct kprobe *p)
> > /*
> > * 3. load instruction to be emulated into relevant register, and
> > */
> > - patch_imm32_load_insns(*p->ainsn.insn, buff + TMPL_INSN_IDX);
> > + temp = ppc_inst_read((struct ppc_inst *)p->ainsn.insn);
> > + patch_imm64_load_insns(ppc_inst_val(temp) |
> > + ((u64)ppc_inst_suffix(temp) << 32),
>
>
> did we check building for ppc32 ?
Yeah I need to do so.
>
> I doubt we might hit build failure as `ppc_inst_suffix()` macro is not defined.
>
>
> > + 4,
> > + buff + TMPL_INSN_IDX);
> >
> > /*
> > * 4. branch back from trampoline
> > diff --git a/arch/powerpc/kernel/optprobes_head.S
> > b/arch/powerpc/kernel/optprobes_head.S
> > index cf383520843f..ff8ba4d3824d 100644
> > --- a/arch/powerpc/kernel/optprobes_head.S
> > +++ b/arch/powerpc/kernel/optprobes_head.S
> > @@ -94,6 +94,9 @@ optprobe_template_insn:
> > /* 2, Pass instruction to be emulated in r4 */
> > nop
> > nop
> > + nop
> > + nop
> > + nop
> >
> > .global optprobe_template_call_emulate
> > optprobe_template_call_emulate:
> > diff --git a/arch/powerpc/kernel/trace/ftrace.c
> > b/arch/powerpc/kernel/trace/ftrace.c
> > index e78742613b36..16041a5c86d5 100644
> > --- a/arch/powerpc/kernel/trace/ftrace.c
> > +++ b/arch/powerpc/kernel/trace/ftrace.c
> > @@ -41,11 +41,35 @@
> > #define NUM_FTRACE_TRAMPS 8
> > static unsigned long ftrace_tramps[NUM_FTRACE_TRAMPS];
> >
> > +#ifdef __powerpc64__
> > static long
> > probe_kernel_read_inst(struct ppc_inst *inst, const void *src)
> > {
> > - return probe_kernel_read((void *)inst, src, MCOUNT_INSN_SIZE);
> > + u32 val, suffix = 0;
>
>
> don't we need to initialize suffix with 0xff ?
Good catch, that was causing problems.
>
>
> > + long err;
> > +
> > + err = probe_kernel_read((void *)&val,
> > + src, sizeof(val));
> > + if (err)
> > + return err;
> > +
> > + if ((val >> 26) == 1)
> > + err = probe_kernel_read((void *)&suffix,
> > + src + 4, MCOUNT_INSN_SIZE);
> > + if (err)
> > + return err;
> > +
> > + *inst = ppc_inst_prefix(val, suffix);
> > +
> > + return 0;
> > }
> > +#else
> > +static long
> > +probe_kernel_read_inst(struct ppc_inst *inst, const void *src)
> > +{
> > + return probe_kernel_read((void *)inst, src, MCOUNT_INSN_SIZE)
> > +}
> > +#endif
> >
> > static struct ppc_inst
> > ftrace_call_replace(unsigned long ip, unsigned long addr, int link)
> > diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-
> > patching.c
> > index c329ad657302..b4007e03d8fa 100644
> > --- a/arch/powerpc/lib/code-patching.c
> > +++ b/arch/powerpc/lib/code-patching.c
> > @@ -24,12 +24,19 @@ static int __patch_instruction(struct ppc_inst
> > *exec_addr, struct ppc_inst instr
> > {
> > int err = 0;
> >
> > - __put_user_asm(ppc_inst_val(instr), patch_addr, err, "stw");
> > - if (err)
> > - return err;
> > -
> > - asm ("dcbst 0, %0; sync; icbi 0,%1; sync; isync" :: "r" (patch_addr),
> > - "r" (exec_addr));
> > + if (!ppc_inst_prefixed(instr)) {
> > + __put_user_asm(ppc_inst_val(instr), patch_addr, err, "stw");
> > + if (err)
> > + return err;
> > + asm ("dcbst 0, %0; sync; icbi 0,%1; sync; isync" :: "r"
> > (patch_addr),
> > + "r"
> > (exec_addr));
> > + } else {
> > + __put_user_asm((u64)ppc_inst_suffix(instr) << 32 |
> > ppc_inst_val(instr), patch_addr, err, "std");
> > + if (err)
> > + return err;
> > + asm ("dcbst 0, %0; sync; icbi 0,%1; sync; isync" :: "r"
> > (patch_addr),
> > + "r"
> > (exec_addr));
> > + }
>
>
> can we keep these 2 lines out of conditions as it remains to be the same ?
True.
>
> 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/feature-fixups.c b/arch/powerpc/lib/feature-
> > fixups.c
> > index f00dd13b1c3c..5519cec83cc8 100644
> > --- a/arch/powerpc/lib/feature-fixups.c
> > +++ b/arch/powerpc/lib/feature-fixups.c
> > @@ -84,12 +84,13 @@ static int patch_feature_section(unsigned long value,
> > struct fixup_entry *fcur)
> > src = alt_start;
> > dest = start;
> >
> > - for (; src < alt_end; src++, dest++) {
> > + for (; src < alt_end; src = (void *)src +
> > ppc_inst_len(ppc_inst_read(src)),
> > + (dest = (void *)dest + ppc_inst_len(ppc_inst_read(dest)))) {
> > if (patch_alt_instruction(src, dest, alt_start, alt_end))
> > return 1;
> > }
> >
> > - for (; dest < end; dest++)
> > + for (; dest < end; dest = (void *)dest +
> > ppc_inst_len(ppc_inst(PPC_INST_NOP)))
> > raw_patch_instruction(dest, ppc_inst(PPC_INST_NOP));
> >
> > return 0;
> > diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
> > index 52ddd3122dc8..8b285bf11218 100644
> > --- a/arch/powerpc/lib/sstep.c
> > +++ b/arch/powerpc/lib/sstep.c
> > @@ -1169,10 +1169,12 @@ int analyse_instr(struct instruction_op *op, const
> > struct pt_regs *regs,
> > unsigned long int imm;
> > unsigned long int val, val2;
> > unsigned int mb, me, sh;
> > - unsigned int word;
> > + unsigned int word, suffix;
> > long ival;
> >
> > word = ppc_inst_val(instr);
> > + suffix = ppc_inst_suffix(instr);
>
>
> same here, I doubt it might break for ppc32.
Yeah I need to work on ppc32.
>
>
> -- Bala
> > +
> > op->type = COMPUTE;
> >
> > opcode = word >> 26;
> > diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
> > index 6f3bcdcfc9c7..b704aebb099a 100644
> > --- a/arch/powerpc/xmon/xmon.c
> > +++ b/arch/powerpc/xmon/xmon.c
> > @@ -761,8 +761,8 @@ static int xmon_bpt(struct pt_regs *regs)
> >
> > /* Are we at the trap at bp->instr[1] for some bp? */
> > bp = in_breakpoint_table(regs->nip, &offset);
> > - if (bp != NULL && offset == 4) {
> > - regs->nip = bp->address + 4;
> > + if (bp != NULL && (offset == 4 || offset == 8)) {
> > + regs->nip = bp->address + offset;
> > atomic_dec(&bp->ref_count);
> > return 1;
> > }
> > @@ -863,7 +863,7 @@ static struct bpt *in_breakpoint_table(unsigned long nip,
> > unsigned long *offp)
> > if (off >= sizeof(bpt_table))
> > return NULL;
> > *offp = off % BPT_SIZE;
> > - if (*offp != 0 && *offp != 4)
> > + if (*offp != 0 && *offp != 4 && *offp != 8)
> > return NULL;
> > return bpts + (off / BPT_SIZE);
> > }
> > diff --git a/arch/powerpc/xmon/xmon_bpts.S b/arch/powerpc/xmon/xmon_bpts.S
> > index ebb2dbc70ca8..09058eb6abbd 100644
> > --- a/arch/powerpc/xmon/xmon_bpts.S
> > +++ b/arch/powerpc/xmon/xmon_bpts.S
> > @@ -3,6 +3,8 @@
> > #include <asm/asm-compat.h>
> > #include "xmon_bpts.h"
> >
> > +/* Prefixed instructions can not cross 64 byte boundaries */
> > +.align 6
> > .global bpt_table
> > bpt_table:
> > - .space NBPTS * 8
> > + .space NBPTS * 16
>
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH v5 18/21] powerpc64: Add prefixed instructions to instruction data type
2020-04-15 4:40 ` Jordan Niethe
@ 2020-04-15 8:14 ` Balamuruhan S
0 siblings, 0 replies; 71+ messages in thread
From: Balamuruhan S @ 2020-04-15 8:14 UTC (permalink / raw)
To: Jordan Niethe
Cc: Alistair Popple, linuxppc-dev, Nicholas Piggin, Daniel Axtens
On Wed, 2020-04-15 at 14:40 +1000, Jordan Niethe wrote:
> On Mon, Apr 13, 2020 at 10:04 PM Balamuruhan S <bala24@linux.ibm.com> wrote:
> > On Mon, 2020-04-06 at 18:09 +1000, Jordan Niethe wrote:
> > > 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>
> > > ---
> > > v4: New to series
> > > v5: - Distinguish normal instructions from prefixed instructions with a
> > > 0xff marker for the suffix.
> > > - __patch_instruction() using std for prefixed instructions
> > > ---
> > > arch/powerpc/include/asm/inst.h | 71 ++++++++++++++++++++++++++--
> > > arch/powerpc/include/asm/kprobes.h | 2 +-
> > > arch/powerpc/include/asm/uaccess.h | 31 ++++++++++--
> > > arch/powerpc/include/asm/uprobes.h | 2 +-
> > > arch/powerpc/kernel/optprobes.c | 42 ++++++++--------
> > > arch/powerpc/kernel/optprobes_head.S | 3 ++
> > > arch/powerpc/kernel/trace/ftrace.c | 26 +++++++++-
> > > arch/powerpc/lib/code-patching.c | 19 +++++---
> > > arch/powerpc/lib/feature-fixups.c | 5 +-
> > > arch/powerpc/lib/sstep.c | 4 +-
> > > arch/powerpc/xmon/xmon.c | 6 +--
> > > arch/powerpc/xmon/xmon_bpts.S | 4 +-
> > > 12 files changed, 171 insertions(+), 44 deletions(-)
> > >
> > > diff --git a/arch/powerpc/include/asm/inst.h
> > > b/arch/powerpc/include/asm/inst.h
> > > index 70b37a35a91a..7e23e7146c66 100644
> > > --- a/arch/powerpc/include/asm/inst.h
> > > +++ b/arch/powerpc/include/asm/inst.h
> > > @@ -8,23 +8,67 @@
> > >
> > > struct ppc_inst {
> > > u32 val;
> > > +#ifdef __powerpc64__
> > > + u32 suffix;
> > > +#endif /* __powerpc64__ */
> > > } __packed;
> > >
> > > -#define ppc_inst(x) ((struct ppc_inst){ .val = x })
> > > +static inline int ppc_inst_opcode(struct ppc_inst x)
> > > +{
> > > + return x.val >> 26;
> >
> > why don't we wrap here and in `ppc_inst_opcode()` in patch 9 using
> > `ppc_inst_val()` ?
> Will do.
> >
> > > +}
> > >
> > > static inline u32 ppc_inst_val(struct ppc_inst x)
> >
> > There is another same definition below for the same function in
> > #else part of __powerpc64__ ifdef.
> Thanks
> >
> > > {
> > > return x.val;
> > > }
> > >
> > > -static inline bool ppc_inst_len(struct ppc_inst x)
> > > +#ifdef __powerpc64__
> > > +#define ppc_inst(x) ((struct ppc_inst){ .val = (x), .suffix = 0xff })
> > > +
> > > +#define ppc_inst_prefix(x, y) ((struct ppc_inst){ .val = (x), .suffix =
> > > (y)
> > > })
> > > +
> > > +static inline u32 ppc_inst_suffix(struct ppc_inst x)
> > > {
> > > - return sizeof(struct ppc_inst);
> > > + return x.suffix;
> > > }
> > >
> > > -static inline int ppc_inst_opcode(struct ppc_inst x)
> > > +static inline bool ppc_inst_prefixed(struct ppc_inst x) {
> > > + return ((ppc_inst_val(x) >> 26) == 1) && ppc_inst_suffix(x) !=
> > > 0xff;
> > > +}
> > > +
> > > +static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
> > > {
> > > - return x.val >> 26;
> > > + return ppc_inst_prefix(swab32(ppc_inst_val(x)),
> > > + swab32(ppc_inst_suffix(x)));
> > > +}
> > > +
> > > +static inline struct ppc_inst ppc_inst_read(const struct ppc_inst *ptr)
> > > +{
> > > + u32 val, suffix = 0xff;
> > > + val = *(u32 *)ptr;
> > > + if ((val >> 26) == 1)
> > > + suffix = *((u32 *)ptr + 1);
> > > + return ppc_inst_prefix(val, suffix);
> > > +}
> > > +
> > > +static inline void ppc_inst_write(struct ppc_inst *ptr, struct ppc_inst
> > > x)
> > > +{
> > > + if (ppc_inst_prefixed(x)) {
> > > + *(u32 *)ptr = x.val;
> > > + *((u32 *)ptr + 1) = x.suffix;
> > > + } else {
> > > + *(u32 *)ptr = x.val;
> >
> > can we wrap here as well with `ppc_inst_val()` and `ppc_inst_suffix()` ?
> Yeah no reason not too.
> >
> > > + }
> > > +}
> > > +
> > > +#else
> > > +
> > > +#define ppc_inst(x) ((struct ppc_inst){ .val = x })
> > > +
> > > +static inline bool ppc_inst_prefixed(ppc_inst x)
> > > +{
> > > + return 0;
> >
> > Is it return !!0 or return false ?
> False probably will make more sense.
> >
> > > }
> > >
> > > static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
> > > @@ -32,14 +76,31 @@ static inline struct ppc_inst ppc_inst_swab(struct
> > > ppc_inst x)
> > > return ppc_inst(swab32(ppc_inst_val(x)));
> > > }
> > >
> > > +static inline u32 ppc_inst_val(struct ppc_inst x)
> >
> > [...] duplicate definition that is defined outside __powerpc64__ above.
> >
> >
> > > +{
> > > + return x.val;
> > > +}
> > > +
> > > static inline struct ppc_inst ppc_inst_read(const struct ppc_inst *ptr)
> > > {
> > > return *ptr;
> > > }
> > >
> > > +static inline void ppc_inst_write(struct ppc_inst *ptr, struct ppc_inst
> > > x)
> > > +{
> > > + *ptr = x;
> > > +}
> > > +
> > > +#endif /* __powerpc64__ */
> > > +
> > > static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
> > > {
> > > return !memcmp(&x, &y, sizeof(struct ppc_inst));
> > > }
> > >
> > > +static inline int ppc_inst_len(struct ppc_inst x)
> > > +{
> > > + return (ppc_inst_prefixed(x)) ? 8 : 4;
> > > +}
> > > +
> > > #endif /* _ASM_INST_H */
> > > diff --git a/arch/powerpc/include/asm/kprobes.h
> > > b/arch/powerpc/include/asm/kprobes.h
> > > index 66b3f2983b22..4fc0e15e23a5 100644
> > > --- a/arch/powerpc/include/asm/kprobes.h
> > > +++ b/arch/powerpc/include/asm/kprobes.h
> > > @@ -43,7 +43,7 @@ extern kprobe_opcode_t optprobe_template_ret[];
> > > extern kprobe_opcode_t optprobe_template_end[];
> > >
> > > /* Fixed instruction size for powerpc */
> > > -#define MAX_INSN_SIZE 1
> > > +#define MAX_INSN_SIZE 2
> > > #define MAX_OPTIMIZED_LENGTH sizeof(kprobe_opcode_t) /* 4 bytes */
> > > #define MAX_OPTINSN_SIZE (optprobe_template_end -
> > > optprobe_template_entry)
> > > #define RELATIVEJUMP_SIZE sizeof(kprobe_opcode_t) /* 4 bytes */
> > > diff --git a/arch/powerpc/include/asm/uaccess.h
> > > b/arch/powerpc/include/asm/uaccess.h
> > > index c0a35e4586a5..5a3f486ddf02 100644
> > > --- a/arch/powerpc/include/asm/uaccess.h
> > > +++ b/arch/powerpc/include/asm/uaccess.h
> > > @@ -105,11 +105,34 @@ 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)))
> > >
> > > -#define __get_user_instr(x, ptr) \
> > > - __get_user_nocheck((x).val, (u32 *)(ptr), sizeof(u32), true)
> > > +#define __get_user_instr(x, ptr) \
> > > +({ \
> > > + long __gui_ret = 0; \
> > > + unsigned int prefix, suffix; \
> > > + __gui_ret = __get_user(prefix, (unsigned int __user *)ptr);
> > > \
> > > + if (!__gui_ret && (prefix >> 26) == 1) { \
> > > + __gui_ret = __get_user(suffix, (unsigned int __user *)ptr +
> > > 1);
> > > \
> > > + (x) = ppc_inst_prefix(prefix, suffix); \
> > > + } else { \
> > > + (x) = ppc_inst(prefix); \
> > > + } \
> > > + __gui_ret; \
> > > +})
> > > +
> > > +#define __get_user_instr_inatomic(x, ptr) \
> > > +({ \
> > > + long __gui_ret = 0; \
> > > + unsigned int prefix, suffix; \
> > > + __gui_ret = __get_user_inatomic(prefix, (unsigned int __user
> > > *)ptr);
> > > \
> > > + if (!__gui_ret && (prefix >> 26) == 1) { \
> > > + __gui_ret = __get_user_inatomic(suffix, (unsigned int
> > > __user
> > > *)ptr + 1); \
> > > + (x) = ppc_inst_prefix(prefix, suffix); \
> > > + } else { \
> > > + (x) = ppc_inst(prefix); \
> > > + } \
> > > + __gui_ret; \
> > > +})
> > >
> > > -#define __get_user_instr_inatomic(x, ptr) \
> > > - __get_user_nosleep((x).val, (u32 *)(ptr), sizeof(u32))
> > > extern long __put_user_bad(void);
> > >
> > > /*
> > > diff --git a/arch/powerpc/include/asm/uprobes.h
> > > b/arch/powerpc/include/asm/uprobes.h
> > > index 7e3b329ba2d3..5bf65f5d44a9 100644
> > > --- a/arch/powerpc/include/asm/uprobes.h
> > > +++ b/arch/powerpc/include/asm/uprobes.h
> > > @@ -15,7 +15,7 @@
> > >
> > > typedef ppc_opcode_t uprobe_opcode_t;
> > >
> > > -#define MAX_UINSN_BYTES 4
> > > +#define MAX_UINSN_BYTES 8
> > > #define UPROBE_XOL_SLOT_BYTES (MAX_UINSN_BYTES)
> > >
> > > /* The following alias is needed for reference from arch-agnostic code
> > > */
> > > diff --git a/arch/powerpc/kernel/optprobes.c
> > > b/arch/powerpc/kernel/optprobes.c
> > > index 684640b8fa2e..689daf430161 100644
> > > --- a/arch/powerpc/kernel/optprobes.c
> > > +++ b/arch/powerpc/kernel/optprobes.c
> > > @@ -159,38 +159,38 @@ void patch_imm32_load_insns(unsigned int val,
> > > kprobe_opcode_t *addr)
> > >
> > > /*
> > > * Generate instructions to load provided immediate 64-bit value
> > > - * to register 'r3' and patch these instructions at 'addr'.
> > > + * to register 'reg' and patch these instructions at 'addr'.
> > > */
> > > -void patch_imm64_load_insns(unsigned long val, kprobe_opcode_t *addr)
> > > +void patch_imm64_load_insns(unsigned long val, int reg, kprobe_opcode_t
> > > *addr)
> > > {
> > > - /* lis r3,(op)@highest */
> > > - patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ADDIS
> > > |
> > > ___PPC_RT(3) |
> > > + /* lis reg,(op)@highest */
> > > + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ADDIS
> > > |
> > > ___PPC_RT(reg) |
> > > ((val >> 48) & 0xffff)));
> > > addr++;
> > >
> > > - /* ori r3,r3,(op)@higher */
> > > - patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI |
> > > ___PPC_RA(3) |
> > > - ___PPC_RS(3) | ((val >> 32) & 0xffff)));
> > > + /* ori reg,reg,(op)@higher */
> > > + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI |
> > > ___PPC_RA(reg) |
> > > + ___PPC_RS(reg) | ((val >> 32) & 0xffff)));
> > > addr++;
> > >
> > > - /* rldicr r3,r3,32,31 */
> > > - patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_RLDICR
> > > |
> > > ___PPC_RA(3) |
> > > - ___PPC_RS(3) | __PPC_SH64(32) | __PPC_ME64(31)));
> > > + /* rldicr reg,reg,32,31 */
> > > + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_RLDICR
> > > |
> > > ___PPC_RA(reg) |
> > > + ___PPC_RS(reg) | __PPC_SH64(32) |
> > > __PPC_ME64(31)));
> > > addr++;
> > >
> > > - /* oris r3,r3,(op)@h */
> > > - patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORIS |
> > > ___PPC_RA(3) |
> > > - ___PPC_RS(3) | ((val >> 16) & 0xffff)));
> > > + /* oris reg,reg,(op)@h */
> > > + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORIS |
> > > ___PPC_RA(reg) |
> > > + ___PPC_RS(reg) | ((val >> 16) & 0xffff)));
> > > addr++;
> > >
> > > - /* ori r3,r3,(op)@l */
> > > - patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI |
> > > ___PPC_RA(3) |
> > > - ___PPC_RS(3) | (val & 0xffff)));
> > > + /* ori reg,reg,(op)@l */
> > > + patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI |
> > > ___PPC_RA(reg) |
> > > + ___PPC_RS(reg) | (val & 0xffff)));
> > > }
> > >
> > > int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct
> > > kprobe
> > > *p)
> > > {
> > > - struct ppc_inst branch_op_callback, branch_emulate_step;
> > > + struct ppc_inst branch_op_callback, branch_emulate_step, temp;
> > > kprobe_opcode_t *op_callback_addr, *emulate_step_addr, *buff;
> > > long b_offset;
> > > unsigned long nip, size;
> > > @@ -240,7 +240,7 @@ int arch_prepare_optimized_kprobe(struct
> > > optimized_kprobe
> > > *op, struct kprobe *p)
> > > * Fixup the template with instructions to:
> > > * 1. load the address of the actual probepoint
> > > */
> > > - patch_imm64_load_insns((unsigned long)op, buff + TMPL_OP_IDX);
> > > + patch_imm64_load_insns((unsigned long)op, 3, buff + TMPL_OP_IDX);
> > >
> > > /*
> > > * 2. branch to optimized_callback() and emulate_step()
> > > @@ -271,7 +271,11 @@ int arch_prepare_optimized_kprobe(struct
> > > optimized_kprobe *op, struct kprobe *p)
> > > /*
> > > * 3. load instruction to be emulated into relevant register, and
> > > */
> > > - patch_imm32_load_insns(*p->ainsn.insn, buff + TMPL_INSN_IDX);
> > > + temp = ppc_inst_read((struct ppc_inst *)p->ainsn.insn);
> > > + patch_imm64_load_insns(ppc_inst_val(temp) |
> > > + ((u64)ppc_inst_suffix(temp) << 32),
> >
> > did we check building for ppc32 ?
> Yeah I need to do so.
> > I doubt we might hit build failure as `ppc_inst_suffix()` macro is not
> > defined.
> >
> >
> > > + 4,
> > > + buff + TMPL_INSN_IDX);
> > >
> > > /*
> > > * 4. branch back from trampoline
> > > diff --git a/arch/powerpc/kernel/optprobes_head.S
> > > b/arch/powerpc/kernel/optprobes_head.S
> > > index cf383520843f..ff8ba4d3824d 100644
> > > --- a/arch/powerpc/kernel/optprobes_head.S
> > > +++ b/arch/powerpc/kernel/optprobes_head.S
> > > @@ -94,6 +94,9 @@ optprobe_template_insn:
> > > /* 2, Pass instruction to be emulated in r4 */
> > > nop
> > > nop
> > > + nop
> > > + nop
> > > + nop
> > >
> > > .global optprobe_template_call_emulate
> > > optprobe_template_call_emulate:
> > > diff --git a/arch/powerpc/kernel/trace/ftrace.c
> > > b/arch/powerpc/kernel/trace/ftrace.c
> > > index e78742613b36..16041a5c86d5 100644
> > > --- a/arch/powerpc/kernel/trace/ftrace.c
> > > +++ b/arch/powerpc/kernel/trace/ftrace.c
> > > @@ -41,11 +41,35 @@
> > > #define NUM_FTRACE_TRAMPS 8
> > > static unsigned long ftrace_tramps[NUM_FTRACE_TRAMPS];
> > >
> > > +#ifdef __powerpc64__
> > > static long
> > > probe_kernel_read_inst(struct ppc_inst *inst, const void *src)
> > > {
> > > - return probe_kernel_read((void *)inst, src, MCOUNT_INSN_SIZE);
> > > + u32 val, suffix = 0;
> >
> > don't we need to initialize suffix with 0xff ?
> Good catch, that was causing problems.
Also we can do,
if ((val >> 26) == 1)
{
err = probe_kernel_read((void *)&suffix,
src + 4, MCOUNT_INSN_SIZE);
if (err)
return err;
*inst = ppc_inst_prefix(val, suffix);
}
else
*inst = ppc_inst(val);
to explicitly show a non-prefixed instruction and we do not have to
initialize suffix to 0xff, as ppc_inst() would take care.
-- Bala
> >
> > > + long err;
> > > +
> > > + err = probe_kernel_read((void *)&val,
> > > + src, sizeof(val));
> > > + if (err)
> > > + return err;
> > > +
> > > + if ((val >> 26) == 1)
> > > + err = probe_kernel_read((void *)&suffix,
> > > + src + 4, MCOUNT_INSN_SIZE);
> > > + if (err)
> > > + return err;
> > > +
> > > + *inst = ppc_inst_prefix(val, suffix);
> > > +
> > > + return 0;
> > > }
> > > +#else
> > > +static long
> > > +probe_kernel_read_inst(struct ppc_inst *inst, const void *src)
> > > +{
> > > + return probe_kernel_read((void *)inst, src, MCOUNT_INSN_SIZE)
> > > +}
> > > +#endif
> > >
> > > static struct ppc_inst
> > > ftrace_call_replace(unsigned long ip, unsigned long addr, int link)
> > > diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-
> > > patching.c
> > > index c329ad657302..b4007e03d8fa 100644
> > > --- a/arch/powerpc/lib/code-patching.c
> > > +++ b/arch/powerpc/lib/code-patching.c
> > > @@ -24,12 +24,19 @@ static int __patch_instruction(struct ppc_inst
> > > *exec_addr, struct ppc_inst instr
> > > {
> > > int err = 0;
> > >
> > > - __put_user_asm(ppc_inst_val(instr), patch_addr, err, "stw");
> > > - if (err)
> > > - return err;
> > > -
> > > - asm ("dcbst 0, %0; sync; icbi 0,%1; sync; isync" :: "r"
> > > (patch_addr),
> > > - "r"
> > > (exec_addr));
> > > + if (!ppc_inst_prefixed(instr)) {
> > > + __put_user_asm(ppc_inst_val(instr), patch_addr, err,
> > > "stw");
> > > + if (err)
> > > + return err;
> > > + asm ("dcbst 0, %0; sync; icbi 0,%1; sync; isync" :: "r"
> > > (patch_addr),
> > > + "r"
> > > (exec_addr));
> > > + } else {
> > > + __put_user_asm((u64)ppc_inst_suffix(instr) << 32 |
> > > ppc_inst_val(instr), patch_addr, err, "std");
> > > + if (err)
> > > + return err;
> > > + asm ("dcbst 0, %0; sync; icbi 0,%1; sync; isync" :: "r"
> > > (patch_addr),
> > > + "r"
> > > (exec_addr));
> > > + }
> >
> > can we keep these 2 lines out of conditions as it remains to be the same ?
> True.
> > 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/feature-fixups.c
> > > b/arch/powerpc/lib/feature-
> > > fixups.c
> > > index f00dd13b1c3c..5519cec83cc8 100644
> > > --- a/arch/powerpc/lib/feature-fixups.c
> > > +++ b/arch/powerpc/lib/feature-fixups.c
> > > @@ -84,12 +84,13 @@ static int patch_feature_section(unsigned long value,
> > > struct fixup_entry *fcur)
> > > src = alt_start;
> > > dest = start;
> > >
> > > - for (; src < alt_end; src++, dest++) {
> > > + for (; src < alt_end; src = (void *)src +
> > > ppc_inst_len(ppc_inst_read(src)),
> > > + (dest = (void *)dest + ppc_inst_len(ppc_inst_read(dest)))) {
> > > if (patch_alt_instruction(src, dest, alt_start, alt_end))
> > > return 1;
> > > }
> > >
> > > - for (; dest < end; dest++)
> > > + for (; dest < end; dest = (void *)dest +
> > > ppc_inst_len(ppc_inst(PPC_INST_NOP)))
> > > raw_patch_instruction(dest, ppc_inst(PPC_INST_NOP));
> > >
> > > return 0;
> > > diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
> > > index 52ddd3122dc8..8b285bf11218 100644
> > > --- a/arch/powerpc/lib/sstep.c
> > > +++ b/arch/powerpc/lib/sstep.c
> > > @@ -1169,10 +1169,12 @@ int analyse_instr(struct instruction_op *op,
> > > const
> > > struct pt_regs *regs,
> > > unsigned long int imm;
> > > unsigned long int val, val2;
> > > unsigned int mb, me, sh;
> > > - unsigned int word;
> > > + unsigned int word, suffix;
> > > long ival;
> > >
> > > word = ppc_inst_val(instr);
> > > + suffix = ppc_inst_suffix(instr);
> >
> > same here, I doubt it might break for ppc32.
> Yeah I need to work on ppc32.
> >
> > -- Bala
> > > +
> > > op->type = COMPUTE;
> > >
> > > opcode = word >> 26;
> > > diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
> > > index 6f3bcdcfc9c7..b704aebb099a 100644
> > > --- a/arch/powerpc/xmon/xmon.c
> > > +++ b/arch/powerpc/xmon/xmon.c
> > > @@ -761,8 +761,8 @@ static int xmon_bpt(struct pt_regs *regs)
> > >
> > > /* Are we at the trap at bp->instr[1] for some bp? */
> > > bp = in_breakpoint_table(regs->nip, &offset);
> > > - if (bp != NULL && offset == 4) {
> > > - regs->nip = bp->address + 4;
> > > + if (bp != NULL && (offset == 4 || offset == 8)) {
> > > + regs->nip = bp->address + offset;
> > > atomic_dec(&bp->ref_count);
> > > return 1;
> > > }
> > > @@ -863,7 +863,7 @@ static struct bpt *in_breakpoint_table(unsigned long
> > > nip,
> > > unsigned long *offp)
> > > if (off >= sizeof(bpt_table))
> > > return NULL;
> > > *offp = off % BPT_SIZE;
> > > - if (*offp != 0 && *offp != 4)
> > > + if (*offp != 0 && *offp != 4 && *offp != 8)
> > > return NULL;
> > > return bpts + (off / BPT_SIZE);
> > > }
> > > diff --git a/arch/powerpc/xmon/xmon_bpts.S
> > > b/arch/powerpc/xmon/xmon_bpts.S
> > > index ebb2dbc70ca8..09058eb6abbd 100644
> > > --- a/arch/powerpc/xmon/xmon_bpts.S
> > > +++ b/arch/powerpc/xmon/xmon_bpts.S
> > > @@ -3,6 +3,8 @@
> > > #include <asm/asm-compat.h>
> > > #include "xmon_bpts.h"
> > >
> > > +/* Prefixed instructions can not cross 64 byte boundaries */
> > > +.align 6
> > > .global bpt_table
> > > bpt_table:
> > > - .space NBPTS * 8
> > > + .space NBPTS * 16
^ permalink raw reply [flat|nested] 71+ messages in thread
end of thread, other threads:[~2020-04-15 8:17 UTC | newest]
Thread overview: 71+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-04-06 8:09 [PATCH v5 00/21] Initial Prefixed Instruction support Jordan Niethe
2020-04-06 8:09 ` [PATCH v5 01/21] powerpc/xmon: Remove store_inst() for patch_instruction() Jordan Niethe
2020-04-06 8:09 ` [PATCH v5 02/21] powerpc/xmon: Move out-of-line instructions to text section Jordan Niethe
2020-04-07 6:45 ` Balamuruhan S
2020-04-09 6:11 ` Christophe Leroy
2020-04-09 7:26 ` Jordan Niethe
2020-04-06 8:09 ` [PATCH v5 03/21] powerpc: Change calling convention for create_branch() et. al Jordan Niethe
2020-04-06 10:25 ` kbuild test robot
2020-04-06 10:25 ` kbuild test robot
2020-04-07 6:10 ` Balamuruhan S
2020-04-07 6:35 ` Jordan Niethe
2020-04-07 6:59 ` Balamuruhan S
2020-04-06 8:09 ` [PATCH v5 04/21] powerpc: Use a macro for creating instructions from u32s Jordan Niethe
2020-04-07 6:40 ` Balamuruhan S
2020-04-07 8:27 ` Jordan Niethe
2020-04-06 8:09 ` [PATCH v5 05/21] powerpc: Use a function for getting the instruction op code Jordan Niethe
2020-04-06 8:22 ` Christophe Leroy
2020-04-06 9:38 ` Jordan Niethe
2020-04-07 7:04 ` Balamuruhan S
2020-04-07 8:32 ` Jordan Niethe
2020-04-08 18:21 ` Segher Boessenkool
2020-04-09 4:48 ` Jordan Niethe
2020-04-06 8:09 ` [PATCH v5 06/21] powerpc: Use an accessor for instructions Jordan Niethe
2020-04-06 8:09 ` [PATCH v5 07/21] powerpc: Use a function for byte swapping instructions Jordan Niethe
2020-04-07 7:42 ` Balamuruhan S
2020-04-06 8:09 ` [PATCH v5 08/21] powerpc: Introduce functions for instruction equality Jordan Niethe
2020-04-07 7:37 ` Balamuruhan S
2020-04-06 8:09 ` [PATCH v5 09/21] powerpc: Use a datatype for instructions Jordan Niethe
2020-04-06 10:34 ` kbuild test robot
2020-04-06 10:34 ` kbuild test robot
2020-04-06 10:35 ` kbuild test robot
2020-04-06 10:35 ` kbuild test robot
2020-04-07 10:30 ` Balamuruhan S
2020-04-08 2:11 ` Jordan Niethe
2020-04-06 8:09 ` [PATCH v5 10/21] powerpc: Use a function for reading instructions Jordan Niethe
2020-04-07 10:42 ` Balamuruhan S
2020-04-06 8:09 ` [PATCH v5 11/21] powerpc: Define and use __get_user_instr{, inatomic}() Jordan Niethe
2020-04-07 10:48 ` Balamuruhan S
2020-04-08 2:13 ` Jordan Niethe
2020-04-06 8:09 ` [PATCH v5 12/21] powerpc: Introduce a function for reporting instruction length Jordan Niethe
2020-04-07 11:14 ` Balamuruhan S
2020-04-08 2:14 ` Jordan Niethe
2020-04-06 8:09 ` [PATCH v5 13/21] powerpc/xmon: Use a function for reading instructions Jordan Niethe
2020-04-07 11:30 ` Balamuruhan S
2020-04-08 2:18 ` Jordan Niethe
2020-04-09 5:04 ` Balamuruhan S
2020-04-09 5:14 ` Jordan Niethe
2020-04-06 8:09 ` [PATCH v5 14/21] powerpc/xmon: Move insertion of breakpoint for xol'ing Jordan Niethe
2020-04-06 8:09 ` [PATCH v5 15/21] powerpc: Make test_translate_branch() independent of instruction length Jordan Niethe
2020-04-06 8:09 ` [PATCH v5 16/21] powerpc: Enable Prefixed Instructions Jordan Niethe
2020-04-06 8:09 ` [PATCH v5 17/21] powerpc: Define new SRR1 bits for a future ISA version Jordan Niethe
2020-04-06 8:09 ` [PATCH v5 18/21] powerpc64: Add prefixed instructions to instruction data type Jordan Niethe
2020-04-06 9:52 ` Alistair Popple
2020-04-06 10:25 ` Christophe Leroy
2020-04-06 11:13 ` Jordan Niethe
2020-04-08 18:11 ` Segher Boessenkool
2020-04-08 18:43 ` Christophe Leroy
2020-04-06 10:42 ` Jordan Niethe
2020-04-07 1:39 ` Alistair Popple
2020-04-06 11:04 ` kbuild test robot
2020-04-06 11:04 ` kbuild test robot
2020-04-13 12:04 ` Balamuruhan S
2020-04-15 4:40 ` Jordan Niethe
2020-04-15 8:14 ` Balamuruhan S
2020-04-06 8:09 ` [PATCH v5 19/21] powerpc: Support prefixed instructions in alignment handler Jordan Niethe
2020-04-06 8:09 ` [PATCH v5 20/21] powerpc sstep: Add support for prefixed load/stores Jordan Niethe
2020-04-06 11:29 ` kbuild test robot
2020-04-06 11:29 ` kbuild test robot
2020-04-06 8:09 ` [PATCH v5 21/21] powerpc sstep: Add support for prefixed fixed-point arithmetic Jordan Niethe
2020-04-09 6:39 ` [PATCH v5 00/21] Initial Prefixed Instruction support Christophe Leroy
2020-04-09 7:28 ` Jordan Niethe
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.