All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v8 00/30] Initial Prefixed Instruction support
@ 2020-05-06  3:40 Jordan Niethe
  2020-05-06  3:40 ` [PATCH v8 01/30] powerpc/xmon: Remove store_inst() for patch_instruction() Jordan Niethe
                   ` (31 more replies)
  0 siblings, 32 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-06  3:40 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, 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.

v8 incorporates feedback from Alistair Popple and Balamuruhan Suriyakumar.
The major changes:
    - Fix some style issues
    - Fix __patch_instruction() on big endian
    - Reintroduce v3's forbidding breakpoints on second word of prefix
      instructions for kprobes and xmon. Missed this when changing to
      using a data type.
    - Use the data type in some places that were missed.

v7 fixes compilation issues for some configs reported by Alistair
Popple.

v6 is based on feedback from Balamuruhan Suriyakumar, Alistair Popple,
Christophe Leroy and Segher Boessenkool.
The major changes:
    - Use the instruction type in more places that had been missed before
    - Fix issues with ppc32
    - Introduce new self tests for code patching and feature fixups

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 (29):
  powerpc/xmon: Remove store_inst() for patch_instruction()
  powerpc/xmon: Move breakpoint instructions to own array
  powerpc/xmon: Move breakpoints to text section
  powerpc/xmon: Use bitwise calculations in_breakpoint_table()
  powerpc: Change calling convention for create_branch() et. al.
  powerpc: Use a macro for creating instructions from u32s
  powerpc: Use an accessor for instructions
  powerpc: Use a function for getting the instruction op code
  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: Add a probe_user_read_inst() function
  powerpc: Add a probe_kernel_read_inst() function
  powerpc/kprobes: Use patch_instruction()
  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
  powerpc: Add prefixed instructions to instruction data type
  powerpc: Test prefixed code patching
  powerpc: Test prefixed instructions in feature fixups
  powerpc/xmon: Don't allow breakpoints on suffixes
  powerpc/kprobes: Don't allow breakpoints on suffixes
  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           | 107 +++++
 arch/powerpc/include/asm/kprobes.h        |   2 +-
 arch/powerpc/include/asm/ppc-opcode.h     |   3 +
 arch/powerpc/include/asm/reg.h            |   7 +-
 arch/powerpc/include/asm/sstep.h          |  15 +-
 arch/powerpc/include/asm/uaccess.h        |  43 ++
 arch/powerpc/include/asm/uprobes.h        |   7 +-
 arch/powerpc/kernel/align.c               |  13 +-
 arch/powerpc/kernel/asm-offsets.c         |   8 +
 arch/powerpc/kernel/crash_dump.c          |   7 +-
 arch/powerpc/kernel/epapr_paravirt.c      |   7 +-
 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             |  37 +-
 arch/powerpc/kernel/mce_power.c           |   5 +-
 arch/powerpc/kernel/module_64.c           |   3 +-
 arch/powerpc/kernel/optprobes.c           | 102 +++--
 arch/powerpc/kernel/optprobes_head.S      |   3 +
 arch/powerpc/kernel/security.c            |  12 +-
 arch/powerpc/kernel/setup_32.c            |   8 +-
 arch/powerpc/kernel/trace/ftrace.c        | 168 ++++----
 arch/powerpc/kernel/traps.c               |  20 +-
 arch/powerpc/kernel/uprobes.c             |   5 +-
 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/Makefile                 |   2 +-
 arch/powerpc/lib/code-patching.c          | 319 +++++++++------
 arch/powerpc/lib/feature-fixups-test.S    |  69 ++++
 arch/powerpc/lib/feature-fixups.c         | 160 ++++++--
 arch/powerpc/lib/inst.c                   |  70 ++++
 arch/powerpc/lib/sstep.c                  | 459 +++++++++++++++-------
 arch/powerpc/lib/test_code-patching.S     |  20 +
 arch/powerpc/lib/test_emulate_step.c      |  56 +--
 arch/powerpc/mm/fault.c                   |  15 +-
 arch/powerpc/mm/nohash/8xx.c              |   5 +-
 arch/powerpc/perf/8xx-pmu.c               |   9 +-
 arch/powerpc/perf/core-book3s.c           |   4 +-
 arch/powerpc/platforms/86xx/mpc86xx_smp.c |   5 +-
 arch/powerpc/platforms/powermac/smp.c     |   5 +-
 arch/powerpc/xmon/Makefile                |   2 +-
 arch/powerpc/xmon/xmon.c                  | 122 ++++--
 arch/powerpc/xmon/xmon_bpts.S             |  11 +
 arch/powerpc/xmon/xmon_bpts.h             |  14 +
 47 files changed, 1409 insertions(+), 602 deletions(-)
 create mode 100644 arch/powerpc/include/asm/inst.h
 create mode 100644 arch/powerpc/lib/inst.c
 create mode 100644 arch/powerpc/lib/test_code-patching.S
 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] 81+ messages in thread

* [PATCH v8 01/30] powerpc/xmon: Remove store_inst() for patch_instruction()
  2020-05-06  3:40 [PATCH v8 00/30] Initial Prefixed Instruction support Jordan Niethe
@ 2020-05-06  3:40 ` Jordan Niethe
  2020-05-06  3:40 ` [PATCH v8 02/30] powerpc/xmon: Move breakpoint instructions to own array Jordan Niethe
                   ` (30 subsequent siblings)
  31 siblings, 0 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-06  3:40 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, 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 7af840c0fc93..f91ae2c9adbe 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -326,11 +326,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));
@@ -882,8 +877,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;
 		}
 	}
@@ -895,25 +889,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,
@@ -923,7 +918,6 @@ static void insert_bpts(void)
 			bp->enabled &= ~BP_TRAP;
 			continue;
 		}
-		store_inst((void *)bp->address);
 	}
 }
 
@@ -958,8 +952,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] 81+ messages in thread

* [PATCH v8 02/30] powerpc/xmon: Move breakpoint instructions to own array
  2020-05-06  3:40 [PATCH v8 00/30] Initial Prefixed Instruction support Jordan Niethe
  2020-05-06  3:40 ` [PATCH v8 01/30] powerpc/xmon: Remove store_inst() for patch_instruction() Jordan Niethe
@ 2020-05-06  3:40 ` Jordan Niethe
  2020-05-06  3:40 ` [PATCH v8 03/30] powerpc/xmon: Move breakpoints to text section Jordan Niethe
                   ` (29 subsequent siblings)
  31 siblings, 0 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-06  3:40 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, 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. A later patch will move this to 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.

Reviewed-by: Alistair Popple <alistair@popple.id.au>
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
v6: - Seperate moving to text section
---
 arch/powerpc/xmon/xmon.c | 21 ++++++++++++---------
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index f91ae2c9adbe..14c578e0383a 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -98,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;
@@ -117,6 +117,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))
+static unsigned int bpt_table[NBPTS * BPT_WORDS];
+
 /* Prototypes */
 static int cmds(struct pt_regs *);
 static int mread(unsigned long, void *, int);
@@ -854,15 +858,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)
@@ -877,7 +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;
-			patch_instruction(&bp->instr[1], bpinstr);
+			bp->instr = bpt_table + ((bp - bpts) * BPT_WORDS);
+			patch_instruction(bp->instr + 1, bpinstr);
 			return bp;
 		}
 	}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH v8 03/30] powerpc/xmon: Move breakpoints to text section
  2020-05-06  3:40 [PATCH v8 00/30] Initial Prefixed Instruction support Jordan Niethe
  2020-05-06  3:40 ` [PATCH v8 01/30] powerpc/xmon: Remove store_inst() for patch_instruction() Jordan Niethe
  2020-05-06  3:40 ` [PATCH v8 02/30] powerpc/xmon: Move breakpoint instructions to own array Jordan Niethe
@ 2020-05-06  3:40 ` Jordan Niethe
  2020-05-06  3:40 ` [PATCH v8 04/30] powerpc/xmon: Use bitwise calculations in_breakpoint_table() Jordan Niethe
                   ` (28 subsequent siblings)
  31 siblings, 0 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-06  3:40 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, Jordan Niethe, dja

The instructions for xmon's breakpoint are stored bpt_table[] which is in
the data section. This is problematic as the data section may be marked
as no execute. Move bpt_table[] to the text section.

Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v6: - New to series. Was part of the previous patch.
    - Make BPT_SIZE available in assembly
---
 arch/powerpc/kernel/asm-offsets.c |  8 ++++++++
 arch/powerpc/xmon/Makefile        |  2 +-
 arch/powerpc/xmon/xmon.c          |  6 +-----
 arch/powerpc/xmon/xmon_bpts.S     |  9 +++++++++
 arch/powerpc/xmon/xmon_bpts.h     | 14 ++++++++++++++
 5 files changed, 33 insertions(+), 6 deletions(-)
 create mode 100644 arch/powerpc/xmon/xmon_bpts.S
 create mode 100644 arch/powerpc/xmon/xmon_bpts.h

diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index fcf24a365fc0..9b9cde07e396 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -70,6 +70,10 @@
 #include <asm/fixmap.h>
 #endif
 
+#ifdef CONFIG_XMON
+#include "../xmon/xmon_bpts.h"
+#endif
+
 #define STACK_PT_REGS_OFFSET(sym, val)	\
 	DEFINE(sym, STACK_FRAME_OVERHEAD + offsetof(struct pt_regs, val))
 
@@ -795,5 +799,9 @@ int main(void)
 	DEFINE(VIRT_IMMR_BASE, (u64)__fix_to_virt(FIX_IMMR_BASE));
 #endif
 
+#ifdef CONFIG_XMON
+	DEFINE(BPT_SIZE, BPT_SIZE);
+#endif
+
 	return 0;
 }
diff --git a/arch/powerpc/xmon/Makefile b/arch/powerpc/xmon/Makefile
index 6f9cccea54f3..89c76ca35640 100644
--- a/arch/powerpc/xmon/Makefile
+++ b/arch/powerpc/xmon/Makefile
@@ -18,7 +18,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 14c578e0383a..4ecb7e73b017 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;
@@ -109,7 +110,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;
@@ -117,10 +117,6 @@ 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))
-static unsigned int bpt_table[NBPTS * BPT_WORDS];
-
 /* Prototypes */
 static int cmds(struct pt_regs *);
 static int mread(unsigned long, void *, int);
diff --git a/arch/powerpc/xmon/xmon_bpts.S b/arch/powerpc/xmon/xmon_bpts.S
new file mode 100644
index 000000000000..f3ad0ab50854
--- /dev/null
+++ b/arch/powerpc/xmon/xmon_bpts.S
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#include <asm/ppc_asm.h>
+#include <asm/asm-compat.h>
+#include <asm/asm-offsets.h>
+#include "xmon_bpts.h"
+
+.global bpt_table
+bpt_table:
+	.space NBPTS * BPT_SIZE
diff --git a/arch/powerpc/xmon/xmon_bpts.h b/arch/powerpc/xmon/xmon_bpts.h
new file mode 100644
index 000000000000..b7e94375db86
--- /dev/null
+++ b/arch/powerpc/xmon/xmon_bpts.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef XMON_BPTS_H
+#define XMON_BPTS_H
+
+#define NBPTS	256
+#ifndef __ASSEMBLY__
+#define BPT_SIZE	(sizeof(unsigned int) * 2)
+#define BPT_WORDS	(BPT_SIZE / sizeof(unsigned int))
+
+extern unsigned int bpt_table[NBPTS * BPT_WORDS];
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* XMON_BPTS_H */
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH v8 04/30] powerpc/xmon: Use bitwise calculations in_breakpoint_table()
  2020-05-06  3:40 [PATCH v8 00/30] Initial Prefixed Instruction support Jordan Niethe
                   ` (2 preceding siblings ...)
  2020-05-06  3:40 ` [PATCH v8 03/30] powerpc/xmon: Move breakpoints to text section Jordan Niethe
@ 2020-05-06  3:40 ` Jordan Niethe
  2020-05-06  3:40 ` [PATCH v8 05/30] powerpc: Change calling convention for create_branch() et. al Jordan Niethe
                   ` (27 subsequent siblings)
  31 siblings, 0 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-06  3:40 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, Jordan Niethe, dja

A modulo operation is used for calculating the current offset from a
breakpoint within the breakpoint table. As instruction lengths are
always a power of 2, this can be replaced with a bitwise 'and'. The
current check for word alignment can be replaced with checking that the
lower 2 bits are not set.

Suggested-by: Christophe Leroy <christophe.leroy@c-s.fr>
Reviewed-by: Alistair Popple <alistair@popple.id.au>
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v6: New to series
---
 arch/powerpc/xmon/xmon.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 4ecb7e73b017..c52b117640f2 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -857,8 +857,8 @@ static struct bpt *in_breakpoint_table(unsigned long nip, unsigned long *offp)
 	off = nip - (unsigned long)bpt_table;
 	if (off >= sizeof(bpt_table))
 		return NULL;
-	*offp = off % BPT_SIZE;
-	if (*offp != 0 && *offp != 4)
+	*offp = off & (BPT_SIZE - 1);
+	if (off & 3)
 		return NULL;
 	return bpts + (off / BPT_SIZE);
 }
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH v8 05/30] powerpc: Change calling convention for create_branch() et. al.
  2020-05-06  3:40 [PATCH v8 00/30] Initial Prefixed Instruction support Jordan Niethe
                   ` (3 preceding siblings ...)
  2020-05-06  3:40 ` [PATCH v8 04/30] powerpc/xmon: Use bitwise calculations in_breakpoint_table() Jordan Niethe
@ 2020-05-06  3:40 ` Jordan Niethe
  2020-05-06  3:40 ` [PATCH v8 06/30] powerpc: Use a macro for creating instructions from u32s Jordan Niethe
                   ` (26 subsequent siblings)
  31 siblings, 0 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-06  3:40 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, Jordan Niethe, dja

create_branch(), create_cond_branch() and translate_branch() return the
instruction that they create, or return 0 to signal an error. 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.

Reviewed-by: Alistair Popple <alistair@popple.id.au>
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v5: New to series
v6: - setup_32.c: machine_init(): change insn to unsigned int
    - Fix typo in commit message
    - __ftrace_make_call(): test for err not !err
v8: Style fix
---
 arch/powerpc/include/asm/code-patching.h |  12 +-
 arch/powerpc/kernel/optprobes.c          |  24 ++--
 arch/powerpc/kernel/setup_32.c           |   4 +-
 arch/powerpc/kernel/trace/ftrace.c       |  24 ++--
 arch/powerpc/lib/code-patching.c         | 134 +++++++++++++----------
 arch/powerpc/lib/feature-fixups.c        |   5 +-
 6 files changed, 119 insertions(+), 84 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 305ca89d856f..3a43e8e847c8 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -75,7 +75,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;
+	unsigned int insn;
 
 	/* Configure static keys first, now that we're relocated. */
 	setup_feature_keys();
@@ -87,7 +87,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..8799d891320c 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..6ed3301c0582 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,19 @@ 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 +407,7 @@ static void __init test_trampoline(void)
 
 static void __init test_branch_iform(void)
 {
+	int err;
 	unsigned int instr;
 	unsigned long addr;
 
@@ -443,35 +448,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 +485,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 +533,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 +570,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 +584,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 +593,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 +604,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 +615,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 +625,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 +636,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 +659,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 +671,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] 81+ messages in thread

* [PATCH v8 06/30] powerpc: Use a macro for creating instructions from u32s
  2020-05-06  3:40 [PATCH v8 00/30] Initial Prefixed Instruction support Jordan Niethe
                   ` (4 preceding siblings ...)
  2020-05-06  3:40 ` [PATCH v8 05/30] powerpc: Change calling convention for create_branch() et. al Jordan Niethe
@ 2020-05-06  3:40 ` Jordan Niethe
  2020-05-06  3:40 ` [PATCH v8 07/30] powerpc: Use an accessor for instructions Jordan Niethe
                   ` (25 subsequent siblings)
  31 siblings, 0 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-06  3:40 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, 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.

Reviewed-by: Alistair Popple <alistair@popple.id.au>
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
v6: - Use in setup_32.c
    - epapr_paravirt.c: early_init_dt_scan_epapr(): move the use of
      ppc_inst() earlier.
v8: - style fixes
    - Use in crash_dump.c, 8xx.c, 8xx-pmu.c, mpc86xx_smp.c, smp.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/crash_dump.c          |  3 +-
 arch/powerpc/kernel/epapr_paravirt.c      |  3 +-
 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           | 32 +++++++------
 arch/powerpc/kernel/security.c            | 12 +++--
 arch/powerpc/kernel/setup_32.c            |  2 +-
 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/mm/nohash/8xx.c              |  5 +-
 arch/powerpc/perf/8xx-pmu.c               |  9 ++--
 arch/powerpc/platforms/86xx/mpc86xx_smp.c |  3 +-
 arch/powerpc/platforms/powermac/smp.c     |  3 +-
 arch/powerpc/xmon/xmon.c                  |  7 +--
 24 files changed, 156 insertions(+), 120 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/crash_dump.c b/arch/powerpc/kernel/crash_dump.c
index 05745ddbd229..78e556b131db 100644
--- a/arch/powerpc/kernel/crash_dump.c
+++ b/arch/powerpc/kernel/crash_dump.c
@@ -18,6 +18,7 @@
 #include <asm/firmware.h>
 #include <linux/uaccess.h>
 #include <asm/rtas.h>
+#include <asm/inst.h>
 
 #ifdef DEBUG
 #include <asm/udbg.h>
@@ -44,7 +45,7 @@ static void __init create_trampoline(unsigned long addr)
 	 * branch to "addr" we jump to ("addr" + 32 MB). Although it requires
 	 * two instructions it doesn't require any registers.
 	 */
-	patch_instruction(p, PPC_INST_NOP);
+	patch_instruction(p, ppc_inst(PPC_INST_NOP));
 	patch_branch(++p, addr + PHYSICAL_START, 0);
 }
 
diff --git a/arch/powerpc/kernel/epapr_paravirt.c b/arch/powerpc/kernel/epapr_paravirt.c
index 9d32158ce36f..e8eb72a65572 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);
@@ -36,7 +37,7 @@ static int __init early_init_dt_scan_epapr(unsigned long node,
 		return -1;
 
 	for (i = 0; i < (len / 4); i++) {
-		u32 inst = be32_to_cpu(insts[i]);
+		u32 inst = ppc_inst(be32_to_cpu(insts[i]));
 		patch_instruction(epapr_hypercall_start + i, inst);
 #if !defined(CONFIG_64BIT) || defined(CONFIG_PPC_BOOK3E_64)
 		patch_instruction(epapr_ev_idle_start + i, inst);
diff --git a/arch/powerpc/kernel/hw_breakpoint.c b/arch/powerpc/kernel/hw_breakpoint.c
index 72f461bd70fb..46e09ac8b84a 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 81efb605113e..2378a7ed4438 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..44006c4ca4f1 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,8 @@ 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..8e620da2b179 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,11 @@ 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 +431,8 @@ 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 +443,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/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 3a43e8e847c8..0536e4aed330 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -85,7 +85,7 @@ notrace void __init machine_init(u64 dt_ptr)
 	/* Enable early debugging if any specified (see udbg.h) */
 	udbg_early_init();
 
-	patch_instruction_site(&patch__memcpy_nocache, PPC_INST_NOP);
+	patch_instruction_site(&patch__memcpy_nocache, ppc_inst(PPC_INST_NOP));
 
 	create_cond_branch(&insn, addr, branch_target(addr), 0x820000);
 	patch_instruction(addr, insn);	/* replace b by bne cr0 */
diff --git a/arch/powerpc/kernel/trace/ftrace.c b/arch/powerpc/kernel/trace/ftrace.c
index 8799d891320c..00f69b7baa8a 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 6ed3301c0582..6c30ddadd971 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)
@@ -414,37 +415,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 */
@@ -478,7 +479,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)
@@ -505,28 +506,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 */
@@ -563,7 +564,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)
@@ -597,7 +598,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;
@@ -608,7 +609,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;
@@ -654,7 +655,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;
@@ -666,7 +667,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 53df4146dd32..85d62f16d07a 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)
 #define IMM_DS(i)		((uintptr_t)(i) & 0xfffc)
@@ -19,40 +20,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_DS(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) | IMM_DS(i))
-#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
@@ -472,7 +473,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/mm/nohash/8xx.c b/arch/powerpc/mm/nohash/8xx.c
index 3189308dece4..b27017109a36 100644
--- a/arch/powerpc/mm/nohash/8xx.c
+++ b/arch/powerpc/mm/nohash/8xx.c
@@ -11,6 +11,7 @@
 #include <linux/mmu_context.h>
 #include <asm/fixmap.h>
 #include <asm/code-patching.h>
+#include <asm/inst.h>
 
 #include <mm/mmu_decl.h>
 
@@ -101,7 +102,7 @@ static void mmu_patch_addis(s32 *site, long simm)
 
 	instr &= 0xffff0000;
 	instr |= ((unsigned long)simm) >> 16;
-	patch_instruction_site(site, instr);
+	patch_instruction_site(site, ppc_inst(instr));
 }
 
 static void mmu_mapin_ram_chunk(unsigned long offset, unsigned long top, pgprot_t prot)
@@ -125,7 +126,7 @@ unsigned long __init mmu_mapin_ram(unsigned long base, unsigned long top)
 		mapped = 0;
 		mmu_mapin_immr();
 		if (!IS_ENABLED(CONFIG_PIN_TLB_IMMR))
-			patch_instruction_site(&patch__dtlbmiss_immr_jmp, PPC_INST_NOP);
+			patch_instruction_site(&patch__dtlbmiss_immr_jmp, ppc_inst(PPC_INST_NOP));
 		if (!IS_ENABLED(CONFIG_PIN_TLB_TEXT))
 			mmu_patch_cmp_limit(&patch__itlbmiss_linmem_top, 0);
 	} else {
diff --git a/arch/powerpc/perf/8xx-pmu.c b/arch/powerpc/perf/8xx-pmu.c
index 1ad03c55c88c..acc27fc63eb7 100644
--- a/arch/powerpc/perf/8xx-pmu.c
+++ b/arch/powerpc/perf/8xx-pmu.c
@@ -15,6 +15,7 @@
 #include <asm/firmware.h>
 #include <asm/ptrace.h>
 #include <asm/code-patching.h>
+#include <asm/inst.h>
 
 #define PERF_8xx_ID_CPU_CYCLES		1
 #define PERF_8xx_ID_HW_INSTRUCTIONS	2
@@ -170,8 +171,8 @@ static void mpc8xx_pmu_del(struct perf_event *event, int flags)
 	case PERF_8xx_ID_ITLB_LOAD_MISS:
 		if (atomic_dec_return(&itlb_miss_ref) == 0) {
 			/* mfspr r10, SPRN_SPRG_SCRATCH0 */
-			unsigned int insn = PPC_INST_MFSPR | __PPC_RS(R10) |
-					    __PPC_SPR(SPRN_SPRG_SCRATCH0);
+			struct ppc_inst insn = ppc_inst(PPC_INST_MFSPR | __PPC_RS(R10) |
+					    __PPC_SPR(SPRN_SPRG_SCRATCH0));
 
 			patch_instruction_site(&patch__itlbmiss_exit_1, insn);
 #ifndef CONFIG_PIN_TLB_TEXT
@@ -182,8 +183,8 @@ static void mpc8xx_pmu_del(struct perf_event *event, int flags)
 	case PERF_8xx_ID_DTLB_LOAD_MISS:
 		if (atomic_dec_return(&dtlb_miss_ref) == 0) {
 			/* mfspr r10, SPRN_DAR */
-			unsigned int insn = PPC_INST_MFSPR | __PPC_RS(R10) |
-					    __PPC_SPR(SPRN_DAR);
+			struct ppc_inst insn = ppc_inst(PPC_INST_MFSPR | __PPC_RS(R10) |
+					    __PPC_SPR(SPRN_DAR));
 
 			patch_instruction_site(&patch__dtlbmiss_exit_1, insn);
 			patch_instruction_site(&patch__dtlbmiss_exit_2, insn);
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_smp.c b/arch/powerpc/platforms/86xx/mpc86xx_smp.c
index 5b91ea5694e3..31540ebf1e29 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_smp.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_smp.c
@@ -17,6 +17,7 @@
 #include <asm/pci-bridge.h>
 #include <asm/mpic.h>
 #include <asm/cacheflush.h>
+#include <asm/inst.h>
 
 #include <sysdev/fsl_soc.h>
 
@@ -82,7 +83,7 @@ smp_86xx_kick_cpu(int nr)
 		mdelay(1);
 
 	/* Restore the exception vector */
-	patch_instruction(vector, save_vector);
+	patch_instruction(vector, ppc_inst(save_vector));
 
 	local_irq_restore(flags);
 
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index be2ab5b11e57..44a00990af9d 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -49,6 +49,7 @@
 #include <asm/keylargo.h>
 #include <asm/pmac_low_i2c.h>
 #include <asm/pmac_pfunc.h>
+#include <asm/inst.h>
 
 #include "pmac.h"
 
@@ -826,7 +827,7 @@ static int smp_core99_kick_cpu(int nr)
 	mdelay(1);
 
 	/* Restore our exception vector */
-	patch_instruction(vector, save_vector);
+	patch_instruction(vector, ppc_inst(save_vector));
 
 	local_irq_restore(flags);
 	if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu done", 0x347);
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index c52b117640f2..23a057563aa3 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>
@@ -946,7 +947,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",
@@ -2847,7 +2848,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;
@@ -2860,7 +2861,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] 81+ messages in thread

* [PATCH v8 07/30] powerpc: Use an accessor for instructions
  2020-05-06  3:40 [PATCH v8 00/30] Initial Prefixed Instruction support Jordan Niethe
                   ` (5 preceding siblings ...)
  2020-05-06  3:40 ` [PATCH v8 06/30] powerpc: Use a macro for creating instructions from u32s Jordan Niethe
@ 2020-05-06  3:40 ` Jordan Niethe
  2020-05-06  3:40 ` [PATCH v8 08/30] powerpc: Use a function for getting the instruction op code Jordan Niethe
                   ` (24 subsequent siblings)
  31 siblings, 0 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-06  3:40 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, Jordan Niethe, dja

In preparation for introducing a more complicated instruction type to
accommodate prefixed instructions use an accessor for getting an
instruction as a u32.

Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v4: New to series
v5: Remove references to 'word' instructions
v6: - test_emulate_step.c: execute_compute_instr(): Introduce
      ppc_inst_val() here instead of in a later patch
    - ftrace.c: __ftrace_make_call(): Introduce adding ppc_inst_val() in
      this patch
    - fault.c: store_updates_sp(): Start using ppc_inst_val()
    - Move this patch before the ppc_inst_primary_opcode() patch
v8: - Style
    - Missed some in ftrace.c: __ftrace_make_nop(), __ftrace_make_call()
---
 arch/powerpc/include/asm/inst.h      |   5 +
 arch/powerpc/include/asm/sstep.h     |   6 +-
 arch/powerpc/kernel/align.c          |   6 +-
 arch/powerpc/kernel/kprobes.c        |   2 +-
 arch/powerpc/kernel/trace/ftrace.c   |  30 +--
 arch/powerpc/kernel/vecemu.c         |  16 +-
 arch/powerpc/lib/code-patching.c     |  18 +-
 arch/powerpc/lib/sstep.c             | 268 ++++++++++++++-------------
 arch/powerpc/lib/test_emulate_step.c |   8 +-
 arch/powerpc/mm/fault.c              |   6 +-
 arch/powerpc/xmon/xmon.c             |   4 +-
 11 files changed, 190 insertions(+), 179 deletions(-)

diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h
index 5298ba33b6e5..8a9e73bfbd27 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 u32 ppc_inst_val(u32 x)
+{
+	return x;
+}
+
 #endif /* _ASM_INST_H */
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 86e9bf62f18c..44921001f84a 100644
--- a/arch/powerpc/kernel/align.c
+++ b/arch/powerpc/kernel/align.c
@@ -314,8 +314,8 @@ int fix_alignment(struct pt_regs *regs)
 	}
 
 #ifdef CONFIG_SPE
-	if ((instr >> 26) == 0x4) {
-		int reg = (instr >> 21) & 0x1f;
+	if ((ppc_inst_val(instr) >> 26) == 0x4) {
+		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 2378a7ed4438..92fa3070d905 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 00f69b7baa8a..cc23c63f3769 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,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)) {
-		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 +202,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 */
@@ -229,7 +230,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;
 	}
 
@@ -403,7 +404,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 +498,8 @@ 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;
 }
@@ -527,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;
 	}
 
@@ -590,7 +592,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
 
 	/* It should be pointing to a nop */
 	if (op != ppc_inst(PPC_INST_NOP)) {
-		pr_err("Expected NOP but have %x\n", op);
+		pr_err("Expected NOP but have %x\n", ppc_inst_val(op));
 		return -EINVAL;
 	}
 
@@ -647,7 +649,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 +728,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..1f5e3b4c8ae4 100644
--- a/arch/powerpc/kernel/vecemu.c
+++ b/arch/powerpc/kernel/vecemu.c
@@ -260,21 +260,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 6c30ddadd971..baa849b1a1f9 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;
@@ -373,9 +373,9 @@ int translate_branch(unsigned int *instr, const unsigned int *dest,
 	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 5f3a7bd9d90d..14c93ee4ffc8 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;
 	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 85d62f16d07a..b928b21feac1 100644
--- a/arch/powerpc/lib/test_emulate_step.c
+++ b/arch/powerpc/lib/test_emulate_step.c
@@ -847,12 +847,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;
 	}
 
@@ -866,13 +866,13 @@ 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 */
 	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/mm/fault.c b/arch/powerpc/mm/fault.c
index 84af6c8eecf7..9364921870df 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -49,7 +49,7 @@
 static bool store_updates_sp(unsigned int inst)
 {
 	/* check for 1 in the rA field */
-	if (((inst >> 16) & 0x1f) != 1)
+	if (((ppc_inst_val(inst) >> 16) & 0x1f) != 1)
 		return false;
 	/* check major opcode */
 	switch (inst >> 26) {
@@ -60,10 +60,10 @@ static bool store_updates_sp(unsigned int inst)
 	case OP_STFDU:
 		return true;
 	case OP_STD:	/* std or stdu */
-		return (inst & 3) == 1;
+		return (ppc_inst_val(inst) & 3) == 1;
 	case OP_31:
 		/* check minor opcode */
-		switch ((inst >> 1) & 0x3ff) {
+		switch ((ppc_inst_val(inst) >> 1) & 0x3ff) {
 		case OP_31_XOP_STDUX:
 		case OP_31_XOP_STWUX:
 		case OP_31_XOP_STBUX:
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 23a057563aa3..99ba585a769b 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -2872,9 +2872,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] 81+ messages in thread

* [PATCH v8 08/30] powerpc: Use a function for getting the instruction op code
  2020-05-06  3:40 [PATCH v8 00/30] Initial Prefixed Instruction support Jordan Niethe
                   ` (6 preceding siblings ...)
  2020-05-06  3:40 ` [PATCH v8 07/30] powerpc: Use an accessor for instructions Jordan Niethe
@ 2020-05-06  3:40 ` Jordan Niethe
  2020-05-15  7:48   ` Jordan Niethe
  2020-05-06  3:40 ` [PATCH v8 09/30] powerpc: Use a function for byte swapping instructions Jordan Niethe
                   ` (23 subsequent siblings)
  31 siblings, 1 reply; 81+ messages in thread
From: Jordan Niethe @ 2020-05-06  3:40 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, 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.

Reviewed-by: Alistair Popple <alistair@popple.id.au>
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v4: New to series
v6: - Rename ppc_inst_primary() to ppc_inst_primary_opcode()
    - Use in vecemu.c, fault.c, sstep.c
    - Move this patch after the ppc_inst_val() patch
---
 arch/powerpc/include/asm/inst.h  | 5 +++++
 arch/powerpc/kernel/align.c      | 2 +-
 arch/powerpc/kernel/vecemu.c     | 3 ++-
 arch/powerpc/lib/code-patching.c | 4 ++--
 arch/powerpc/lib/sstep.c         | 2 +-
 arch/powerpc/mm/fault.c          | 3 ++-
 6 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h
index 8a9e73bfbd27..442a95f20de7 100644
--- a/arch/powerpc/include/asm/inst.h
+++ b/arch/powerpc/include/asm/inst.h
@@ -13,4 +13,9 @@ static inline u32 ppc_inst_val(u32 x)
 	return x;
 }
 
+static inline int ppc_inst_primary_opcode(u32 x)
+{
+	return ppc_inst_val(x) >> 26;
+}
+
 #endif /* _ASM_INST_H */
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
index 44921001f84a..47dbba81a227 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 ((ppc_inst_val(instr) >> 26) == 0x4) {
+	if (ppc_inst_primary_opcode(instr) == 0x4) {
 		int reg = (ppc_inst_val(instr) >> 21) & 0x1f;
 		PPC_WARN_ALIGNMENT(spe, regs);
 		return emulate_spe(regs, reg, instr);
diff --git a/arch/powerpc/kernel/vecemu.c b/arch/powerpc/kernel/vecemu.c
index 1f5e3b4c8ae4..a544590b90e5 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);
@@ -268,7 +269,7 @@ int emulate_altivec(struct pt_regs *regs)
 		return -EFAULT;
 
 	word = ppc_inst_val(instr);
-	if ((word >> 26) != 4)
+	if (ppc_inst_primary_opcode(instr) != 4)
 		return -EINVAL;		/* not an altivec instruction */
 	vd = (word >> 21) & 0x1f;
 	va = (word >> 16) & 0x1f;
diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index baa849b1a1f9..f5c6dcbac44b 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_primary_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_primary_opcode(instr) & 0x3F;
 }
 
 static int instr_is_branch_iform(unsigned int instr)
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index 14c93ee4ffc8..7f7be154da7e 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -1175,7 +1175,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 	word = ppc_inst_val(instr);
 	op->type = COMPUTE;
 
-	opcode = instr >> 26;
+	opcode = ppc_inst_primary_opcode(instr);
 	switch (opcode) {
 	case 16:	/* bc */
 		op->type = BRANCH;
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 9364921870df..0e7e145d5cad 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -41,6 +41,7 @@
 #include <asm/siginfo.h>
 #include <asm/debug.h>
 #include <asm/kup.h>
+#include <asm/inst.h>
 
 /*
  * Check whether the instruction inst is a store using
@@ -52,7 +53,7 @@ static bool store_updates_sp(unsigned int inst)
 	if (((ppc_inst_val(inst) >> 16) & 0x1f) != 1)
 		return false;
 	/* check major opcode */
-	switch (inst >> 26) {
+	switch (ppc_inst_primary_opcode(inst)) {
 	case OP_STWU:
 	case OP_STBU:
 	case OP_STHU:
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH v8 09/30] powerpc: Use a function for byte swapping instructions
  2020-05-06  3:40 [PATCH v8 00/30] Initial Prefixed Instruction support Jordan Niethe
                   ` (7 preceding siblings ...)
  2020-05-06  3:40 ` [PATCH v8 08/30] powerpc: Use a function for getting the instruction op code Jordan Niethe
@ 2020-05-06  3:40 ` Jordan Niethe
  2020-05-06  3:40 ` [PATCH v8 10/30] powerpc: Introduce functions for instruction equality Jordan Niethe
                   ` (22 subsequent siblings)
  31 siblings, 0 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-06  3:40 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, Jordan Niethe, dja

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 442a95f20de7..23fd57a86b03 100644
--- a/arch/powerpc/include/asm/inst.h
+++ b/arch/powerpc/include/asm/inst.h
@@ -18,4 +18,9 @@ static inline int ppc_inst_primary_opcode(u32 x)
 	return ppc_inst_val(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 47dbba81a227..a63216da8cf1 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] 81+ messages in thread

* [PATCH v8 10/30] powerpc: Introduce functions for instruction equality
  2020-05-06  3:40 [PATCH v8 00/30] Initial Prefixed Instruction support Jordan Niethe
                   ` (8 preceding siblings ...)
  2020-05-06  3:40 ` [PATCH v8 09/30] powerpc: Use a function for byte swapping instructions Jordan Niethe
@ 2020-05-06  3:40 ` Jordan Niethe
  2020-05-06  3:40 ` [PATCH v8 11/30] powerpc: Use a datatype for instructions Jordan Niethe
                   ` (21 subsequent siblings)
  31 siblings, 0 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-06  3:40 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, Jordan Niethe, dja

In preparation for an instruction data type that can not be directly
used with the '==' operator use functions for checking equality.

Reviewed-by: Balamuruhan S <bala24@linux.ibm.com>
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v5: Remove ppc_inst_null()
v7: Fix compilation issue in expected_nop_sequence() when no
    CONFIG_MPROFILE_KERNEL
---
 arch/powerpc/include/asm/inst.h    |  5 +++++
 arch/powerpc/kernel/trace/ftrace.c | 15 ++++++++-------
 arch/powerpc/lib/code-patching.c   | 12 ++++++------
 arch/powerpc/xmon/xmon.c           |  4 ++--
 4 files changed, 21 insertions(+), 15 deletions(-)

diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h
index 23fd57a86b03..0c5dc539160a 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 cc23c63f3769..cbb19af4a72a 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;
@@ -201,7 +202,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;
 	}
@@ -498,7 +499,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) ||
+	if (!ppc_inst_equal(op0, ppc_inst(0x48000008)) ||
 	    (ppc_inst_val(op1) & 0xffff0000) != 0xe8410000)
 		return 0;
 	return 1;
@@ -508,7 +509,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;
 }
@@ -591,7 +592,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", ppc_inst_val(op));
 		return -EINVAL;
 	}
@@ -648,7 +649,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 f5c6dcbac44b..d298bb16936e 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -479,7 +479,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)
@@ -564,7 +564,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)
@@ -598,7 +598,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;
@@ -609,7 +609,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;
@@ -655,7 +655,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;
@@ -667,7 +667,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/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 99ba585a769b..2e8ed8cdcf28 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -947,7 +947,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",
@@ -2862,7 +2862,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] 81+ messages in thread

* [PATCH v8 11/30] powerpc: Use a datatype for instructions
  2020-05-06  3:40 [PATCH v8 00/30] Initial Prefixed Instruction support Jordan Niethe
                   ` (9 preceding siblings ...)
  2020-05-06  3:40 ` [PATCH v8 10/30] powerpc: Introduce functions for instruction equality Jordan Niethe
@ 2020-05-06  3:40 ` Jordan Niethe
  2020-05-08  1:51   ` Jordan Niethe
                     ` (3 more replies)
  2020-05-06  3:40 ` [PATCH v8 12/30] powerpc: Use a function for reading instructions Jordan Niethe
                   ` (20 subsequent siblings)
  31 siblings, 4 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-06  3:40 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, 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 endianness 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.

Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v4: New to series
v5: Add to epapr_paravirt.c, kgdb.c
v6: - setup_32.c: machine_init(): Use type
    - feature-fixups.c: do_final_fixups(): Use type
    - optprobes.c: arch_prepare_optimized_kprobe(): change a void * to
      struct ppc_inst *
    - fault.c: store_updates_sp(): Use type
    - Change ppc_inst_equal() implementation from memcpy()
v7: - Fix compilation issue in early_init_dt_scan_epapr() and
      do_patch_instruction() with CONFIG_STRICT_KERNEL_RWX
v8: - style
    - Use in crash_dump.c, mpc86xx_smp.c, smp.c
---
 arch/powerpc/include/asm/code-patching.h  | 32 ++++-----
 arch/powerpc/include/asm/inst.h           | 18 +++--
 arch/powerpc/include/asm/sstep.h          |  5 +-
 arch/powerpc/include/asm/uprobes.h        |  5 +-
 arch/powerpc/kernel/align.c               |  4 +-
 arch/powerpc/kernel/crash_dump.c          |  2 +-
 arch/powerpc/kernel/epapr_paravirt.c      |  6 +-
 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           | 64 +++++++++--------
 arch/powerpc/kernel/setup_32.c            |  4 +-
 arch/powerpc/kernel/trace/ftrace.c        | 83 ++++++++++++-----------
 arch/powerpc/kernel/vecemu.c              |  5 +-
 arch/powerpc/lib/code-patching.c          | 76 ++++++++++-----------
 arch/powerpc/lib/feature-fixups.c         | 60 ++++++++--------
 arch/powerpc/lib/sstep.c                  |  4 +-
 arch/powerpc/lib/test_emulate_step.c      |  9 +--
 arch/powerpc/mm/fault.c                   |  4 +-
 arch/powerpc/perf/core-book3s.c           |  4 +-
 arch/powerpc/platforms/86xx/mpc86xx_smp.c |  4 +-
 arch/powerpc/platforms/powermac/smp.c     |  4 +-
 arch/powerpc/xmon/xmon.c                  | 22 +++---
 arch/powerpc/xmon/xmon_bpts.h             |  6 +-
 26 files changed, 233 insertions(+), 211 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 0c5dc539160a..19d8bb7a1c2b 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_primary_opcode(u32 x)
+static inline int ppc_inst_primary_opcode(struct ppc_inst x)
 {
 	return ppc_inst_val(x) >> 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 ppc_inst_val(x) == ppc_inst_val(y);
 }
 
 #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 a63216da8cf1..9e66e6c62354 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/crash_dump.c b/arch/powerpc/kernel/crash_dump.c
index 78e556b131db..72bafb47e757 100644
--- a/arch/powerpc/kernel/crash_dump.c
+++ b/arch/powerpc/kernel/crash_dump.c
@@ -35,7 +35,7 @@ void __init reserve_kdump_trampoline(void)
 
 static void __init create_trampoline(unsigned long addr)
 {
-	unsigned int *p = (unsigned int *)addr;
+	struct ppc_inst *p = (struct ppc_inst *)addr;
 
 	/* The maximum range of a single instruction branch, is the current
 	 * instruction's address + (32 MB - 4) bytes. For the trampoline we
diff --git a/arch/powerpc/kernel/epapr_paravirt.c b/arch/powerpc/kernel/epapr_paravirt.c
index e8eb72a65572..2ed14d4a47f5 100644
--- a/arch/powerpc/kernel/epapr_paravirt.c
+++ b/arch/powerpc/kernel/epapr_paravirt.c
@@ -37,10 +37,10 @@ static int __init early_init_dt_scan_epapr(unsigned long node,
 		return -1;
 
 	for (i = 0; i < (len / 4); i++) {
-		u32 inst = ppc_inst(be32_to_cpu(insts[i]));
-		patch_instruction(epapr_hypercall_start + i, inst);
+		struct ppc_inst inst = ppc_inst(be32_to_cpu(insts[i]));
+		patch_instruction((struct ppc_inst *)(epapr_hypercall_start + i), inst);
 #if !defined(CONFIG_64BIT) || defined(CONFIG_PPC_BOOK3E_64)
-		patch_instruction(epapr_ev_idle_start + i, inst);
+		patch_instruction((struct ppc_inst *)(epapr_ev_idle_start + i), inst);
 #endif
 	}
 
diff --git a/arch/powerpc/kernel/hw_breakpoint.c b/arch/powerpc/kernel/hw_breakpoint.c
index 46e09ac8b84a..2db9a7ac7bcb 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 92fa3070d905..a08ae5803622 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 067b094bfeff..cd23218c60bb 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 44006c4ca4f1..5a71fef71c22 100644
--- a/arch/powerpc/kernel/optprobes.c
+++ b/arch/powerpc/kernel/optprobes.c
@@ -100,8 +100,9 @@ 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, &regs, *p->ainsn.insn) == 1) {
+	if (!is_conditional_branch(*(struct ppc_inst *)p->ainsn.insn) &&
+	    analyse_instr(&op, &regs,
+			  *(struct ppc_inst *)p->ainsn.insn) == 1) {
 		emulate_update_regs(&regs, &op);
 		nip = regs.nip;
 	}
@@ -148,13 +149,15 @@ 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) |
-			  ((val >> 16) & 0xffff)));
+	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) |
-			  ___PPC_RS(4) | (val & 0xffff)));
+	patch_instruction((struct ppc_inst *)addr,
+			  ppc_inst(PPC_INST_ORI | ___PPC_RA(4) |
+				   ___PPC_RS(4) | (val & 0xffff)));
 }
 
 /*
@@ -164,34 +167,39 @@ 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) |
-			  ((val >> 48) & 0xffff)));
+	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) |
-			  ___PPC_RS(3) | ((val >> 32) & 0xffff)));
+	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) |
-			  ___PPC_RS(3) | __PPC_SH64(32) | __PPC_ME64(31)));
+	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) |
-			  ___PPC_RS(3) | ((val >> 16) & 0xffff)));
+	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) |
-			  ___PPC_RS(3) | (val & 0xffff)));
+	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 +239,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,
+		rc = patch_instruction((struct ppc_inst *)(buff + i),
 				       ppc_inst(*(optprobe_template_entry + i)));
 		if (rc < 0)
 			goto error;
@@ -254,20 +262,22 @@ 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
@@ -277,7 +287,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((struct ppc_inst *)(buff + TMPL_RET_IDX), (unsigned long)nip, 0);
 
 	flush_icache_range((unsigned long)buff,
 			   (unsigned long)(&buff[TMPL_END_IDX]));
@@ -309,7 +319,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;
 
@@ -321,9 +331,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 0536e4aed330..15f0a7c84944 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -74,8 +74,8 @@ 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 int insn;
+	struct ppc_inst *addr = (struct ppc_inst *)patch_site_addr(&patch__memset_nocache);
+	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 cbb19af4a72a..3117ed675735 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))) {
@@ -208,7 +208,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;
 	}
@@ -221,7 +221,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;
@@ -280,7 +280,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;
@@ -291,7 +291,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
@@ -328,9 +328,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? */
@@ -379,7 +380,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;
 	}
@@ -395,7 +396,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))) {
@@ -423,7 +424,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;
 	}
@@ -435,7 +436,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,
@@ -488,7 +489,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:
@@ -506,7 +507,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)))
@@ -518,8 +519,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;
@@ -584,7 +585,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 */
@@ -604,7 +605,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");
@@ -613,7 +614,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
 
 	pr_devel("write to %lx\n", rec->ip);
 
-	if (patch_instruction((unsigned int *)ip, op))
+	if (patch_instruction((struct ppc_inst *)ip, op))
 		return -EPERM;
 
 	return 0;
@@ -623,7 +624,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;
 
@@ -671,7 +672,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,
@@ -710,7 +711,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;
@@ -758,7 +759,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;
 		}
@@ -786,12 +787,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;
 	}
@@ -804,7 +805,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,
@@ -844,10 +845,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);
 
@@ -855,7 +856,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);
 	}
@@ -929,7 +930,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);
@@ -942,7 +943,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 a544590b90e5..3dd70eeb10c5 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 d298bb16936e..1dff9d9d6645 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;
@@ -161,8 +161,7 @@ static int do_patch_instruction(unsigned int *addr, unsigned int instr)
 		goto out;
 	}
 
-	patch_addr = (unsigned int *)(text_poke_addr) +
-			((kaddr & ~PAGE_MASK) / sizeof(unsigned int));
+	patch_addr = (struct ppc_inst *)(text_poke_addr + (kaddr & ~PAGE_MASK));
 
 	__patch_instruction(addr, instr, patch_addr);
 
@@ -177,14 +176,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 +194,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 +228,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_primary_opcode(instr);
 
@@ -247,13 +246,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 +262,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 +281,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_primary_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 +309,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 +330,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 +346,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 +356,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,8 +364,8 @@ 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;
 
@@ -392,7 +391,7 @@ void __patch_exception(int exc, unsigned long addr)
 	 * instruction of the exception, not the first one
 	 */
 
-	patch_branch(ibase + (exc / 4) + 1, addr, 0);
+	patch_branch((struct ppc_inst *)(ibase + (exc / 4) + 1), addr, 0);
 }
 #endif
 
@@ -409,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;
@@ -484,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);
@@ -500,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;
@@ -570,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..fb6e8e8abf4e 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,17 @@ 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 +210,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 +263,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 +298,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 +341,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 +375,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 ;
@@ -390,18 +392,18 @@ void do_lwsync_fixups(unsigned long value, void *fixup_start, void *fixup_end)
 static void do_final_fixups(void)
 {
 #if defined(CONFIG_PPC64) && defined(CONFIG_RELOCATABLE)
-	int *src, *dest;
+	struct ppc_inst *src, *dest;
 	unsigned long length;
 
 	if (PHYSICAL_START == 0)
 		return;
 
-	src = (int *)(KERNELBASE + PHYSICAL_START);
-	dest = (int *)KERNELBASE;
-	length = (__end_interrupts - _stext) / sizeof(int);
+	src = (struct ppc_inst *)(KERNELBASE + PHYSICAL_START);
+	dest = (struct ppc_inst *)KERNELBASE;
+	length = (__end_interrupts - _stext) / sizeof(struct ppc_inst);
 
 	while (length--) {
-		raw_patch_instruction(dest, ppc_inst(*src));
+		raw_patch_instruction(dest, *src);
 		src++;
 		dest++;
 	}
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index 7f7be154da7e..95a56bb1ba3f 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 b928b21feac1..46af80279ebc 100644
--- a/arch/powerpc/lib/test_emulate_step.c
+++ b/arch/powerpc/lib/test_emulate_step.c
@@ -462,7 +462,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];
 };
@@ -843,7 +843,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;
 
@@ -861,7 +861,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;
@@ -892,7 +892,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/mm/fault.c b/arch/powerpc/mm/fault.c
index 0e7e145d5cad..4a50f125ec18 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -47,7 +47,7 @@
  * Check whether the instruction inst is a store using
  * an update addressing form which will update r1.
  */
-static bool store_updates_sp(unsigned int inst)
+static bool store_updates_sp(struct ppc_inst inst)
 {
 	/* check for 1 in the rA field */
 	if (((ppc_inst_val(inst) >> 16) & 0x1f) != 1)
@@ -279,7 +279,7 @@ static bool bad_stack_expansion(struct pt_regs *regs, unsigned long address,
 
 		if ((flags & FAULT_FLAG_WRITE) && (flags & FAULT_FLAG_USER) &&
 		    access_ok(nip, sizeof(*nip))) {
-			unsigned int inst;
+			struct ppc_inst inst;
 
 			if (!probe_user_read(&inst, nip, sizeof(inst)))
 				return !store_updates_sp(inst);
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 3dcfecf858f3..13b9dd5e4a76 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/platforms/86xx/mpc86xx_smp.c b/arch/powerpc/platforms/86xx/mpc86xx_smp.c
index 31540ebf1e29..dba3aa73c062 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_smp.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_smp.c
@@ -73,7 +73,7 @@ smp_86xx_kick_cpu(int nr)
 
 	/* Setup fake reset vector to call __secondary_start_mpc86xx. */
 	target = (unsigned long) __secondary_start_mpc86xx;
-	patch_branch(vector, target, BRANCH_SET_LINK);
+	patch_branch((struct ppc_inst *)vector, target, BRANCH_SET_LINK);
 
 	/* Kick that CPU */
 	smp_86xx_release_core(nr);
@@ -83,7 +83,7 @@ smp_86xx_kick_cpu(int nr)
 		mdelay(1);
 
 	/* Restore the exception vector */
-	patch_instruction(vector, ppc_inst(save_vector));
+	patch_instruction((struct ppc_inst *)vector, ppc_inst(save_vector));
 
 	local_irq_restore(flags);
 
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index 44a00990af9d..9969c07035b6 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -814,7 +814,7 @@ static int smp_core99_kick_cpu(int nr)
 	 *   b __secondary_start_pmac_0 + nr*8
 	 */
 	target = (unsigned long) __secondary_start_pmac_0 + nr * 8;
-	patch_branch(vector, target, BRANCH_SET_LINK);
+	patch_branch((struct ppc_inst *)vector, target, BRANCH_SET_LINK);
 
 	/* Put some life in our friend */
 	pmac_call_feature(PMAC_FTR_RESET_CPU, NULL, nr, 0);
@@ -827,7 +827,7 @@ static int smp_core99_kick_cpu(int nr)
 	mdelay(1);
 
 	/* Restore our exception vector */
-	patch_instruction(vector, ppc_inst(save_vector));
+	patch_instruction((struct ppc_inst *)vector, ppc_inst(save_vector));
 
 	local_irq_restore(flags);
 	if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu done", 0x347);
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 2e8ed8cdcf28..e0132d6d24d0 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -100,7 +100,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;
@@ -876,8 +876,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;
 		}
 	}
@@ -889,7 +889,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;
@@ -911,8 +911,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;
@@ -940,7 +940,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) {
@@ -949,7 +949,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);
 	}
@@ -1156,7 +1156,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();
@@ -1322,7 +1322,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)) {
@@ -2848,7 +2848,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;
diff --git a/arch/powerpc/xmon/xmon_bpts.h b/arch/powerpc/xmon/xmon_bpts.h
index b7e94375db86..57e6fb03de48 100644
--- a/arch/powerpc/xmon/xmon_bpts.h
+++ b/arch/powerpc/xmon/xmon_bpts.h
@@ -4,11 +4,11 @@
 
 #define NBPTS	256
 #ifndef __ASSEMBLY__
-#define BPT_SIZE	(sizeof(unsigned int) * 2)
-#define BPT_WORDS	(BPT_SIZE / sizeof(unsigned int))
+#include <asm/inst.h>
+#define BPT_SIZE	(sizeof(struct ppc_inst) * 2)
+#define BPT_WORDS	(BPT_SIZE / sizeof(struct ppc_inst))
 
 extern unsigned int bpt_table[NBPTS * BPT_WORDS];
-
 #endif /* __ASSEMBLY__ */
 
 #endif /* XMON_BPTS_H */
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH v8 12/30] powerpc: Use a function for reading instructions
  2020-05-06  3:40 [PATCH v8 00/30] Initial Prefixed Instruction support Jordan Niethe
                   ` (10 preceding siblings ...)
  2020-05-06  3:40 ` [PATCH v8 11/30] powerpc: Use a datatype for instructions Jordan Niethe
@ 2020-05-06  3:40 ` Jordan Niethe
  2020-05-16 18:39   ` Christophe Leroy
  2020-05-06  3:40 ` [PATCH v8 13/30] powerpc: Add a probe_user_read_inst() function Jordan Niethe
                   ` (19 subsequent siblings)
  31 siblings, 1 reply; 81+ messages in thread
From: Jordan Niethe @ 2020-05-06  3:40 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, 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.

Reviewed-by: Alistair Popple <alistair@popple.id.au>
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
v6: - feature-fixups.c: do_final_fixups(): Use here
    - arch_prepare_kprobe(): patch_instruction(): no longer part of this
      patch
    - Move probe_kernel_read_inst() out of this patch
    - Use in uprobes
v8: style
---
 arch/powerpc/include/asm/inst.h    |  5 +++++
 arch/powerpc/kernel/kprobes.c      |  6 +++---
 arch/powerpc/kernel/mce_power.c    |  2 +-
 arch/powerpc/kernel/optprobes.c    |  4 ++--
 arch/powerpc/kernel/trace/ftrace.c |  4 ++--
 arch/powerpc/kernel/uprobes.c      |  2 +-
 arch/powerpc/lib/code-patching.c   | 26 ++++++++++++++------------
 arch/powerpc/lib/feature-fixups.c  |  4 ++--
 arch/powerpc/xmon/xmon.c           |  6 +++---
 9 files changed, 33 insertions(+), 26 deletions(-)

diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h
index 19d8bb7a1c2b..552e953bf04f 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 ppc_inst_val(x) == ppc_inst_val(y);
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index a08ae5803622..f64312dca84f 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");
@@ -127,7 +127,7 @@ 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;
+		p->opcode = ppc_inst_val(insn);
 		flush_icache_range((unsigned long)p->ainsn.insn,
 			(unsigned long)p->ainsn.insn + sizeof(kprobe_opcode_t));
 	}
@@ -217,7 +217,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 cd23218c60bb..45c51ba0071b 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 5a71fef71c22..52c1ab3f85aa 100644
--- a/arch/powerpc/kernel/optprobes.c
+++ b/arch/powerpc/kernel/optprobes.c
@@ -100,9 +100,9 @@ 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) &&
+	if (!is_conditional_branch(ppc_inst_read((struct ppc_inst *)p->ainsn.insn)) &&
 	    analyse_instr(&op, &regs,
-			  *(struct ppc_inst *)p->ainsn.insn) == 1) {
+			  ppc_inst_read((struct ppc_inst *)p->ainsn.insn)) == 1) {
 		emulate_update_regs(&regs, &op);
 		nip = regs.nip;
 	}
diff --git a/arch/powerpc/kernel/trace/ftrace.c b/arch/powerpc/kernel/trace/ftrace.c
index 3117ed675735..acd5b889815f 100644
--- a/arch/powerpc/kernel/trace/ftrace.c
+++ b/arch/powerpc/kernel/trace/ftrace.c
@@ -848,7 +848,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);
 
@@ -856,7 +856,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/kernel/uprobes.c b/arch/powerpc/kernel/uprobes.c
index 31c870287f2b..6893d40a48c5 100644
--- a/arch/powerpc/kernel/uprobes.c
+++ b/arch/powerpc/kernel/uprobes.c
@@ -174,7 +174,7 @@ bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
 	 * emulate_step() returns 1 if the insn was successfully emulated.
 	 * For all other cases, we need to single-step in hardware.
 	 */
-	ret = emulate_step(regs, auprobe->insn);
+	ret = emulate_step(regs, ppc_inst_read(&auprobe->insn));
 	if (ret > 0)
 		return true;
 
diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index 1dff9d9d6645..435fc8e9f45d 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -348,9 +348,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;
@@ -358,7 +358,8 @@ 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 +369,14 @@ 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 +600,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 +611,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 +657,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 +669,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 fb6e8e8abf4e..c0d3ed4efb7e 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);
@@ -403,7 +403,7 @@ static void do_final_fixups(void)
 	length = (__end_interrupts - _stext) / sizeof(struct ppc_inst);
 
 	while (length--) {
-		raw_patch_instruction(dest, *src);
+		raw_patch_instruction(dest, ppc_inst_read(src));
 		src++;
 		dest++;
 	}
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index e0132d6d24d0..68e0b05d9226 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -702,13 +702,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");
 			}
 		}
 	}
@@ -949,7 +949,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] 81+ messages in thread

* [PATCH v8 13/30] powerpc: Add a probe_user_read_inst() function
  2020-05-06  3:40 [PATCH v8 00/30] Initial Prefixed Instruction support Jordan Niethe
                   ` (11 preceding siblings ...)
  2020-05-06  3:40 ` [PATCH v8 12/30] powerpc: Use a function for reading instructions Jordan Niethe
@ 2020-05-06  3:40 ` Jordan Niethe
  2020-05-13 12:52   ` Michael Ellerman
  2020-05-14  5:46   ` Christophe Leroy
  2020-05-06  3:40 ` [PATCH v8 14/30] powerpc: Add a probe_kernel_read_inst() function Jordan Niethe
                   ` (18 subsequent siblings)
  31 siblings, 2 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-06  3:40 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, Jordan Niethe, dja

Introduce a probe_user_read_inst() function to use in cases where
probe_user_read() is used for getting an instruction. This will be more
useful for prefixed instructions.

Reviewed-by: Alistair Popple <alistair@popple.id.au>
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v6: - New to series
---
 arch/powerpc/include/asm/inst.h |  3 +++
 arch/powerpc/lib/Makefile       |  2 +-
 arch/powerpc/lib/inst.c         | 18 ++++++++++++++++++
 arch/powerpc/mm/fault.c         |  2 +-
 4 files changed, 23 insertions(+), 2 deletions(-)
 create mode 100644 arch/powerpc/lib/inst.c

diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h
index 552e953bf04f..3e9a58420151 100644
--- a/arch/powerpc/include/asm/inst.h
+++ b/arch/powerpc/include/asm/inst.h
@@ -37,4 +37,7 @@ static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
 	return ppc_inst_val(x) == ppc_inst_val(y);
 }
 
+int probe_user_read_inst(struct ppc_inst *inst,
+			 struct ppc_inst *nip);
+
 #endif /* _ASM_INST_H */
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index b8de3be10eb4..546591848219 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -16,7 +16,7 @@ CFLAGS_code-patching.o += -DDISABLE_BRANCH_PROFILING
 CFLAGS_feature-fixups.o += -DDISABLE_BRANCH_PROFILING
 endif
 
-obj-y += alloc.o code-patching.o feature-fixups.o pmem.o
+obj-y += alloc.o code-patching.o feature-fixups.o pmem.o inst.o
 
 ifndef CONFIG_KASAN
 obj-y	+=	string.o memcmp_$(BITS).o
diff --git a/arch/powerpc/lib/inst.c b/arch/powerpc/lib/inst.c
new file mode 100644
index 000000000000..eaf786afad2b
--- /dev/null
+++ b/arch/powerpc/lib/inst.c
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *  Copyright 2020, IBM Corporation.
+ */
+
+#include <linux/uaccess.h>
+#include <asm/inst.h>
+
+int probe_user_read_inst(struct ppc_inst *inst,
+			 struct ppc_inst *nip)
+{
+	unsigned int val;
+	int err;
+
+	err = probe_user_read(&val, nip, sizeof(val));
+	*inst = ppc_inst(val);
+	return err;
+}
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 4a50f125ec18..f3a943eae305 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -281,7 +281,7 @@ static bool bad_stack_expansion(struct pt_regs *regs, unsigned long address,
 		    access_ok(nip, sizeof(*nip))) {
 			struct ppc_inst inst;
 
-			if (!probe_user_read(&inst, nip, sizeof(inst)))
+			if (!probe_user_read_inst(&inst, (struct ppc_inst __user *)nip))
 				return !store_updates_sp(inst);
 			*must_retry = true;
 		}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH v8 14/30] powerpc: Add a probe_kernel_read_inst() function
  2020-05-06  3:40 [PATCH v8 00/30] Initial Prefixed Instruction support Jordan Niethe
                   ` (12 preceding siblings ...)
  2020-05-06  3:40 ` [PATCH v8 13/30] powerpc: Add a probe_user_read_inst() function Jordan Niethe
@ 2020-05-06  3:40 ` Jordan Niethe
  2020-05-06  3:40 ` [PATCH v8 15/30] powerpc/kprobes: Use patch_instruction() Jordan Niethe
                   ` (17 subsequent siblings)
  31 siblings, 0 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-06  3:40 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, Jordan Niethe, dja

Introduce a probe_kernel_read_inst() function to use in cases where
probe_kernel_read() is used for getting an instruction. This will be
more useful for prefixed instructions.

Reviewed-by: Alistair Popple <alistair@popple.id.au>
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v6: - This was previously just in ftrace.c
---
 arch/powerpc/include/asm/inst.h    |  2 ++
 arch/powerpc/kernel/trace/ftrace.c | 23 +++++++++++++----------
 arch/powerpc/lib/inst.c            | 11 +++++++++++
 3 files changed, 26 insertions(+), 10 deletions(-)

diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h
index 3e9a58420151..0d581b332c20 100644
--- a/arch/powerpc/include/asm/inst.h
+++ b/arch/powerpc/include/asm/inst.h
@@ -39,5 +39,7 @@ static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
 
 int probe_user_read_inst(struct ppc_inst *inst,
 			 struct ppc_inst *nip);
+int probe_kernel_read_inst(struct ppc_inst *inst,
+			   struct ppc_inst *src);
 
 #endif /* _ASM_INST_H */
diff --git a/arch/powerpc/kernel/trace/ftrace.c b/arch/powerpc/kernel/trace/ftrace.c
index acd5b889815f..5e399628f51a 100644
--- a/arch/powerpc/kernel/trace/ftrace.c
+++ b/arch/powerpc/kernel/trace/ftrace.c
@@ -68,7 +68,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 +130,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 +164,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;
 	}
@@ -197,7 +197,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;
 	}
@@ -349,7 +349,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;
 	}
@@ -399,7 +399,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;
 	}
@@ -526,7 +526,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])) {
@@ -589,7 +592,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 */
@@ -645,7 +648,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;
 	}
@@ -723,7 +726,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;
 	}
diff --git a/arch/powerpc/lib/inst.c b/arch/powerpc/lib/inst.c
index eaf786afad2b..08dedd927268 100644
--- a/arch/powerpc/lib/inst.c
+++ b/arch/powerpc/lib/inst.c
@@ -16,3 +16,14 @@ int probe_user_read_inst(struct ppc_inst *inst,
 	*inst = ppc_inst(val);
 	return err;
 }
+
+int probe_kernel_read_inst(struct ppc_inst *inst,
+			   struct ppc_inst *src)
+{
+	unsigned int val;
+	int err;
+
+	err = probe_kernel_read(&val, src, sizeof(val));
+	*inst = ppc_inst(val);
+	return err;
+}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH v8 15/30] powerpc/kprobes: Use patch_instruction()
  2020-05-06  3:40 [PATCH v8 00/30] Initial Prefixed Instruction support Jordan Niethe
                   ` (13 preceding siblings ...)
  2020-05-06  3:40 ` [PATCH v8 14/30] powerpc: Add a probe_kernel_read_inst() function Jordan Niethe
@ 2020-05-06  3:40 ` Jordan Niethe
  2020-05-06  3:40 ` [PATCH v8 16/30] powerpc: Define and use __get_user_instr{, inatomic}() Jordan Niethe
                   ` (16 subsequent siblings)
  31 siblings, 0 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-06  3:40 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, Jordan Niethe, dja

Instead of using memcpy() and flush_icache_range() use
patch_instruction() which not only accomplishes both of these steps but
will also make it easier to add support for prefixed instructions.

Reviewed-by: Alistair Popple <alistair@popple.id.au>
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v6: New to series.
---
 arch/powerpc/kernel/kprobes.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index f64312dca84f..a72c8e1a42ad 100644
--- a/arch/powerpc/kernel/kprobes.c
+++ b/arch/powerpc/kernel/kprobes.c
@@ -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));
+		patch_instruction((struct ppc_inst *)p->ainsn.insn, insn);
 		p->opcode = ppc_inst_val(insn);
-		flush_icache_range((unsigned long)p->ainsn.insn,
-			(unsigned long)p->ainsn.insn + sizeof(kprobe_opcode_t));
 	}
 
 	p->ainsn.boostable = 0;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH v8 16/30] powerpc: Define and use __get_user_instr{, inatomic}()
  2020-05-06  3:40 [PATCH v8 00/30] Initial Prefixed Instruction support Jordan Niethe
                   ` (14 preceding siblings ...)
  2020-05-06  3:40 ` [PATCH v8 15/30] powerpc/kprobes: Use patch_instruction() Jordan Niethe
@ 2020-05-06  3:40 ` Jordan Niethe
  2020-05-13 14:18   ` Michael Ellerman
  2020-05-06  3:40 ` [PATCH v8 17/30] powerpc: Introduce a function for reporting instruction length Jordan Niethe
                   ` (15 subsequent siblings)
  31 siblings, 1 reply; 81+ messages in thread
From: Jordan Niethe @ 2020-05-06  3:40 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, Jordan Niethe, dja

Define specific __get_user_instr() and __get_user_instr_inatomic()
macros for reading instructions from user space.

Reviewed-by: Alistair Popple <alistair@popple.id.au>
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 9e66e6c62354..b8f56052c6fe 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 2db9a7ac7bcb..423603c92c0f 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 3dd70eeb10c5..60ed5aea8d4e 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] 81+ messages in thread

* [PATCH v8 17/30] powerpc: Introduce a function for reporting instruction length
  2020-05-06  3:40 [PATCH v8 00/30] Initial Prefixed Instruction support Jordan Niethe
                   ` (15 preceding siblings ...)
  2020-05-06  3:40 ` [PATCH v8 16/30] powerpc: Define and use __get_user_instr{, inatomic}() Jordan Niethe
@ 2020-05-06  3:40 ` Jordan Niethe
  2020-05-06  3:40 ` [PATCH v8 18/30] powerpc/xmon: Use a function for reading instructions Jordan Niethe
                   ` (14 subsequent siblings)
  31 siblings, 0 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-06  3:40 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, Jordan Niethe, dja

Currently all instructions have the same length, but in preparation for
prefixed instructions introduce a function for returning instruction
length.

Reviewed-by: Alistair Popple <alistair@popple.id.au>
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v6: - feature-fixups.c: do_final_fixups(): use here
    - ppc_inst_len(): change return type from bool to int
    - uprobes: Use ppc_inst_read() before calling ppc_inst_len()
---
 arch/powerpc/include/asm/inst.h   |  5 +++++
 arch/powerpc/kernel/kprobes.c     |  6 ++++--
 arch/powerpc/kernel/uprobes.c     |  2 +-
 arch/powerpc/lib/feature-fixups.c | 14 +++++++-------
 4 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h
index 0d581b332c20..2f3c9d5bcf7c 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 int ppc_inst_len(struct ppc_inst x)
+{
+	return sizeof(struct ppc_inst);
+}
+
 static inline int ppc_inst_primary_opcode(struct ppc_inst x)
 {
 	return ppc_inst_val(x) >> 26;
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index a72c8e1a42ad..33d54b091c70 100644
--- a/arch/powerpc/kernel/kprobes.c
+++ b/arch/powerpc/kernel/kprobes.c
@@ -462,14 +462,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) {
@@ -478,7 +480,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 6893d40a48c5..83e883e1a42d 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(ppc_inst_read(&auprobe->insn));
 
 	user_disable_single_step(current);
 	return 0;
diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c
index c0d3ed4efb7e..2bd2b752de4f 100644
--- a/arch/powerpc/lib/feature-fixups.c
+++ b/arch/powerpc/lib/feature-fixups.c
@@ -392,20 +392,20 @@ void do_lwsync_fixups(unsigned long value, void *fixup_start, void *fixup_end)
 static void do_final_fixups(void)
 {
 #if defined(CONFIG_PPC64) && defined(CONFIG_RELOCATABLE)
-	struct ppc_inst *src, *dest;
-	unsigned long length;
+	struct ppc_inst inst, *src, *dest, *end;
 
 	if (PHYSICAL_START == 0)
 		return;
 
 	src = (struct ppc_inst *)(KERNELBASE + PHYSICAL_START);
 	dest = (struct ppc_inst *)KERNELBASE;
-	length = (__end_interrupts - _stext) / sizeof(struct ppc_inst);
+	end = (void *)src + (__end_interrupts - _stext);
 
-	while (length--) {
-		raw_patch_instruction(dest, ppc_inst_read(src));
-		src++;
-		dest++;
+	while (src < end) {
+		inst = ppc_inst_read(src);
+		raw_patch_instruction(dest, inst);
+		src = (void *)src + ppc_inst_len(inst);
+		dest = (void *)dest + ppc_inst_len(inst);
 	}
 #endif
 }
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH v8 18/30] powerpc/xmon: Use a function for reading instructions
  2020-05-06  3:40 [PATCH v8 00/30] Initial Prefixed Instruction support Jordan Niethe
                   ` (16 preceding siblings ...)
  2020-05-06  3:40 ` [PATCH v8 17/30] powerpc: Introduce a function for reporting instruction length Jordan Niethe
@ 2020-05-06  3:40 ` Jordan Niethe
  2020-05-06  3:40 ` [PATCH v8 19/30] powerpc/xmon: Move insertion of breakpoint for xol'ing Jordan Niethe
                   ` (13 subsequent siblings)
  31 siblings, 0 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-06  3:40 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, 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.

Reviewed-by: Alistair Popple <alistair@popple.id.au>
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v5: New to series, seperated from "Add prefixed instructions to
    instruction data type"
v6: mread_instr(): correctly return error status
v8: style
---
 arch/powerpc/xmon/xmon.c | 28 ++++++++++++++++++++++++----
 1 file changed, 24 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 68e0b05d9226..7a9cbc6d9b21 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -122,6 +122,7 @@ static unsigned bpinstr = 0x7fe00008;	/* trap */
 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);
@@ -896,7 +897,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;
@@ -946,7 +947,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)
@@ -1162,7 +1163,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",
@@ -1329,7 +1330,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;
 	}
@@ -2122,6 +2123,25 @@ mwrite(unsigned long adrs, void *buf, int size)
 	return n;
 }
 
+static int
+mread_instr(unsigned long adrs, struct ppc_inst *instr)
+{
+	volatile int n;
+
+	n = 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);
+		n = ppc_inst_len(*instr);
+	}
+	catch_memory_errors = 0;
+	return n;
+}
+
 static int fault_type;
 static int fault_except;
 static char *fault_chars[] = { "--", "**", "##" };
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH v8 19/30] powerpc/xmon: Move insertion of breakpoint for xol'ing
  2020-05-06  3:40 [PATCH v8 00/30] Initial Prefixed Instruction support Jordan Niethe
                   ` (17 preceding siblings ...)
  2020-05-06  3:40 ` [PATCH v8 18/30] powerpc/xmon: Use a function for reading instructions Jordan Niethe
@ 2020-05-06  3:40 ` Jordan Niethe
  2020-05-06  3:40 ` [PATCH v8 20/30] powerpc: Make test_translate_branch() independent of instruction length Jordan Niethe
                   ` (12 subsequent siblings)
  31 siblings, 0 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-06  3:40 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, 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.

Reviewed-by: Alistair Popple <alistair@popple.id.au>
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v8: style
---
 arch/powerpc/xmon/xmon.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 7a9cbc6d9b21..4d6980d51456 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -878,7 +878,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;
 		}
 	}
@@ -910,6 +909,8 @@ 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] 81+ messages in thread

* [PATCH v8 20/30] powerpc: Make test_translate_branch() independent of instruction length
  2020-05-06  3:40 [PATCH v8 00/30] Initial Prefixed Instruction support Jordan Niethe
                   ` (18 preceding siblings ...)
  2020-05-06  3:40 ` [PATCH v8 19/30] powerpc/xmon: Move insertion of breakpoint for xol'ing Jordan Niethe
@ 2020-05-06  3:40 ` Jordan Niethe
  2020-05-06  3:40 ` [PATCH v8 21/30] powerpc: Enable Prefixed Instructions Jordan Niethe
                   ` (11 subsequent siblings)
  31 siblings, 0 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-06  3:40 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, 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.

Reviewed-by: Alistair Popple <alistair@popple.id.au>
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 435fc8e9f45d..d946f7d6bb32 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -572,7 +572,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;
 
@@ -586,7 +586,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));
@@ -642,7 +642,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] 81+ messages in thread

* [PATCH v8 21/30] powerpc: Enable Prefixed Instructions
  2020-05-06  3:40 [PATCH v8 00/30] Initial Prefixed Instruction support Jordan Niethe
                   ` (19 preceding siblings ...)
  2020-05-06  3:40 ` [PATCH v8 20/30] powerpc: Make test_translate_branch() independent of instruction length Jordan Niethe
@ 2020-05-06  3:40 ` Jordan Niethe
  2020-05-06  3:40 ` [PATCH v8 22/30] powerpc: Define new SRR1 bits for a future ISA version Jordan Niethe
                   ` (10 subsequent siblings)
  31 siblings, 0 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-06  3:40 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, 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 da5cab038e25..773f76402392 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 3fca22276bb1..493a3fa0ac1a 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] 81+ messages in thread

* [PATCH v8 22/30] powerpc: Define new SRR1 bits for a future ISA version
  2020-05-06  3:40 [PATCH v8 00/30] Initial Prefixed Instruction support Jordan Niethe
                   ` (20 preceding siblings ...)
  2020-05-06  3:40 ` [PATCH v8 21/30] powerpc: Enable Prefixed Instructions Jordan Niethe
@ 2020-05-06  3:40 ` Jordan Niethe
  2020-05-08  2:26   ` Jordan Niethe
  2020-05-06  3:40 ` [PATCH v8 23/30] powerpc: Add prefixed instructions to instruction data type Jordan Niethe
                   ` (9 subsequent siblings)
  31 siblings, 1 reply; 81+ messages in thread
From: Jordan Niethe @ 2020-05-06  3:40 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, 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.

Reviewed-by: Alistair Popple <alistair@popple.id.au>
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 773f76402392..f95eb8f97756 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] 81+ messages in thread

* [PATCH v8 23/30] powerpc: Add prefixed instructions to instruction data type
  2020-05-06  3:40 [PATCH v8 00/30] Initial Prefixed Instruction support Jordan Niethe
                   ` (21 preceding siblings ...)
  2020-05-06  3:40 ` [PATCH v8 22/30] powerpc: Define new SRR1 bits for a future ISA version Jordan Niethe
@ 2020-05-06  3:40 ` Jordan Niethe
  2020-05-14  1:40   ` Jordan Niethe
                     ` (2 more replies)
  2020-05-06  3:40 ` [PATCH v8 24/30] powerpc: Test prefixed code patching Jordan Niethe
                   ` (8 subsequent siblings)
  31 siblings, 3 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-06  3:40 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, 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.

Reviewed-by: Alistair Popple <alistair@popple.id.au>
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
v6:  - Return false instead of 0 in ppc_inst_prefixed()
     - Fix up types for ppc32 so it compiles
     - remove ppc_inst_write()
     - __patching_instruction(): move flush out of condition
v8:  - style
     - Define and use OP_PREFIX instead of '1' (back from v3)
     - __patch_instruction() fix for big endian
---
 arch/powerpc/include/asm/inst.h       | 69 ++++++++++++++++++++++++---
 arch/powerpc/include/asm/kprobes.h    |  2 +-
 arch/powerpc/include/asm/ppc-opcode.h |  3 ++
 arch/powerpc/include/asm/uaccess.h    | 40 +++++++++++++++-
 arch/powerpc/include/asm/uprobes.h    |  2 +-
 arch/powerpc/kernel/crash_dump.c      |  2 +-
 arch/powerpc/kernel/optprobes.c       | 42 ++++++++--------
 arch/powerpc/kernel/optprobes_head.S  |  3 ++
 arch/powerpc/lib/code-patching.c      | 19 ++++++--
 arch/powerpc/lib/feature-fixups.c     |  5 +-
 arch/powerpc/lib/inst.c               | 41 ++++++++++++++++
 arch/powerpc/lib/sstep.c              |  4 +-
 arch/powerpc/xmon/xmon.c              |  4 +-
 arch/powerpc/xmon/xmon_bpts.S         |  2 +
 14 files changed, 200 insertions(+), 38 deletions(-)

diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h
index 2f3c9d5bcf7c..7868b80b610e 100644
--- a/arch/powerpc/include/asm/inst.h
+++ b/arch/powerpc/include/asm/inst.h
@@ -2,29 +2,79 @@
 #ifndef _ASM_INST_H
 #define _ASM_INST_H
 
+#include <asm/ppc-opcode.h>
 /*
  * Instruction data type for POWER
  */
 
 struct ppc_inst {
 	u32 val;
+#ifdef __powerpc64__
+	u32 suffix;
+#endif /* __powerpc64__ */
 } __packed;
 
-#define ppc_inst(x) ((struct ppc_inst){ .val = x })
-
 static inline u32 ppc_inst_val(struct ppc_inst x)
 {
 	return x.val;
 }
 
-static inline int ppc_inst_len(struct ppc_inst x)
+static inline int ppc_inst_primary_opcode(struct ppc_inst x)
 {
-	return sizeof(struct ppc_inst);
+	return ppc_inst_val(x) >> 26;
 }
 
-static inline int ppc_inst_primary_opcode(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 ppc_inst_val(x) >> 26;
+	return x.suffix;
+}
+
+static inline bool ppc_inst_prefixed(struct ppc_inst x)
+{
+	return (ppc_inst_primary_opcode(x) == 1) && ppc_inst_suffix(x) != 0xff;
+}
+
+static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
+{
+	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;
+
+	val = *(u32 *)ptr;
+	if ((val >> 26) == 1) {
+		suffix = *((u32 *)ptr + 1);
+		return ppc_inst_prefix(val, suffix);
+	} else {
+		return ppc_inst(val);
+	}
+}
+
+static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
+{
+	return *(u64 *)&x == *(u64 *)&y;
+}
+
+#else
+
+#define ppc_inst(x) ((struct ppc_inst){ .val = x })
+
+static inline bool ppc_inst_prefixed(struct ppc_inst x)
+{
+	return false;
+}
+
+static inline u32 ppc_inst_suffix(struct ppc_inst x)
+{
+	return 0;
 }
 
 static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
@@ -42,6 +92,13 @@ static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
 	return ppc_inst_val(x) == ppc_inst_val(y);
 }
 
+#endif /* __powerpc64__ */
+
+static inline int ppc_inst_len(struct ppc_inst x)
+{
+	return (ppc_inst_prefixed(x)) ? 8  : 4;
+}
+
 int probe_user_read_inst(struct ppc_inst *inst,
 			 struct ppc_inst *nip);
 int probe_kernel_read_inst(struct ppc_inst *inst,
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/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h
index c1df75edde44..2a39c716c343 100644
--- a/arch/powerpc/include/asm/ppc-opcode.h
+++ b/arch/powerpc/include/asm/ppc-opcode.h
@@ -158,6 +158,9 @@
 /* VMX Vector Store Instructions */
 #define OP_31_XOP_STVX          231
 
+/* Prefixed Instructions */
+#define OP_PREFIX		1
+
 #define OP_31   31
 #define OP_LWZ  32
 #define OP_STFS 52
diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h
index c0a35e4586a5..217897927926 100644
--- a/arch/powerpc/include/asm/uaccess.h
+++ b/arch/powerpc/include/asm/uaccess.h
@@ -105,11 +105,49 @@ static inline int __access_ok(unsigned long addr, unsigned long size,
 #define __put_user_inatomic(x, ptr) \
 	__put_user_nosleep((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
 
+#ifdef __powerpc64__
+#define __get_user_instr(x, ptr)			\
+({							\
+	long __gui_ret = 0;				\
+	unsigned long __gui_ptr = (unsigned long)ptr;	\
+	struct ppc_inst __gui_inst;			\
+	unsigned int prefix, suffix;			\
+	__gui_ret = __get_user(prefix, (unsigned int __user *)__gui_ptr);	\
+	if (!__gui_ret && (prefix >> 26) == OP_PREFIX) {	\
+		__gui_ret = __get_user(suffix,		\
+				       (unsigned int __user *)__gui_ptr + 1);	\
+		__gui_inst = ppc_inst_prefix(prefix, suffix);	\
+	} else {					\
+		__gui_inst = ppc_inst(prefix);		\
+	}						\
+	(x) = __gui_inst;				\
+	__gui_ret;					\
+})
+
+#define __get_user_instr_inatomic(x, ptr)		\
+({							\
+	long __gui_ret = 0;				\
+	unsigned long __gui_ptr = (unsigned long)ptr;	\
+	struct ppc_inst __gui_inst;			\
+	unsigned int prefix, suffix;			\
+	__gui_ret = __get_user_inatomic(prefix, (unsigned int __user *)__gui_ptr);	\
+	if (!__gui_ret && (prefix >> 26) == OP_PREFIX) {	\
+		__gui_ret = __get_user_inatomic(suffix,	\
+						(unsigned int __user *)__gui_ptr + 1);	\
+		__gui_inst = ppc_inst_prefix(prefix, suffix);	\
+	} else {					\
+		__gui_inst = ppc_inst(prefix);		\
+	}						\
+	(x) = __gui_inst;				\
+	__gui_ret;					\
+})
+#else
 #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))
+#endif
+
 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/crash_dump.c b/arch/powerpc/kernel/crash_dump.c
index 72bafb47e757..735e89337398 100644
--- a/arch/powerpc/kernel/crash_dump.c
+++ b/arch/powerpc/kernel/crash_dump.c
@@ -46,7 +46,7 @@ static void __init create_trampoline(unsigned long addr)
 	 * two instructions it doesn't require any registers.
 	 */
 	patch_instruction(p, ppc_inst(PPC_INST_NOP));
-	patch_branch(++p, addr + PHYSICAL_START, 0);
+	patch_branch((void *)p + 4, addr + PHYSICAL_START, 0);
 }
 
 void __init setup_kdump_trampoline(void)
diff --git a/arch/powerpc/kernel/optprobes.c b/arch/powerpc/kernel/optprobes.c
index 52c1ab3f85aa..a8e66603d12b 100644
--- a/arch/powerpc/kernel/optprobes.c
+++ b/arch/powerpc/kernel/optprobes.c
@@ -162,43 +162,43 @@ 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 */
+	/* lis reg,(op)@highest */
 	patch_instruction((struct ppc_inst *)addr,
-			  ppc_inst(PPC_INST_ADDIS | ___PPC_RT(3) |
+			  ppc_inst(PPC_INST_ADDIS | ___PPC_RT(reg) |
 				   ((val >> 48) & 0xffff)));
 	addr++;
 
-	/* ori r3,r3,(op)@higher */
+	/* ori reg,reg,(op)@higher */
 	patch_instruction((struct ppc_inst *)addr,
-			  ppc_inst(PPC_INST_ORI | ___PPC_RA(3) |
-				   ___PPC_RS(3) | ((val >> 32) & 0xffff)));
+			  ppc_inst(PPC_INST_ORI | ___PPC_RA(reg) |
+				   ___PPC_RS(reg) | ((val >> 32) & 0xffff)));
 	addr++;
 
-	/* rldicr r3,r3,32,31 */
+	/* rldicr reg,reg,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)));
+			  ppc_inst(PPC_INST_RLDICR | ___PPC_RA(reg) |
+				   ___PPC_RS(reg) | __PPC_SH64(32) | __PPC_ME64(31)));
 	addr++;
 
-	/* oris r3,r3,(op)@h */
+	/* oris reg,reg,(op)@h */
 	patch_instruction((struct ppc_inst *)addr,
-			  ppc_inst(PPC_INST_ORIS | ___PPC_RA(3) |
-				   ___PPC_RS(3) | ((val >> 16) & 0xffff)));
+			  ppc_inst(PPC_INST_ORIS | ___PPC_RA(reg) |
+				   ___PPC_RS(reg) | ((val >> 16) & 0xffff)));
 	addr++;
 
-	/* ori r3,r3,(op)@l */
+	/* ori reg,reg,(op)@l */
 	patch_instruction((struct ppc_inst *)addr,
-			  ppc_inst(PPC_INST_ORI | ___PPC_RA(3) |
-				   ___PPC_RS(3) | (val & 0xffff)));
+			  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;
@@ -249,7 +249,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()
@@ -282,7 +282,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/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index d946f7d6bb32..58b67b62d5d3 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -24,13 +24,24 @@ 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;
+	if (!ppc_inst_prefixed(instr)) {
+		__put_user_asm(ppc_inst_val(instr), patch_addr, err, "stw");
+		if (err)
+			return err;
+	} else {
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+		__put_user_asm((u64)ppc_inst_suffix(instr) << 32 |
+			       ppc_inst_val(instr), patch_addr, err, "std");
+#else
+		__put_user_asm((u64)ppc_inst_val(instr) << 32 |
+			       ppc_inst_suffix(instr), patch_addr, err, "std");
+#endif /* CONFIG_CPU_LITTLE_ENDIAN */
+		if (err)
+			return err;
+	}
 
 	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 2bd2b752de4f..a8238eff3a31 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/inst.c b/arch/powerpc/lib/inst.c
index 08dedd927268..eb6f9ee28ac6 100644
--- a/arch/powerpc/lib/inst.c
+++ b/arch/powerpc/lib/inst.c
@@ -3,9 +3,49 @@
  *  Copyright 2020, IBM Corporation.
  */
 
+#include <asm/ppc-opcode.h>
 #include <linux/uaccess.h>
 #include <asm/inst.h>
 
+#ifdef __powerpc64__
+int probe_user_read_inst(struct ppc_inst *inst,
+			 struct ppc_inst *nip)
+{
+	unsigned int val, suffix;
+	int err;
+
+	err = probe_user_read(&val, nip, sizeof(val));
+	if (err)
+		return err;
+	if ((val >> 26) == OP_PREFIX) {
+		err = probe_user_read(&suffix, (void *)nip + 4,
+				      sizeof(unsigned int));
+		*inst = ppc_inst_prefix(val, suffix);
+	} else {
+		*inst = ppc_inst(val);
+	}
+	return err;
+}
+
+int probe_kernel_read_inst(struct ppc_inst *inst,
+			   struct ppc_inst *src)
+{
+	unsigned int val, suffix;
+	int err;
+
+	err = probe_kernel_read(&val, src, sizeof(val));
+	if (err)
+		return err;
+	if ((val >> 26) == OP_PREFIX) {
+		err = probe_kernel_read(&suffix, (void *)src + 4,
+					sizeof(unsigned int));
+		*inst = ppc_inst_prefix(val, suffix);
+	} else {
+		*inst = ppc_inst(val);
+	}
+	return err;
+}
+#else
 int probe_user_read_inst(struct ppc_inst *inst,
 			 struct ppc_inst *nip)
 {
@@ -27,3 +67,4 @@ int probe_kernel_read_inst(struct ppc_inst *inst,
 	*inst = ppc_inst(val);
 	return err;
 }
+#endif /* __powerpc64__ */
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index 95a56bb1ba3f..ecd756c346fd 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 = ppc_inst_primary_opcode(instr);
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 4d6980d51456..647b3829c4eb 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -758,8 +758,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;
 	}
diff --git a/arch/powerpc/xmon/xmon_bpts.S b/arch/powerpc/xmon/xmon_bpts.S
index f3ad0ab50854..69726814cd27 100644
--- a/arch/powerpc/xmon/xmon_bpts.S
+++ b/arch/powerpc/xmon/xmon_bpts.S
@@ -4,6 +4,8 @@
 #include <asm/asm-offsets.h>
 #include "xmon_bpts.h"
 
+/* Prefixed instructions can not cross 64 byte boundaries */
+.align 6
 .global bpt_table
 bpt_table:
 	.space NBPTS * BPT_SIZE
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH v8 24/30] powerpc: Test prefixed code patching
  2020-05-06  3:40 [PATCH v8 00/30] Initial Prefixed Instruction support Jordan Niethe
                   ` (22 preceding siblings ...)
  2020-05-06  3:40 ` [PATCH v8 23/30] powerpc: Add prefixed instructions to instruction data type Jordan Niethe
@ 2020-05-06  3:40 ` Jordan Niethe
  2020-05-15  7:54   ` Jordan Niethe
  2020-05-06  3:40 ` [PATCH v8 25/30] powerpc: Test prefixed instructions in feature fixups Jordan Niethe
                   ` (7 subsequent siblings)
  31 siblings, 1 reply; 81+ messages in thread
From: Jordan Niethe @ 2020-05-06  3:40 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, Jordan Niethe, dja

Expand the code-patching self-tests to includes tests for patching
prefixed instructions.

Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v6: New to series
v8: Use OP_PREFIX
---
 arch/powerpc/lib/Makefile             |  2 +-
 arch/powerpc/lib/code-patching.c      | 21 +++++++++++++++++++++
 arch/powerpc/lib/test_code-patching.S | 20 ++++++++++++++++++++
 3 files changed, 42 insertions(+), 1 deletion(-)
 create mode 100644 arch/powerpc/lib/test_code-patching.S

diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index 546591848219..5e994cda8e40 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -16,7 +16,7 @@ CFLAGS_code-patching.o += -DDISABLE_BRANCH_PROFILING
 CFLAGS_feature-fixups.o += -DDISABLE_BRANCH_PROFILING
 endif
 
-obj-y += alloc.o code-patching.o feature-fixups.o pmem.o inst.o
+obj-y += alloc.o code-patching.o feature-fixups.o pmem.o inst.o test_code-patching.o
 
 ifndef CONFIG_KASAN
 obj-y	+=	string.o memcmp_$(BITS).o
diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index 58b67b62d5d3..aa51a44bc138 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -708,6 +708,24 @@ static void __init test_translate_branch(void)
 	vfree(buf);
 }
 
+#ifdef __powerpc64__
+static void __init test_prefixed_patching(void)
+{
+	extern unsigned int code_patching_test1[];
+	extern unsigned int code_patching_test1_expected[];
+	extern unsigned int end_code_patching_test1[];
+
+	__patch_instruction((struct ppc_inst *)code_patching_test1,
+			    ppc_inst_prefix(OP_PREFIX << 26, 0x00000000),
+			    (struct ppc_inst *)code_patching_test1);
+
+	check(!memcmp(code_patching_test1,
+		      code_patching_test1_expected,
+		      sizeof(unsigned int) *
+		      (end_code_patching_test1 - code_patching_test1)));
+}
+#endif
+
 static int __init test_code_patching(void)
 {
 	printk(KERN_DEBUG "Running code patching self-tests ...\n");
@@ -716,6 +734,9 @@ static int __init test_code_patching(void)
 	test_branch_bform();
 	test_create_function_call();
 	test_translate_branch();
+#ifdef __powerpc64__
+	test_prefixed_patching();
+#endif
 
 	return 0;
 }
diff --git a/arch/powerpc/lib/test_code-patching.S b/arch/powerpc/lib/test_code-patching.S
new file mode 100644
index 000000000000..a9be6107844e
--- /dev/null
+++ b/arch/powerpc/lib/test_code-patching.S
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020 IBM Corporation
+ */
+#include <asm/ppc-opcode.h>
+
+	.text
+
+#define globl(x)		\
+	.globl x;	\
+x:
+
+globl(code_patching_test1)
+	nop
+	nop
+globl(end_code_patching_test1)
+
+globl(code_patching_test1_expected)
+	.long OP_PREFIX << 26
+	.long 0x0000000
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH v8 25/30] powerpc: Test prefixed instructions in feature fixups
  2020-05-06  3:40 [PATCH v8 00/30] Initial Prefixed Instruction support Jordan Niethe
                   ` (23 preceding siblings ...)
  2020-05-06  3:40 ` [PATCH v8 24/30] powerpc: Test prefixed code patching Jordan Niethe
@ 2020-05-06  3:40 ` Jordan Niethe
  2020-05-15  7:57   ` Jordan Niethe
  2020-05-06  3:40 ` [PATCH v8 26/30] powerpc/xmon: Don't allow breakpoints on suffixes Jordan Niethe
                   ` (6 subsequent siblings)
  31 siblings, 1 reply; 81+ messages in thread
From: Jordan Niethe @ 2020-05-06  3:40 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, Jordan Niethe, dja

Expand the feature-fixups self-tests to includes tests for prefixed
instructions.

Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v6: New to series
v8: Use OP_PREFIX
---
 arch/powerpc/lib/feature-fixups-test.S | 69 ++++++++++++++++++++++++
 arch/powerpc/lib/feature-fixups.c      | 73 ++++++++++++++++++++++++++
 2 files changed, 142 insertions(+)

diff --git a/arch/powerpc/lib/feature-fixups-test.S b/arch/powerpc/lib/feature-fixups-test.S
index b12168c2447a..480172fbd024 100644
--- a/arch/powerpc/lib/feature-fixups-test.S
+++ b/arch/powerpc/lib/feature-fixups-test.S
@@ -7,6 +7,7 @@
 #include <asm/ppc_asm.h>
 #include <asm/synch.h>
 #include <asm/asm-compat.h>
+#include <asm/ppc-opcode.h>
 
 	.text
 
@@ -791,3 +792,71 @@ globl(lwsync_fixup_test_expected_SYNC)
 1:	or	1,1,1
 	sync
 
+globl(ftr_fixup_prefix1)
+	or	1,1,1
+	.long OP_PREFIX << 26
+	.long 0x0000000
+	or	2,2,2
+globl(end_ftr_fixup_prefix1)
+
+globl(ftr_fixup_prefix1_orig)
+	or	1,1,1
+	.long OP_PREFIX << 26
+	.long 0x0000000
+	or	2,2,2
+
+globl(ftr_fixup_prefix1_expected)
+	or	1,1,1
+	nop
+	nop
+	or	2,2,2
+
+globl(ftr_fixup_prefix2)
+	or	1,1,1
+	.long OP_PREFIX << 26
+	.long 0x0000000
+	or	2,2,2
+globl(end_ftr_fixup_prefix2)
+
+globl(ftr_fixup_prefix2_orig)
+	or	1,1,1
+	.long OP_PREFIX << 26
+	.long 0x0000000
+	or	2,2,2
+
+globl(ftr_fixup_prefix2_alt)
+	.long OP_PREFIX << 26
+	.long 0x0000001
+
+globl(ftr_fixup_prefix2_expected)
+	or	1,1,1
+	.long OP_PREFIX << 26
+	.long 0x0000001
+	or	2,2,2
+
+globl(ftr_fixup_prefix3)
+	or	1,1,1
+	.long OP_PREFIX << 26
+	.long 0x0000000
+	or	2,2,2
+	or	3,3,3
+globl(end_ftr_fixup_prefix3)
+
+globl(ftr_fixup_prefix3_orig)
+	or	1,1,1
+	.long OP_PREFIX << 26
+	.long 0x0000000
+	or	2,2,2
+	or	3,3,3
+
+globl(ftr_fixup_prefix3_alt)
+	.long OP_PREFIX << 26
+	.long 0x0000001
+	nop
+
+globl(ftr_fixup_prefix3_expected)
+	or	1,1,1
+	.long OP_PREFIX << 26
+	.long 0x0000001
+	nop
+	or	3,3,3
diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c
index a8238eff3a31..5144854713e6 100644
--- a/arch/powerpc/lib/feature-fixups.c
+++ b/arch/powerpc/lib/feature-fixups.c
@@ -689,6 +689,74 @@ static void test_lwsync_macros(void)
 	}
 }
 
+#ifdef __powerpc64__
+static void __init test_prefix_patching(void)
+{
+	extern unsigned int ftr_fixup_prefix1[];
+	extern unsigned int end_ftr_fixup_prefix1[];
+	extern unsigned int ftr_fixup_prefix1_orig[];
+	extern unsigned int ftr_fixup_prefix1_expected[];
+	int size = sizeof(unsigned int) * (end_ftr_fixup_prefix1 - ftr_fixup_prefix1);
+
+	fixup.value = fixup.mask = 8;
+	fixup.start_off = calc_offset(&fixup, ftr_fixup_prefix1 + 1);
+	fixup.end_off = calc_offset(&fixup, ftr_fixup_prefix1 + 3);
+	fixup.alt_start_off = fixup.alt_end_off = 0;
+
+	/* Sanity check */
+	check(memcmp(ftr_fixup_prefix1, ftr_fixup_prefix1_orig, size) == 0);
+
+	patch_feature_section(0, &fixup);
+	check(memcmp(ftr_fixup_prefix1, ftr_fixup_prefix1_expected, size) == 0);
+	check(memcmp(ftr_fixup_prefix1, ftr_fixup_prefix1_orig, size) != 0);
+}
+
+static void __init test_prefix_alt_patching(void)
+{
+	extern unsigned int ftr_fixup_prefix2[];
+	extern unsigned int end_ftr_fixup_prefix2[];
+	extern unsigned int ftr_fixup_prefix2_orig[];
+	extern unsigned int ftr_fixup_prefix2_expected[];
+	extern unsigned int ftr_fixup_prefix2_alt[];
+	int size = sizeof(unsigned int) * (end_ftr_fixup_prefix2 - ftr_fixup_prefix2);
+
+	fixup.value = fixup.mask = 8;
+	fixup.start_off = calc_offset(&fixup, ftr_fixup_prefix2 + 1);
+	fixup.end_off = calc_offset(&fixup, ftr_fixup_prefix2 + 3);
+	fixup.alt_start_off = calc_offset(&fixup, ftr_fixup_prefix2_alt);
+	fixup.alt_end_off = calc_offset(&fixup, ftr_fixup_prefix2_alt + 2);
+	/* Sanity check */
+	check(memcmp(ftr_fixup_prefix2, ftr_fixup_prefix2_orig, size) == 0);
+
+	patch_feature_section(0, &fixup);
+	check(memcmp(ftr_fixup_prefix2, ftr_fixup_prefix2_expected, size) == 0);
+	check(memcmp(ftr_fixup_prefix2, ftr_fixup_prefix2_orig, size) != 0);
+}
+
+static void __init test_prefix_word_alt_patching(void)
+{
+	extern unsigned int ftr_fixup_prefix3[];
+	extern unsigned int end_ftr_fixup_prefix3[];
+	extern unsigned int ftr_fixup_prefix3_orig[];
+	extern unsigned int ftr_fixup_prefix3_expected[];
+	extern unsigned int ftr_fixup_prefix3_alt[];
+	int size = sizeof(unsigned int) * (end_ftr_fixup_prefix3 - ftr_fixup_prefix3);
+
+	fixup.value = fixup.mask = 8;
+	fixup.start_off = calc_offset(&fixup, ftr_fixup_prefix3 + 1);
+	fixup.end_off = calc_offset(&fixup, ftr_fixup_prefix3 + 4);
+	fixup.alt_start_off = calc_offset(&fixup, ftr_fixup_prefix3_alt);
+	fixup.alt_end_off = calc_offset(&fixup, ftr_fixup_prefix3_alt + 3);
+	/* Sanity check */
+	check(memcmp(ftr_fixup_prefix3, ftr_fixup_prefix3_orig, size) == 0);
+
+	patch_feature_section(0, &fixup);
+	check(memcmp(ftr_fixup_prefix3, ftr_fixup_prefix3_expected, size) == 0);
+	patch_feature_section(0, &fixup);
+	check(memcmp(ftr_fixup_prefix3, ftr_fixup_prefix3_orig, size) != 0);
+}
+#endif /* __powerpc64__ */
+
 static int __init test_feature_fixups(void)
 {
 	printk(KERN_DEBUG "Running feature fixup self-tests ...\n");
@@ -703,6 +771,11 @@ static int __init test_feature_fixups(void)
 	test_cpu_macros();
 	test_fw_macros();
 	test_lwsync_macros();
+#ifdef __powerpc64__
+	test_prefix_patching();
+	test_prefix_alt_patching();
+	test_prefix_word_alt_patching();
+#endif
 
 	return 0;
 }
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH v8 26/30] powerpc/xmon: Don't allow breakpoints on suffixes
  2020-05-06  3:40 [PATCH v8 00/30] Initial Prefixed Instruction support Jordan Niethe
                   ` (24 preceding siblings ...)
  2020-05-06  3:40 ` [PATCH v8 25/30] powerpc: Test prefixed instructions in feature fixups Jordan Niethe
@ 2020-05-06  3:40 ` Jordan Niethe
  2020-05-06  3:40 ` [PATCH v8 27/30] powerpc/kprobes: " Jordan Niethe
                   ` (5 subsequent siblings)
  31 siblings, 0 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-06  3:40 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, Jordan Niethe, dja

Do not allow placing xmon breakpoints on the suffix of a prefix
instruction.

Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v8: Add this back from v3
---
 arch/powerpc/xmon/xmon.c | 29 +++++++++++++++++++++++++++--
 1 file changed, 27 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 647b3829c4eb..d082c35c6638 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -889,8 +889,8 @@ static struct bpt *new_breakpoint(unsigned long a)
 static void insert_bpts(void)
 {
 	int i;
-	struct ppc_inst instr;
-	struct bpt *bp;
+	struct ppc_inst instr, instr2;
+	struct bpt *bp, *bp2;
 
 	bp = bpts;
 	for (i = 0; i < NBPTS; ++i, ++bp) {
@@ -908,6 +908,31 @@ static void insert_bpts(void)
 			bp->enabled = 0;
 			continue;
 		}
+		/*
+		 * Check the address is not a suffix by looking for a prefix in
+		 * front of it.
+		 */
+		if (mread_instr(bp->address - 4, &instr2) == 8) {
+			printf("Breakpoint at %lx is on the second word of a "
+			       "prefixed instruction, disabling it\n",
+			       bp->address);
+			bp->enabled = 0;
+			continue;
+		}
+		/*
+		 * We might still be a suffix - if the prefix has already been
+		 * replaced by a breakpoint we won't catch it with the above
+		 * test.
+		 */
+		bp2 = at_breakpoint(bp->address - 4);
+		if (bp2 && ppc_inst_prefixed(ppc_inst_read(bp2->instr))) {
+			printf("Breakpoint at %lx is on the second word of a "
+			       "prefixed instruction, disabling it\n",
+			       bp->address);
+			bp->enabled = 0;
+			continue;
+		}
+
 		patch_instruction(bp->instr, instr);
 		patch_instruction((void *)bp->instr + ppc_inst_len(instr),
 				  ppc_inst(bpinstr));
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH v8 27/30] powerpc/kprobes: Don't allow breakpoints on suffixes
  2020-05-06  3:40 [PATCH v8 00/30] Initial Prefixed Instruction support Jordan Niethe
                   ` (25 preceding siblings ...)
  2020-05-06  3:40 ` [PATCH v8 26/30] powerpc/xmon: Don't allow breakpoints on suffixes Jordan Niethe
@ 2020-05-06  3:40 ` Jordan Niethe
  2021-05-18 18:43   ` Christophe Leroy
  2020-05-06  3:40 ` [PATCH v8 28/30] powerpc: Support prefixed instructions in alignment handler Jordan Niethe
                   ` (4 subsequent siblings)
  31 siblings, 1 reply; 81+ messages in thread
From: Jordan Niethe @ 2020-05-06  3:40 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, Jordan Niethe, dja

Do not allow inserting breakpoints on the suffix of a prefix instruction
in kprobes.

Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v8: Add this back from v3
---
 arch/powerpc/kernel/kprobes.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index 33d54b091c70..227510df8c55 100644
--- a/arch/powerpc/kernel/kprobes.c
+++ b/arch/powerpc/kernel/kprobes.c
@@ -106,7 +106,9 @@ kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset)
 int arch_prepare_kprobe(struct kprobe *p)
 {
 	int ret = 0;
+	struct kprobe *prev;
 	struct ppc_inst insn = ppc_inst_read((struct ppc_inst *)p->addr);
+	struct ppc_inst prefix = ppc_inst_read((struct ppc_inst *)(p->addr - 1));
 
 	if ((unsigned long)p->addr & 0x03) {
 		printk("Attempt to register kprobe at an unaligned address\n");
@@ -114,6 +116,17 @@ int arch_prepare_kprobe(struct kprobe *p)
 	} else if (IS_MTMSRD(insn) || IS_RFID(insn) || IS_RFI(insn)) {
 		printk("Cannot register a kprobe on rfi/rfid or mtmsr[d]\n");
 		ret = -EINVAL;
+	} else if (ppc_inst_prefixed(prefix)) {
+		printk("Cannot register a kprobe on the second word of prefixed instruction\n");
+		ret = -EINVAL;
+	}
+	preempt_disable();
+	prev = get_kprobe(p->addr - 1);
+	preempt_enable_no_resched();
+	if (prev &&
+	    ppc_inst_prefixed(ppc_inst_read((struct ppc_inst *)prev->ainsn.insn))) {
+		printk("Cannot register a kprobe on the second word of prefixed instruction\n");
+		ret = -EINVAL;
 	}
 
 	/* insn must be on a special executable page on ppc64.  This is
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH v8 28/30] powerpc: Support prefixed instructions in alignment handler
  2020-05-06  3:40 [PATCH v8 00/30] Initial Prefixed Instruction support Jordan Niethe
                   ` (26 preceding siblings ...)
  2020-05-06  3:40 ` [PATCH v8 27/30] powerpc/kprobes: " Jordan Niethe
@ 2020-05-06  3:40 ` Jordan Niethe
  2020-05-14  6:14   ` Christophe Leroy
  2020-05-06  3:40 ` [PATCH v8 29/30] powerpc sstep: Add support for prefixed load/stores Jordan Niethe
                   ` (3 subsequent siblings)
  31 siblings, 1 reply; 81+ messages in thread
From: Jordan Niethe @ 2020-05-06  3:40 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, 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().

Reviewed-by: Alistair Popple <alistair@popple.id.au>
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 493a3fa0ac1a..105242cc2f28 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] 81+ messages in thread

* [PATCH v8 29/30] powerpc sstep: Add support for prefixed load/stores
  2020-05-06  3:40 [PATCH v8 00/30] Initial Prefixed Instruction support Jordan Niethe
                   ` (27 preceding siblings ...)
  2020-05-06  3:40 ` [PATCH v8 28/30] powerpc: Support prefixed instructions in alignment handler Jordan Niethe
@ 2020-05-06  3:40 ` Jordan Niethe
  2020-05-14  6:15   ` Christophe Leroy
  2020-05-15  7:59   ` Jordan Niethe
  2020-05-06  3:40 ` [PATCH v8 30/30] powerpc sstep: Add support for prefixed fixed-point arithmetic Jordan Niethe
                   ` (2 subsequent siblings)
  31 siblings, 2 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-06  3:40 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, 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
v6: - Compile on ppc32
    - Add back in + GETLENGTH(op->type)
v8: Use fallthrough; keyword
---
 arch/powerpc/include/asm/sstep.h |   4 +
 arch/powerpc/lib/sstep.c         | 163 ++++++++++++++++++++++++++++++-
 2 files changed, 165 insertions(+), 2 deletions(-)

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 ecd756c346fd..6794a7672ad5 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,9 @@ 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;
+#ifdef __powerpc64__
+	unsigned int suffixopcode, prefixtype, prefix_r;
+#endif
 	unsigned long int imm;
 	unsigned long int val, val2;
 	unsigned int mb, me, sh;
@@ -2652,6 +2693,124 @@ 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;
+				fallthrough;
+			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;
+				fallthrough;
+			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__ */
 
 	}
@@ -2760,7 +2919,7 @@ void emulate_update_regs(struct pt_regs *regs, struct instruction_op *op)
 {
 	unsigned long next_pc;
 
-	next_pc = truncate_if_32bit(regs->msr, regs->nip + 4);
+	next_pc = truncate_if_32bit(regs->msr, regs->nip + GETLENGTH(op->type));
 	switch (GETTYPE(op->type)) {
 	case COMPUTE:
 		if (op->type & SETREG)
@@ -3205,7 +3364,7 @@ int emulate_step(struct pt_regs *regs, struct ppc_inst instr)
 	return 0;
 
  instr_done:
-	regs->nip = truncate_if_32bit(regs->msr, regs->nip + 4);
+	regs->nip = truncate_if_32bit(regs->msr, regs->nip + GETLENGTH(op.type));
 	return 1;
 }
 NOKPROBE_SYMBOL(emulate_step);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH v8 30/30] powerpc sstep: Add support for prefixed fixed-point arithmetic
  2020-05-06  3:40 [PATCH v8 00/30] Initial Prefixed Instruction support Jordan Niethe
                   ` (28 preceding siblings ...)
  2020-05-06  3:40 ` [PATCH v8 29/30] powerpc sstep: Add support for prefixed load/stores Jordan Niethe
@ 2020-05-06  3:40 ` Jordan Niethe
  2020-05-14  6:15   ` Christophe Leroy
  2020-05-15  8:02   ` Jordan Niethe
  2020-05-14  5:31 ` [PATCH v8 00/30] Initial Prefixed Instruction support Christophe Leroy
  2020-05-20 10:59 ` Michael Ellerman
  31 siblings, 2 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-06  3:40 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, 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 6794a7672ad5..964fe7bbfce3 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -1337,6 +1337,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] 81+ messages in thread

* Re: [PATCH v8 11/30] powerpc: Use a datatype for instructions
  2020-05-06  3:40 ` [PATCH v8 11/30] powerpc: Use a datatype for instructions Jordan Niethe
@ 2020-05-08  1:51   ` Jordan Niethe
  2020-05-08  7:17     ` Christophe Leroy
  2020-05-08  2:15   ` Jordan Niethe
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 81+ messages in thread
From: Jordan Niethe @ 2020-05-08  1:51 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Alistair Popple, Nicholas Piggin, Balamuruhan S, naveen.n.rao,
	Daniel Axtens

On Wed, May 6, 2020 at 1:45 PM Jordan Niethe <jniethe5@gmail.com> 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 endianness 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.
>
> Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> ---
> v4: New to series
> v5: Add to epapr_paravirt.c, kgdb.c
> v6: - setup_32.c: machine_init(): Use type
>     - feature-fixups.c: do_final_fixups(): Use type
>     - optprobes.c: arch_prepare_optimized_kprobe(): change a void * to
>       struct ppc_inst *
>     - fault.c: store_updates_sp(): Use type
>     - Change ppc_inst_equal() implementation from memcpy()
> v7: - Fix compilation issue in early_init_dt_scan_epapr() and
>       do_patch_instruction() with CONFIG_STRICT_KERNEL_RWX
> v8: - style
>     - Use in crash_dump.c, mpc86xx_smp.c, smp.c
> ---
>  arch/powerpc/include/asm/code-patching.h  | 32 ++++-----
>  arch/powerpc/include/asm/inst.h           | 18 +++--
>  arch/powerpc/include/asm/sstep.h          |  5 +-
>  arch/powerpc/include/asm/uprobes.h        |  5 +-
>  arch/powerpc/kernel/align.c               |  4 +-
>  arch/powerpc/kernel/crash_dump.c          |  2 +-
>  arch/powerpc/kernel/epapr_paravirt.c      |  6 +-
>  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           | 64 +++++++++--------
>  arch/powerpc/kernel/setup_32.c            |  4 +-
>  arch/powerpc/kernel/trace/ftrace.c        | 83 ++++++++++++-----------
>  arch/powerpc/kernel/vecemu.c              |  5 +-
>  arch/powerpc/lib/code-patching.c          | 76 ++++++++++-----------
>  arch/powerpc/lib/feature-fixups.c         | 60 ++++++++--------
>  arch/powerpc/lib/sstep.c                  |  4 +-
>  arch/powerpc/lib/test_emulate_step.c      |  9 +--
>  arch/powerpc/mm/fault.c                   |  4 +-
>  arch/powerpc/perf/core-book3s.c           |  4 +-
>  arch/powerpc/platforms/86xx/mpc86xx_smp.c |  4 +-
>  arch/powerpc/platforms/powermac/smp.c     |  4 +-
>  arch/powerpc/xmon/xmon.c                  | 22 +++---
>  arch/powerpc/xmon/xmon_bpts.h             |  6 +-
>  26 files changed, 233 insertions(+), 211 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 0c5dc539160a..19d8bb7a1c2b 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_primary_opcode(u32 x)
> +static inline int ppc_inst_primary_opcode(struct ppc_inst x)
>  {
>         return ppc_inst_val(x) >> 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 ppc_inst_val(x) == ppc_inst_val(y);
>  }
>
>  #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 a63216da8cf1..9e66e6c62354 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/crash_dump.c b/arch/powerpc/kernel/crash_dump.c
> index 78e556b131db..72bafb47e757 100644
> --- a/arch/powerpc/kernel/crash_dump.c
> +++ b/arch/powerpc/kernel/crash_dump.c
> @@ -35,7 +35,7 @@ void __init reserve_kdump_trampoline(void)
>
>  static void __init create_trampoline(unsigned long addr)
>  {
> -       unsigned int *p = (unsigned int *)addr;
> +       struct ppc_inst *p = (struct ppc_inst *)addr;
>
>         /* The maximum range of a single instruction branch, is the current
>          * instruction's address + (32 MB - 4) bytes. For the trampoline we
> diff --git a/arch/powerpc/kernel/epapr_paravirt.c b/arch/powerpc/kernel/epapr_paravirt.c
> index e8eb72a65572..2ed14d4a47f5 100644
> --- a/arch/powerpc/kernel/epapr_paravirt.c
> +++ b/arch/powerpc/kernel/epapr_paravirt.c
> @@ -37,10 +37,10 @@ static int __init early_init_dt_scan_epapr(unsigned long node,
>                 return -1;
>
>         for (i = 0; i < (len / 4); i++) {
> -               u32 inst = ppc_inst(be32_to_cpu(insts[i]));
> -               patch_instruction(epapr_hypercall_start + i, inst);
> +               struct ppc_inst inst = ppc_inst(be32_to_cpu(insts[i]));
> +               patch_instruction((struct ppc_inst *)(epapr_hypercall_start + i), inst);
>  #if !defined(CONFIG_64BIT) || defined(CONFIG_PPC_BOOK3E_64)
> -               patch_instruction(epapr_ev_idle_start + i, inst);
> +               patch_instruction((struct ppc_inst *)(epapr_ev_idle_start + i), inst);
>  #endif
>         }
>
> diff --git a/arch/powerpc/kernel/hw_breakpoint.c b/arch/powerpc/kernel/hw_breakpoint.c
> index 46e09ac8b84a..2db9a7ac7bcb 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 92fa3070d905..a08ae5803622 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 067b094bfeff..cd23218c60bb 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 44006c4ca4f1..5a71fef71c22 100644
> --- a/arch/powerpc/kernel/optprobes.c
> +++ b/arch/powerpc/kernel/optprobes.c
> @@ -100,8 +100,9 @@ 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, &regs, *p->ainsn.insn) == 1) {
> +       if (!is_conditional_branch(*(struct ppc_inst *)p->ainsn.insn) &&
> +           analyse_instr(&op, &regs,
> +                         *(struct ppc_inst *)p->ainsn.insn) == 1) {
>                 emulate_update_regs(&regs, &op);
>                 nip = regs.nip;
>         }
> @@ -148,13 +149,15 @@ 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) |
> -                         ((val >> 16) & 0xffff)));
> +       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) |
> -                         ___PPC_RS(4) | (val & 0xffff)));
> +       patch_instruction((struct ppc_inst *)addr,
> +                         ppc_inst(PPC_INST_ORI | ___PPC_RA(4) |
> +                                  ___PPC_RS(4) | (val & 0xffff)));
>  }
>
>  /*
> @@ -164,34 +167,39 @@ 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) |
> -                         ((val >> 48) & 0xffff)));
> +       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) |
> -                         ___PPC_RS(3) | ((val >> 32) & 0xffff)));
> +       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) |
> -                         ___PPC_RS(3) | __PPC_SH64(32) | __PPC_ME64(31)));
> +       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) |
> -                         ___PPC_RS(3) | ((val >> 16) & 0xffff)));
> +       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) |
> -                         ___PPC_RS(3) | (val & 0xffff)));
> +       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 +239,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,
> +               rc = patch_instruction((struct ppc_inst *)(buff + i),
>                                        ppc_inst(*(optprobe_template_entry + i)));
>                 if (rc < 0)
>                         goto error;
> @@ -254,20 +262,22 @@ 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
> @@ -277,7 +287,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((struct ppc_inst *)(buff + TMPL_RET_IDX), (unsigned long)nip, 0);
>
>         flush_icache_range((unsigned long)buff,
>                            (unsigned long)(&buff[TMPL_END_IDX]));
> @@ -309,7 +319,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;
>
> @@ -321,9 +331,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 0536e4aed330..15f0a7c84944 100644
> --- a/arch/powerpc/kernel/setup_32.c
> +++ b/arch/powerpc/kernel/setup_32.c
> @@ -74,8 +74,8 @@ 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 int insn;
> +       struct ppc_inst *addr = (struct ppc_inst *)patch_site_addr(&patch__memset_nocache);
> +       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 cbb19af4a72a..3117ed675735 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))) {
> @@ -208,7 +208,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;
>         }
> @@ -221,7 +221,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;
> @@ -280,7 +280,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;
> @@ -291,7 +291,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
> @@ -328,9 +328,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? */
> @@ -379,7 +380,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;
>         }
> @@ -395,7 +396,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))) {
> @@ -423,7 +424,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;
>         }
> @@ -435,7 +436,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,
> @@ -488,7 +489,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:
> @@ -506,7 +507,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)))
> @@ -518,8 +519,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;
> @@ -584,7 +585,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 */
> @@ -604,7 +605,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");
> @@ -613,7 +614,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
>
>         pr_devel("write to %lx\n", rec->ip);
>
> -       if (patch_instruction((unsigned int *)ip, op))
> +       if (patch_instruction((struct ppc_inst *)ip, op))
>                 return -EPERM;
>
>         return 0;
> @@ -623,7 +624,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;
>
> @@ -671,7 +672,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,
> @@ -710,7 +711,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;
> @@ -758,7 +759,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;
>                 }
> @@ -786,12 +787,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;
>         }
> @@ -804,7 +805,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,
> @@ -844,10 +845,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);
>
> @@ -855,7 +856,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);
>         }
> @@ -929,7 +930,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);
> @@ -942,7 +943,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 a544590b90e5..3dd70eeb10c5 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 d298bb16936e..1dff9d9d6645 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;
> @@ -161,8 +161,7 @@ static int do_patch_instruction(unsigned int *addr, unsigned int instr)
>                 goto out;
>         }
>
> -       patch_addr = (unsigned int *)(text_poke_addr) +
> -                       ((kaddr & ~PAGE_MASK) / sizeof(unsigned int));
> +       patch_addr = (struct ppc_inst *)(text_poke_addr + (kaddr & ~PAGE_MASK));
>
>         __patch_instruction(addr, instr, patch_addr);
>
> @@ -177,14 +176,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 +194,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 +228,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_primary_opcode(instr);
>
> @@ -247,13 +246,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 +262,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 +281,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_primary_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 +309,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 +330,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 +346,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 +356,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,8 +364,8 @@ 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;
>
> @@ -392,7 +391,7 @@ void __patch_exception(int exc, unsigned long addr)
>          * instruction of the exception, not the first one
>          */
>
> -       patch_branch(ibase + (exc / 4) + 1, addr, 0);
> +       patch_branch((struct ppc_inst *)(ibase + (exc / 4) + 1), addr, 0);
>  }
>  #endif
>
> @@ -409,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;
> @@ -484,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);
> @@ -500,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;
> @@ -570,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..fb6e8e8abf4e 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,17 @@ 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 +210,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 +263,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 +298,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 +341,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 +375,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 ;
> @@ -390,18 +392,18 @@ void do_lwsync_fixups(unsigned long value, void *fixup_start, void *fixup_end)
>  static void do_final_fixups(void)
>  {
>  #if defined(CONFIG_PPC64) && defined(CONFIG_RELOCATABLE)
> -       int *src, *dest;
> +       struct ppc_inst *src, *dest;
>         unsigned long length;
>
>         if (PHYSICAL_START == 0)
>                 return;
>
> -       src = (int *)(KERNELBASE + PHYSICAL_START);
> -       dest = (int *)KERNELBASE;
> -       length = (__end_interrupts - _stext) / sizeof(int);
> +       src = (struct ppc_inst *)(KERNELBASE + PHYSICAL_START);
> +       dest = (struct ppc_inst *)KERNELBASE;
> +       length = (__end_interrupts - _stext) / sizeof(struct ppc_inst);
>
>         while (length--) {
> -               raw_patch_instruction(dest, ppc_inst(*src));
> +               raw_patch_instruction(dest, *src);
>                 src++;
>                 dest++;
>         }
> diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
> index 7f7be154da7e..95a56bb1ba3f 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 b928b21feac1..46af80279ebc 100644
> --- a/arch/powerpc/lib/test_emulate_step.c
> +++ b/arch/powerpc/lib/test_emulate_step.c
> @@ -462,7 +462,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];
>  };
> @@ -843,7 +843,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;
>
> @@ -861,7 +861,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;
> @@ -892,7 +892,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/mm/fault.c b/arch/powerpc/mm/fault.c
> index 0e7e145d5cad..4a50f125ec18 100644
> --- a/arch/powerpc/mm/fault.c
> +++ b/arch/powerpc/mm/fault.c
> @@ -47,7 +47,7 @@
>   * Check whether the instruction inst is a store using
>   * an update addressing form which will update r1.
>   */
> -static bool store_updates_sp(unsigned int inst)
> +static bool store_updates_sp(struct ppc_inst inst)
>  {
>         /* check for 1 in the rA field */
>         if (((ppc_inst_val(inst) >> 16) & 0x1f) != 1)
> @@ -279,7 +279,7 @@ static bool bad_stack_expansion(struct pt_regs *regs, unsigned long address,
>
>                 if ((flags & FAULT_FLAG_WRITE) && (flags & FAULT_FLAG_USER) &&
>                     access_ok(nip, sizeof(*nip))) {
> -                       unsigned int inst;
> +                       struct ppc_inst inst;
>
>                         if (!probe_user_read(&inst, nip, sizeof(inst)))
>                                 return !store_updates_sp(inst);
> diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
> index 3dcfecf858f3..13b9dd5e4a76 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/platforms/86xx/mpc86xx_smp.c b/arch/powerpc/platforms/86xx/mpc86xx_smp.c
> index 31540ebf1e29..dba3aa73c062 100644
> --- a/arch/powerpc/platforms/86xx/mpc86xx_smp.c
> +++ b/arch/powerpc/platforms/86xx/mpc86xx_smp.c
> @@ -73,7 +73,7 @@ smp_86xx_kick_cpu(int nr)
>
>         /* Setup fake reset vector to call __secondary_start_mpc86xx. */
>         target = (unsigned long) __secondary_start_mpc86xx;
> -       patch_branch(vector, target, BRANCH_SET_LINK);
> +       patch_branch((struct ppc_inst *)vector, target, BRANCH_SET_LINK);
>
>         /* Kick that CPU */
>         smp_86xx_release_core(nr);
> @@ -83,7 +83,7 @@ smp_86xx_kick_cpu(int nr)
>                 mdelay(1);
>
>         /* Restore the exception vector */
> -       patch_instruction(vector, ppc_inst(save_vector));
> +       patch_instruction((struct ppc_inst *)vector, ppc_inst(save_vector));
>
>         local_irq_restore(flags);
>
> diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
> index 44a00990af9d..9969c07035b6 100644
> --- a/arch/powerpc/platforms/powermac/smp.c
> +++ b/arch/powerpc/platforms/powermac/smp.c
> @@ -814,7 +814,7 @@ static int smp_core99_kick_cpu(int nr)
>          *   b __secondary_start_pmac_0 + nr*8
>          */
>         target = (unsigned long) __secondary_start_pmac_0 + nr * 8;
> -       patch_branch(vector, target, BRANCH_SET_LINK);
> +       patch_branch((struct ppc_inst *)vector, target, BRANCH_SET_LINK);
>
>         /* Put some life in our friend */
>         pmac_call_feature(PMAC_FTR_RESET_CPU, NULL, nr, 0);
> @@ -827,7 +827,7 @@ static int smp_core99_kick_cpu(int nr)
>         mdelay(1);
>
>         /* Restore our exception vector */
> -       patch_instruction(vector, ppc_inst(save_vector));
> +       patch_instruction((struct ppc_inst *)vector, ppc_inst(save_vector));
>
>         local_irq_restore(flags);
>         if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu done", 0x347);
> diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
> index 2e8ed8cdcf28..e0132d6d24d0 100644
> --- a/arch/powerpc/xmon/xmon.c
> +++ b/arch/powerpc/xmon/xmon.c
> @@ -100,7 +100,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;
> @@ -876,8 +876,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;
>                 }
>         }
> @@ -889,7 +889,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;
> @@ -911,8 +911,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;
> @@ -940,7 +940,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) {
> @@ -949,7 +949,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);
>         }
> @@ -1156,7 +1156,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();
> @@ -1322,7 +1322,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)) {
> @@ -2848,7 +2848,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;
> diff --git a/arch/powerpc/xmon/xmon_bpts.h b/arch/powerpc/xmon/xmon_bpts.h
> index b7e94375db86..57e6fb03de48 100644
> --- a/arch/powerpc/xmon/xmon_bpts.h
> +++ b/arch/powerpc/xmon/xmon_bpts.h
> @@ -4,11 +4,11 @@
>
>  #define NBPTS  256
>  #ifndef __ASSEMBLY__
> -#define BPT_SIZE       (sizeof(unsigned int) * 2)
> -#define BPT_WORDS      (BPT_SIZE / sizeof(unsigned int))
> +#include <asm/inst.h>
> +#define BPT_SIZE       (sizeof(struct ppc_inst) * 2)
> +#define BPT_WORDS      (BPT_SIZE / sizeof(struct ppc_inst))
>
>  extern unsigned int bpt_table[NBPTS * BPT_WORDS];
> -
>  #endif /* __ASSEMBLY__ */
>
>  #endif /* XMON_BPTS_H */
> --
> 2.17.1
>

Hi mpe,
Could you add this fixup.
--- a/arch/powerpc/lib/feature-fixups.c
+++ b/arch/powerpc/lib/feature-fixups.c
@@ -356,7 +356,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(PPC_INST_NOP));
+               patch_instruction((struct ppc_inst *)start,
ppc_inst(PPC_INST_NOP));
        }
 }

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 11/30] powerpc: Use a datatype for instructions
  2020-05-06  3:40 ` [PATCH v8 11/30] powerpc: Use a datatype for instructions Jordan Niethe
  2020-05-08  1:51   ` Jordan Niethe
@ 2020-05-08  2:15   ` Jordan Niethe
  2020-05-08  9:23   ` kbuild test robot
  2020-05-17 10:48   ` Jordan Niethe
  3 siblings, 0 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-08  2:15 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Alistair Popple, Nicholas Piggin, Balamuruhan S, naveen.n.rao,
	Daniel Axtens

Hi mpe,
On Wed, May 6, 2020 at 1:45 PM Jordan Niethe <jniethe5@gmail.com> 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

s/a future ISA version will introduce/ISA v3.1 introduces/

> 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 endianness 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.
>
> Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> ---

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 22/30] powerpc: Define new SRR1 bits for a future ISA version
  2020-05-06  3:40 ` [PATCH v8 22/30] powerpc: Define new SRR1 bits for a future ISA version Jordan Niethe
@ 2020-05-08  2:26   ` Jordan Niethe
  0 siblings, 0 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-08  2:26 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Alistair Popple, Nicholas Piggin, Balamuruhan S, naveen.n.rao,
	Daniel Axtens

Hi mpe,
Could you please take some changes for the commit message.
In the patch title
s/a future ISA version/ISA v3.1/

On Wed, May 6, 2020 at 1:47 PM Jordan Niethe <jniethe5@gmail.com> wrote:
>
> 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

s/A future ISA version/ISA v3.1/

> 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.
>
> Reviewed-by: Alistair Popple <alistair@popple.id.au>
> Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> ---
> v2: Combined all the commits concerning SRR1 bits.
> ---

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 11/30] powerpc: Use a datatype for instructions
  2020-05-08  1:51   ` Jordan Niethe
@ 2020-05-08  7:17     ` Christophe Leroy
  2020-05-11  1:19       ` Jordan Niethe
  0 siblings, 1 reply; 81+ messages in thread
From: Christophe Leroy @ 2020-05-08  7:17 UTC (permalink / raw)
  To: Jordan Niethe, linuxppc-dev
  Cc: Alistair Popple, Nicholas Piggin, Balamuruhan S, naveen.n.rao,
	Daniel Axtens



Le 08/05/2020 à 03:51, Jordan Niethe a écrit :
> On Wed, May 6, 2020 at 1:45 PM Jordan Niethe <jniethe5@gmail.com> 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 endianness 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.
>>
>> Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
>> ---
>> v4: New to series
>> v5: Add to epapr_paravirt.c, kgdb.c
>> v6: - setup_32.c: machine_init(): Use type
>>      - feature-fixups.c: do_final_fixups(): Use type
>>      - optprobes.c: arch_prepare_optimized_kprobe(): change a void * to
>>        struct ppc_inst *
>>      - fault.c: store_updates_sp(): Use type
>>      - Change ppc_inst_equal() implementation from memcpy()
>> v7: - Fix compilation issue in early_init_dt_scan_epapr() and
>>        do_patch_instruction() with CONFIG_STRICT_KERNEL_RWX
>> v8: - style
>>      - Use in crash_dump.c, mpc86xx_smp.c, smp.c
>> ---

[...]

>>
> 
> Hi mpe,
> Could you add this fixup.
> --- a/arch/powerpc/lib/feature-fixups.c
> +++ b/arch/powerpc/lib/feature-fixups.c
> @@ -356,7 +356,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(PPC_INST_NOP));
> +               patch_instruction((struct ppc_inst *)start,
> ppc_inst(PPC_INST_NOP));
>          }
>   }
> 

Why not declare stard and end as struct ppc_inst ? Wouldn't it be 
cleaner than a cast ?

Christophe

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 11/30] powerpc: Use a datatype for instructions
  2020-05-06  3:40 ` [PATCH v8 11/30] powerpc: Use a datatype for instructions Jordan Niethe
  2020-05-08  1:51   ` Jordan Niethe
  2020-05-08  2:15   ` Jordan Niethe
@ 2020-05-08  9:23   ` kbuild test robot
  2020-05-17 10:48   ` Jordan Niethe
  3 siblings, 0 replies; 81+ messages in thread
From: kbuild test robot @ 2020-05-08  9:23 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 3308 bytes --]

Hi Jordan,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on powerpc/next]
[also build test ERROR on v5.7-rc4 next-20200507]
[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/20200506-171154
base:   https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next
config: powerpc64-randconfig-r034-20200508 (attached as .config)
compiler: powerpc64-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
        COMPILER_INSTALL_PATH=$HOME/0day GCC_VERSION=9.3.0 make.cross ARCH=powerpc64 

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 'patch_btb_flush_section':
>> arch/powerpc/lib/feature-fixups.c:359:21: error: passing argument 1 of 'patch_instruction' from incompatible pointer type [-Werror=incompatible-pointer-types]
     359 |   patch_instruction(start, ppc_inst(PPC_INST_NOP));
         |                     ^~~~~
         |                     |
         |                     unsigned int *
   In file included from arch/powerpc/lib/feature-fixups.c:18:
   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: some warnings being treated as errors

vim +/patch_instruction +359 arch/powerpc/lib/feature-fixups.c

76a5eaa38b15dd Diana Craciun 2018-12-12  350  
76a5eaa38b15dd Diana Craciun 2018-12-12  351  static void patch_btb_flush_section(long *curr)
76a5eaa38b15dd Diana Craciun 2018-12-12  352  {
76a5eaa38b15dd Diana Craciun 2018-12-12  353  	unsigned int *start, *end;
76a5eaa38b15dd Diana Craciun 2018-12-12  354  
76a5eaa38b15dd Diana Craciun 2018-12-12  355  	start = (void *)curr + *curr;
76a5eaa38b15dd Diana Craciun 2018-12-12  356  	end = (void *)curr + *(curr + 1);
76a5eaa38b15dd Diana Craciun 2018-12-12  357  	for (; start < end; start++) {
76a5eaa38b15dd Diana Craciun 2018-12-12  358  		pr_devel("patching dest %lx\n", (unsigned long)start);
db67542527cd8c Jordan Niethe 2020-05-06 @359  		patch_instruction(start, ppc_inst(PPC_INST_NOP));
76a5eaa38b15dd Diana Craciun 2018-12-12  360  	}
76a5eaa38b15dd Diana Craciun 2018-12-12  361  }
76a5eaa38b15dd Diana Craciun 2018-12-12  362  

:::::: The code@line 359 was first introduced by commit
:::::: db67542527cd8cd5c7002b8ccb222c5ca1946f61 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: 33174 bytes --]

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 11/30] powerpc: Use a datatype for instructions
  2020-05-08  7:17     ` Christophe Leroy
@ 2020-05-11  1:19       ` Jordan Niethe
  0 siblings, 0 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-11  1:19 UTC (permalink / raw)
  To: Christophe Leroy
  Cc: Alistair Popple, Nicholas Piggin, Balamuruhan S, naveen.n.rao,
	linuxppc-dev, Daniel Axtens

On Fri, May 8, 2020 at 5:17 PM Christophe Leroy
<christophe.leroy@csgroup.eu> wrote:
>
>
>
> Le 08/05/2020 à 03:51, Jordan Niethe a écrit :
> > On Wed, May 6, 2020 at 1:45 PM Jordan Niethe <jniethe5@gmail.com> 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 endianness 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.
> >>
> >> Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> >> ---
> >> v4: New to series
> >> v5: Add to epapr_paravirt.c, kgdb.c
> >> v6: - setup_32.c: machine_init(): Use type
> >>      - feature-fixups.c: do_final_fixups(): Use type
> >>      - optprobes.c: arch_prepare_optimized_kprobe(): change a void * to
> >>        struct ppc_inst *
> >>      - fault.c: store_updates_sp(): Use type
> >>      - Change ppc_inst_equal() implementation from memcpy()
> >> v7: - Fix compilation issue in early_init_dt_scan_epapr() and
> >>        do_patch_instruction() with CONFIG_STRICT_KERNEL_RWX
> >> v8: - style
> >>      - Use in crash_dump.c, mpc86xx_smp.c, smp.c
> >> ---
>
> [...]
>
> >>
> >
> > Hi mpe,
> > Could you add this fixup.
> > --- a/arch/powerpc/lib/feature-fixups.c
> > +++ b/arch/powerpc/lib/feature-fixups.c
> > @@ -356,7 +356,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(PPC_INST_NOP));
> > +               patch_instruction((struct ppc_inst *)start,
> > ppc_inst(PPC_INST_NOP));
> >          }
> >   }
> >
>
> Why not declare stard and end as struct ppc_inst ? Wouldn't it be
> cleaner than a cast ?
What I was thinking was if struct ppc_inst was the prefixed version,
then start++ would increase it by 8 bytes, but the NOPs that are being
patched in are only 4 bytes.
>
> Christophe

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 13/30] powerpc: Add a probe_user_read_inst() function
  2020-05-06  3:40 ` [PATCH v8 13/30] powerpc: Add a probe_user_read_inst() function Jordan Niethe
@ 2020-05-13 12:52   ` Michael Ellerman
  2020-05-13 23:51     ` Jordan Niethe
  2020-05-14  5:46   ` Christophe Leroy
  1 sibling, 1 reply; 81+ messages in thread
From: Michael Ellerman @ 2020-05-13 12:52 UTC (permalink / raw)
  To: Jordan Niethe, linuxppc-dev
  Cc: christophe.leroy, alistair, npiggin, bala24, Jordan Niethe,
	naveen.n.rao, dja

Jordan Niethe <jniethe5@gmail.com> writes:
> diff --git a/arch/powerpc/lib/inst.c b/arch/powerpc/lib/inst.c
> new file mode 100644
> index 000000000000..eaf786afad2b
> --- /dev/null
> +++ b/arch/powerpc/lib/inst.c
> @@ -0,0 +1,18 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + *  Copyright 2020, IBM Corporation.
> + */
> +
> +#include <linux/uaccess.h>
> +#include <asm/inst.h>
> +
> +int probe_user_read_inst(struct ppc_inst *inst,
> +			 struct ppc_inst *nip)
> +{
> +	unsigned int val;
> +	int err;
> +
> +	err = probe_user_read(&val, nip, sizeof(val));
> +	*inst = ppc_inst(val);

We shouldn't be storing to *inst if the read failed?

I changed it to:

+	if (!err)
+		*inst = ppc_inst(val);
+

Similarly for probe_kernel_read_inst().

cheers

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 16/30] powerpc: Define and use __get_user_instr{, inatomic}()
  2020-05-06  3:40 ` [PATCH v8 16/30] powerpc: Define and use __get_user_instr{, inatomic}() Jordan Niethe
@ 2020-05-13 14:18   ` Michael Ellerman
  2020-05-13 23:54     ` Jordan Niethe
  0 siblings, 1 reply; 81+ messages in thread
From: Michael Ellerman @ 2020-05-13 14:18 UTC (permalink / raw)
  To: Jordan Niethe, linuxppc-dev
  Cc: christophe.leroy, alistair, npiggin, bala24, Jordan Niethe,
	naveen.n.rao, dja

Jordan Niethe <jniethe5@gmail.com> writes:
> Define specific __get_user_instr() and __get_user_instr_inatomic()
> macros for reading instructions from user space.

At least for fix_alignment() we could be coming from the kernel, not
sure about the other cases.

I can tweak the change log.

> 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))

I'm not super keen on adding new __ versions, which lack the access_ok()
check, but I guess we have to.

> diff --git a/arch/powerpc/kernel/vecemu.c b/arch/powerpc/kernel/vecemu.c
> index 3dd70eeb10c5..60ed5aea8d4e 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;

That drops the access_ok() check, which is not OK, at least without a
reasonable justification.

Given it's regs->nip I guess it should be safe, but it should still be
called out. Or preferably switched to __get_user() in a precursor patch.

cheers

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 13/30] powerpc: Add a probe_user_read_inst() function
  2020-05-13 12:52   ` Michael Ellerman
@ 2020-05-13 23:51     ` Jordan Niethe
  0 siblings, 0 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-13 23:51 UTC (permalink / raw)
  To: Michael Ellerman
  Cc: Christophe Leroy, Alistair Popple, Nicholas Piggin,
	Balamuruhan S, naveen.n.rao, linuxppc-dev, Daniel Axtens

On Wed, May 13, 2020 at 10:52 PM Michael Ellerman <mpe@ellerman.id.au> wrote:
>
> Jordan Niethe <jniethe5@gmail.com> writes:
> > diff --git a/arch/powerpc/lib/inst.c b/arch/powerpc/lib/inst.c
> > new file mode 100644
> > index 000000000000..eaf786afad2b
> > --- /dev/null
> > +++ b/arch/powerpc/lib/inst.c
> > @@ -0,0 +1,18 @@
> > +// SPDX-License-Identifier: GPL-2.0-or-later
> > +/*
> > + *  Copyright 2020, IBM Corporation.
> > + */
> > +
> > +#include <linux/uaccess.h>
> > +#include <asm/inst.h>
> > +
> > +int probe_user_read_inst(struct ppc_inst *inst,
> > +                      struct ppc_inst *nip)
> > +{
> > +     unsigned int val;
> > +     int err;
> > +
> > +     err = probe_user_read(&val, nip, sizeof(val));
> > +     *inst = ppc_inst(val);
>
> We shouldn't be storing to *inst if the read failed?
Good point.
>
> I changed it to:
>
> +       if (!err)
> +               *inst = ppc_inst(val);
> +
>
> Similarly for probe_kernel_read_inst().
Thanks.
>
> cheers

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 16/30] powerpc: Define and use __get_user_instr{, inatomic}()
  2020-05-13 14:18   ` Michael Ellerman
@ 2020-05-13 23:54     ` Jordan Niethe
  2020-05-14  1:43       ` Jordan Niethe
  0 siblings, 1 reply; 81+ messages in thread
From: Jordan Niethe @ 2020-05-13 23:54 UTC (permalink / raw)
  To: Michael Ellerman
  Cc: Christophe Leroy, Alistair Popple, Nicholas Piggin,
	Balamuruhan S, naveen.n.rao, linuxppc-dev, Daniel Axtens

On Thu, May 14, 2020 at 12:17 AM Michael Ellerman <mpe@ellerman.id.au> wrote:
>
> Jordan Niethe <jniethe5@gmail.com> writes:
> > Define specific __get_user_instr() and __get_user_instr_inatomic()
> > macros for reading instructions from user space.
>
> At least for fix_alignment() we could be coming from the kernel, not
> sure about the other cases.
>
> I can tweak the change log.
>
> > 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))
>
> I'm not super keen on adding new __ versions, which lack the access_ok()
> check, but I guess we have to.
>
> > diff --git a/arch/powerpc/kernel/vecemu.c b/arch/powerpc/kernel/vecemu.c
> > index 3dd70eeb10c5..60ed5aea8d4e 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;
>
> That drops the access_ok() check, which is not OK, at least without a
> reasonable justification.
>
> Given it's regs->nip I guess it should be safe, but it should still be
> called out. Or preferably switched to __get_user() in a precursor patch.
Or should I add a get_user_instr() that includes the check?
>
> cheers

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 23/30] powerpc: Add prefixed instructions to instruction data type
  2020-05-06  3:40 ` [PATCH v8 23/30] powerpc: Add prefixed instructions to instruction data type Jordan Niethe
@ 2020-05-14  1:40   ` Jordan Niethe
  2020-05-14  6:11   ` Christophe Leroy
  2020-05-16 11:54   ` [PATCH v8 22.5/30] powerpc/optprobes: Add register argument to patch_imm64_load_insns() Michael Ellerman
  2 siblings, 0 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-14  1:40 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Christophe Leroy, Alistair Popple, Nicholas Piggin,
	Balamuruhan S, naveen.n.rao, Daniel Axtens

Hi mpe,
Relating to your message on [PATCH v8 16/30] powerpc: Define and use
__get_user_instr{,inatomic}() - could you please take this.

diff --git a/arch/powerpc/include/asm/uaccess.h
b/arch/powerpc/include/asm/uaccess.h
--- a/arch/powerpc/include/asm/uaccess.h
+++ b/arch/powerpc/include/asm/uaccess.h
@@ -106,6 +106,24 @@ static inline int __access_ok(unsigned long addr,
unsigned long size,
     __put_user_nosleep((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))

 #ifdef __powerpc64__
+#define get_user_instr(x, ptr)                 \
+({                            \
+    long __gui_ret = 0;                \
+    unsigned long __gui_ptr = (unsigned long)ptr;    \
+    struct ppc_inst __gui_inst;            \
+    unsigned int prefix, suffix;            \
+    __gui_ret = get_user(prefix, (unsigned int __user *)__gui_ptr);    \
+    if (!__gui_ret && (prefix >> 26) == OP_PREFIX) {    \
+        __gui_ret = get_user(suffix,        \
+                       (unsigned int __user *)__gui_ptr + 1);    \
+        __gui_inst = ppc_inst_prefix(prefix, suffix);    \
+    } else {                    \
+        __gui_inst = ppc_inst(prefix);        \
+    }                        \
+    (x) = __gui_inst;                \
+    __gui_ret;                    \
+})
+
 #define __get_user_instr(x, ptr)            \
 ({                            \
     long __gui_ret = 0;                \
@@ -142,6 +160,8 @@ static inline int __access_ok(unsigned long addr,
unsigned long size,
     __gui_ret;                    \
 })
 #else
+#define get_user_instr(x, ptr) \
+    get_user((x).val, (u32 *)(ptr))
 #define __get_user_instr(x, ptr) \
     __get_user_nocheck((x).val, (u32 *)(ptr), sizeof(u32), true)
 #define __get_user_instr_inatomic(x, ptr) \

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 16/30] powerpc: Define and use __get_user_instr{, inatomic}()
  2020-05-13 23:54     ` Jordan Niethe
@ 2020-05-14  1:43       ` Jordan Niethe
  0 siblings, 0 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-14  1:43 UTC (permalink / raw)
  To: Michael Ellerman
  Cc: Christophe Leroy, Alistair Popple, Nicholas Piggin,
	Balamuruhan S, naveen.n.rao, linuxppc-dev, Daniel Axtens

Hi mpe, could you please take this.

 arch/powerpc/include/asm/uaccess.h | 3 +++
 arch/powerpc/kernel/vecemu.c       | 2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/include/asm/uaccess.h
b/arch/powerpc/include/asm/uaccess.h
--- a/arch/powerpc/include/asm/uaccess.h
+++ b/arch/powerpc/include/asm/uaccess.h
@@ -105,6 +105,9 @@ 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((x).val, (u32 *)(ptr))
+
 #define __get_user_instr(x, ptr) \
     __get_user_nocheck((x).val, (u32 *)(ptr), sizeof(u32), true)

diff --git a/arch/powerpc/kernel/vecemu.c b/arch/powerpc/kernel/vecemu.c
index 60ed5aea8d4e..ae632569446f 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(instr, (void __user *)regs->nip))
+    if (get_user_instr(instr, (void __user *)regs->nip))
         return -EFAULT;

     word = ppc_inst_val(instr);

^ permalink raw reply related	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 00/30] Initial Prefixed Instruction support
  2020-05-06  3:40 [PATCH v8 00/30] Initial Prefixed Instruction support Jordan Niethe
                   ` (29 preceding siblings ...)
  2020-05-06  3:40 ` [PATCH v8 30/30] powerpc sstep: Add support for prefixed fixed-point arithmetic Jordan Niethe
@ 2020-05-14  5:31 ` Christophe Leroy
  2020-05-14 10:33   ` Jordan Niethe
  2020-05-20 10:59 ` Michael Ellerman
  31 siblings, 1 reply; 81+ messages in thread
From: Christophe Leroy @ 2020-05-14  5:31 UTC (permalink / raw)
  To: Jordan Niethe, linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, dja



Le 06/05/2020 à 05:40, Jordan Niethe a écrit :
> 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.
> 
> v8 incorporates feedback from Alistair Popple and Balamuruhan Suriyakumar.
> The major changes:
>      - Fix some style issues
>      - Fix __patch_instruction() on big endian
>      - Reintroduce v3's forbidding breakpoints on second word of prefix
>        instructions for kprobes and xmon. Missed this when changing to
>        using a data type.
>      - Use the data type in some places that were missed.

Checkpatch seems to report the following warnings for pmac32_defconfig, 
are they harmless ?

+arch/powerpc/kernel/align.c:307:13: warning: cast removes address space 
'<asn:1>' of expression
+arch/powerpc/kernel/align.c:307:13: warning: cast removes address space 
'<asn:1>' of expression
+arch/powerpc/kernel/align.c:307:13: warning: cast removes address space 
'<asn:1>' of expression
+arch/powerpc/kernel/align.c:307:13: warning: cast removes address space 
'<asn:1>' of expression
+arch/powerpc/kernel/align.c:307:13: warning: cast removes address space 
'<asn:1>' of expression
+arch/powerpc/kernel/align.c:307:13: warning: incorrect type in argument 
1 (different address spaces) expected void const volatile [noderef] 
<asn:1> * got unsigned int [usertype] *
+arch/powerpc/kernel/align.c:307:13: warning: incorrect type in 
initializer (different address spaces) expected unsigned int [noderef] 
<asn:1> *__gu_addr got unsigned int [usertype] *
+arch/powerpc/kernel/hw_breakpoint.c:XX:13: warning: cast removes 
address space '<asn:1>' of expression
+arch/powerpc/kernel/hw_breakpoint.c:XX:13: warning: cast removes 
address space '<asn:1>' of expression
+arch/powerpc/kernel/hw_breakpoint.c:XX:13: warning: cast removes 
address space '<asn:1>' of expression
+arch/powerpc/kernel/hw_breakpoint.c:XX:13: warning: cast removes 
address space '<asn:1>' of expression
+arch/powerpc/kernel/hw_breakpoint.c:XX:13: warning: cast removes 
address space '<asn:1>' of expression
-arch/powerpc/kernel/hw_breakpoint.c:XX:13: warning: incorrect type in 
argument 1 (different address spaces) expected void const volatile 
[noderef] <asn:1> * got unsigned int *
+arch/powerpc/kernel/hw_breakpoint.c:XX:13: warning: incorrect type in 
argument 1 (different address spaces) expected void const volatile 
[noderef] <asn:1> * got unsigned int [usertype] *
-arch/powerpc/kernel/hw_breakpoint.c:XX:13: warning: incorrect type in 
initializer (different address spaces) expected unsigned int [noderef] 
<asn:1> *__gu_addr got unsigned int *
+arch/powerpc/kernel/hw_breakpoint.c:XX:13: warning: incorrect type in 
initializer (different address spaces) expected unsigned int [noderef] 
<asn:1> *__gu_addr got unsigned int [usertype] *
+arch/powerpc/kernel/vecemu.c:269:13: warning: cast removes address 
space '<asn:1>' of expression
+arch/powerpc/kernel/vecemu.c:269:13: warning: cast removes address 
space '<asn:1>' of expression
+arch/powerpc/kernel/vecemu.c:269:13: warning: cast removes address 
space '<asn:1>' of expression
+arch/powerpc/kernel/vecemu.c:269:13: warning: cast removes address 
space '<asn:1>' of expression
+arch/powerpc/kernel/vecemu.c:269:13: warning: cast removes address 
space '<asn:1>' of expression
+arch/powerpc/kernel/vecemu.c:269:13: warning: incorrect type in 
argument 1 (different address spaces) expected void const volatile 
[noderef] <asn:1> * got unsigned int [usertype] *
+arch/powerpc/kernel/vecemu.c:269:13: warning: incorrect type in 
initializer (different address spaces) expected unsigned int [noderef] 
<asn:1> *__gu_addr got unsigned int [usertype] *
+arch/powerpc/lib/inst.c:55:37: warning: incorrect type in argument 2 
(different address spaces) expected void const [noderef] <asn:1> *src 
got struct ppc_inst *nip
+arch/powerpc/mm/fault.c:284:59: warning: incorrect type in argument 2 
(different address spaces) expected struct ppc_inst *nip got struct 
ppc_inst [noderef] <asn:1> *

Christophe

> 
> v7 fixes compilation issues for some configs reported by Alistair
> Popple.
> 
> v6 is based on feedback from Balamuruhan Suriyakumar, Alistair Popple,
> Christophe Leroy and Segher Boessenkool.
> The major changes:
>      - Use the instruction type in more places that had been missed before
>      - Fix issues with ppc32
>      - Introduce new self tests for code patching and feature fixups
> 
> 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 (29):
>    powerpc/xmon: Remove store_inst() for patch_instruction()
>    powerpc/xmon: Move breakpoint instructions to own array
>    powerpc/xmon: Move breakpoints to text section
>    powerpc/xmon: Use bitwise calculations in_breakpoint_table()
>    powerpc: Change calling convention for create_branch() et. al.
>    powerpc: Use a macro for creating instructions from u32s
>    powerpc: Use an accessor for instructions
>    powerpc: Use a function for getting the instruction op code
>    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: Add a probe_user_read_inst() function
>    powerpc: Add a probe_kernel_read_inst() function
>    powerpc/kprobes: Use patch_instruction()
>    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
>    powerpc: Add prefixed instructions to instruction data type
>    powerpc: Test prefixed code patching
>    powerpc: Test prefixed instructions in feature fixups
>    powerpc/xmon: Don't allow breakpoints on suffixes
>    powerpc/kprobes: Don't allow breakpoints on suffixes
>    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           | 107 +++++
>   arch/powerpc/include/asm/kprobes.h        |   2 +-
>   arch/powerpc/include/asm/ppc-opcode.h     |   3 +
>   arch/powerpc/include/asm/reg.h            |   7 +-
>   arch/powerpc/include/asm/sstep.h          |  15 +-
>   arch/powerpc/include/asm/uaccess.h        |  43 ++
>   arch/powerpc/include/asm/uprobes.h        |   7 +-
>   arch/powerpc/kernel/align.c               |  13 +-
>   arch/powerpc/kernel/asm-offsets.c         |   8 +
>   arch/powerpc/kernel/crash_dump.c          |   7 +-
>   arch/powerpc/kernel/epapr_paravirt.c      |   7 +-
>   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             |  37 +-
>   arch/powerpc/kernel/mce_power.c           |   5 +-
>   arch/powerpc/kernel/module_64.c           |   3 +-
>   arch/powerpc/kernel/optprobes.c           | 102 +++--
>   arch/powerpc/kernel/optprobes_head.S      |   3 +
>   arch/powerpc/kernel/security.c            |  12 +-
>   arch/powerpc/kernel/setup_32.c            |   8 +-
>   arch/powerpc/kernel/trace/ftrace.c        | 168 ++++----
>   arch/powerpc/kernel/traps.c               |  20 +-
>   arch/powerpc/kernel/uprobes.c             |   5 +-
>   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/Makefile                 |   2 +-
>   arch/powerpc/lib/code-patching.c          | 319 +++++++++------
>   arch/powerpc/lib/feature-fixups-test.S    |  69 ++++
>   arch/powerpc/lib/feature-fixups.c         | 160 ++++++--
>   arch/powerpc/lib/inst.c                   |  70 ++++
>   arch/powerpc/lib/sstep.c                  | 459 +++++++++++++++-------
>   arch/powerpc/lib/test_code-patching.S     |  20 +
>   arch/powerpc/lib/test_emulate_step.c      |  56 +--
>   arch/powerpc/mm/fault.c                   |  15 +-
>   arch/powerpc/mm/nohash/8xx.c              |   5 +-
>   arch/powerpc/perf/8xx-pmu.c               |   9 +-
>   arch/powerpc/perf/core-book3s.c           |   4 +-
>   arch/powerpc/platforms/86xx/mpc86xx_smp.c |   5 +-
>   arch/powerpc/platforms/powermac/smp.c     |   5 +-
>   arch/powerpc/xmon/Makefile                |   2 +-
>   arch/powerpc/xmon/xmon.c                  | 122 ++++--
>   arch/powerpc/xmon/xmon_bpts.S             |  11 +
>   arch/powerpc/xmon/xmon_bpts.h             |  14 +
>   47 files changed, 1409 insertions(+), 602 deletions(-)
>   create mode 100644 arch/powerpc/include/asm/inst.h
>   create mode 100644 arch/powerpc/lib/inst.c
>   create mode 100644 arch/powerpc/lib/test_code-patching.S
>   create mode 100644 arch/powerpc/xmon/xmon_bpts.S
>   create mode 100644 arch/powerpc/xmon/xmon_bpts.h
> 

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 13/30] powerpc: Add a probe_user_read_inst() function
  2020-05-06  3:40 ` [PATCH v8 13/30] powerpc: Add a probe_user_read_inst() function Jordan Niethe
  2020-05-13 12:52   ` Michael Ellerman
@ 2020-05-14  5:46   ` Christophe Leroy
  2020-05-15  3:46     ` Jordan Niethe
  1 sibling, 1 reply; 81+ messages in thread
From: Christophe Leroy @ 2020-05-14  5:46 UTC (permalink / raw)
  To: Jordan Niethe, linuxppc-dev
  Cc: christophe.leroy, alistair, npiggin, bala24, naveen.n.rao, dja



Le 06/05/2020 à 05:40, Jordan Niethe a écrit :
> Introduce a probe_user_read_inst() function to use in cases where
> probe_user_read() is used for getting an instruction. This will be more
> useful for prefixed instructions.
> 
> Reviewed-by: Alistair Popple <alistair@popple.id.au>
> Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> ---
> v6: - New to series
> ---
>   arch/powerpc/include/asm/inst.h |  3 +++
>   arch/powerpc/lib/Makefile       |  2 +-
>   arch/powerpc/lib/inst.c         | 18 ++++++++++++++++++
>   arch/powerpc/mm/fault.c         |  2 +-
>   4 files changed, 23 insertions(+), 2 deletions(-)
>   create mode 100644 arch/powerpc/lib/inst.c
> 
> diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h
> index 552e953bf04f..3e9a58420151 100644
> --- a/arch/powerpc/include/asm/inst.h
> +++ b/arch/powerpc/include/asm/inst.h
> @@ -37,4 +37,7 @@ static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
>   	return ppc_inst_val(x) == ppc_inst_val(y);
>   }
>   
> +int probe_user_read_inst(struct ppc_inst *inst,
> +			 struct ppc_inst *nip);
> +
>   #endif /* _ASM_INST_H */
> diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
> index b8de3be10eb4..546591848219 100644
> --- a/arch/powerpc/lib/Makefile
> +++ b/arch/powerpc/lib/Makefile
> @@ -16,7 +16,7 @@ CFLAGS_code-patching.o += -DDISABLE_BRANCH_PROFILING
>   CFLAGS_feature-fixups.o += -DDISABLE_BRANCH_PROFILING
>   endif
>   
> -obj-y += alloc.o code-patching.o feature-fixups.o pmem.o
> +obj-y += alloc.o code-patching.o feature-fixups.o pmem.o inst.o
>   
>   ifndef CONFIG_KASAN
>   obj-y	+=	string.o memcmp_$(BITS).o
> diff --git a/arch/powerpc/lib/inst.c b/arch/powerpc/lib/inst.c
> new file mode 100644
> index 000000000000..eaf786afad2b
> --- /dev/null
> +++ b/arch/powerpc/lib/inst.c
> @@ -0,0 +1,18 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + *  Copyright 2020, IBM Corporation.
> + */
> +
> +#include <linux/uaccess.h>
> +#include <asm/inst.h>
> +
> +int probe_user_read_inst(struct ppc_inst *inst,
> +			 struct ppc_inst *nip)
> +{
> +	unsigned int val;
> +	int err;
> +
> +	err = probe_user_read(&val, nip, sizeof(val));
> +	*inst = ppc_inst(val);
> +	return err;
> +}
> diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
> index 4a50f125ec18..f3a943eae305 100644
> --- a/arch/powerpc/mm/fault.c
> +++ b/arch/powerpc/mm/fault.c
> @@ -281,7 +281,7 @@ static bool bad_stack_expansion(struct pt_regs *regs, unsigned long address,
>   		    access_ok(nip, sizeof(*nip))) {
>   			struct ppc_inst inst;
>   
> -			if (!probe_user_read(&inst, nip, sizeof(inst)))
> +			if (!probe_user_read_inst(&inst, (struct ppc_inst __user *)nip))

Shouldn't 'nip' become de 'struct ppc_inst __user *' instead of casting ?

>   				return !store_updates_sp(inst);
>   			*must_retry = true;
>   		}
> 

Christophe

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 23/30] powerpc: Add prefixed instructions to instruction data type
  2020-05-06  3:40 ` [PATCH v8 23/30] powerpc: Add prefixed instructions to instruction data type Jordan Niethe
  2020-05-14  1:40   ` Jordan Niethe
@ 2020-05-14  6:11   ` Christophe Leroy
  2020-05-14 12:06     ` Alistair Popple
                       ` (2 more replies)
  2020-05-16 11:54   ` [PATCH v8 22.5/30] powerpc/optprobes: Add register argument to patch_imm64_load_insns() Michael Ellerman
  2 siblings, 3 replies; 81+ messages in thread
From: Christophe Leroy @ 2020-05-14  6:11 UTC (permalink / raw)
  To: Jordan Niethe, linuxppc-dev
  Cc: christophe.leroy, alistair, npiggin, bala24, naveen.n.rao, dja



Le 06/05/2020 à 05:40, Jordan Niethe a écrit :
> 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.
> 
> Reviewed-by: Alistair Popple <alistair@popple.id.au>
> 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
> v6:  - Return false instead of 0 in ppc_inst_prefixed()
>       - Fix up types for ppc32 so it compiles
>       - remove ppc_inst_write()
>       - __patching_instruction(): move flush out of condition
> v8:  - style
>       - Define and use OP_PREFIX instead of '1' (back from v3)
>       - __patch_instruction() fix for big endian
> ---
>   arch/powerpc/include/asm/inst.h       | 69 ++++++++++++++++++++++++---
>   arch/powerpc/include/asm/kprobes.h    |  2 +-
>   arch/powerpc/include/asm/ppc-opcode.h |  3 ++
>   arch/powerpc/include/asm/uaccess.h    | 40 +++++++++++++++-
>   arch/powerpc/include/asm/uprobes.h    |  2 +-
>   arch/powerpc/kernel/crash_dump.c      |  2 +-
>   arch/powerpc/kernel/optprobes.c       | 42 ++++++++--------
>   arch/powerpc/kernel/optprobes_head.S  |  3 ++
>   arch/powerpc/lib/code-patching.c      | 19 ++++++--
>   arch/powerpc/lib/feature-fixups.c     |  5 +-
>   arch/powerpc/lib/inst.c               | 41 ++++++++++++++++
>   arch/powerpc/lib/sstep.c              |  4 +-
>   arch/powerpc/xmon/xmon.c              |  4 +-
>   arch/powerpc/xmon/xmon_bpts.S         |  2 +
>   14 files changed, 200 insertions(+), 38 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h
> index 2f3c9d5bcf7c..7868b80b610e 100644
> --- a/arch/powerpc/include/asm/inst.h
> +++ b/arch/powerpc/include/asm/inst.h
> @@ -2,29 +2,79 @@
>   #ifndef _ASM_INST_H
>   #define _ASM_INST_H
>   
> +#include <asm/ppc-opcode.h>
>   /*
>    * Instruction data type for POWER
>    */
>   
>   struct ppc_inst {
>   	u32 val;
> +#ifdef __powerpc64__

CONFIG_PPC64 should be used instead. This is also reported by checkpatch.

> +	u32 suffix;
> +#endif /* __powerpc64__ */
>   } __packed;
>   
> -#define ppc_inst(x) ((struct ppc_inst){ .val = x })
> -
>   static inline u32 ppc_inst_val(struct ppc_inst x)
>   {
>   	return x.val;
>   }
>   
> -static inline int ppc_inst_len(struct ppc_inst x)
> +static inline int ppc_inst_primary_opcode(struct ppc_inst x)
>   {
> -	return sizeof(struct ppc_inst);
> +	return ppc_inst_val(x) >> 26;

What about using get_op() from asm/disassemble.h instead of hardcodiing ?

>   }
>   
> -static inline int ppc_inst_primary_opcode(struct ppc_inst x)
> +#ifdef __powerpc64__

Use CONFIG_PPC64

> +#define ppc_inst(x) ((struct ppc_inst){ .val = (x), .suffix = 0xff })
> +
> +#define ppc_inst_prefix(x, y) ((struct ppc_inst){ .val = (x), .suffix = (y) })
> +
> +static inline u32 ppc_inst_suffix(struct ppc_inst x)
>   {
> -	return ppc_inst_val(x) >> 26;
> +	return x.suffix;
> +}
> +
> +static inline bool ppc_inst_prefixed(struct ppc_inst x)
> +{
> +	return (ppc_inst_primary_opcode(x) == 1) && ppc_inst_suffix(x) != 0xff;
> +}
> +
> +static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
> +{
> +	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;
> +
> +	val = *(u32 *)ptr;
> +	if ((val >> 26) == 1) {

Don't hardcode, use ppc_inst_primary_opcode() and compare it to OP_PREFIX
Or use get_op() from asm/disassemble.h


> +		suffix = *((u32 *)ptr + 1);
> +		return ppc_inst_prefix(val, suffix);
> +	} else {
> +		return ppc_inst(val);
> +	}
> +}
> +
> +static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
> +{
> +	return *(u64 *)&x == *(u64 *)&y;
> +}
> +
> +#else
> +
> +#define ppc_inst(x) ((struct ppc_inst){ .val = x })
> +
> +static inline bool ppc_inst_prefixed(struct ppc_inst x)
> +{
> +	return false;
> +}
> +
> +static inline u32 ppc_inst_suffix(struct ppc_inst x)
> +{
> +	return 0;
>   }
>   
>   static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
> @@ -42,6 +92,13 @@ static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
>   	return ppc_inst_val(x) == ppc_inst_val(y);
>   }
>   
> +#endif /* __powerpc64__ */
> +
> +static inline int ppc_inst_len(struct ppc_inst x)
> +{
> +	return (ppc_inst_prefixed(x)) ? 8  : 4;
> +}
> +
>   int probe_user_read_inst(struct ppc_inst *inst,
>   			 struct ppc_inst *nip);
>   int probe_kernel_read_inst(struct ppc_inst *inst,
> 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/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h
> index c1df75edde44..2a39c716c343 100644
> --- a/arch/powerpc/include/asm/ppc-opcode.h
> +++ b/arch/powerpc/include/asm/ppc-opcode.h
> @@ -158,6 +158,9 @@
>   /* VMX Vector Store Instructions */
>   #define OP_31_XOP_STVX          231
>   
> +/* Prefixed Instructions */
> +#define OP_PREFIX		1
> +
>   #define OP_31   31
>   #define OP_LWZ  32
>   #define OP_STFS 52
> diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h
> index c0a35e4586a5..217897927926 100644
> --- a/arch/powerpc/include/asm/uaccess.h
> +++ b/arch/powerpc/include/asm/uaccess.h
> @@ -105,11 +105,49 @@ static inline int __access_ok(unsigned long addr, unsigned long size,
>   #define __put_user_inatomic(x, ptr) \
>   	__put_user_nosleep((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
>   
> +#ifdef __powerpc64__

Replace by CONFIG_PPC64

> +#define __get_user_instr(x, ptr)			\
> +({							\
> +	long __gui_ret = 0;				\
> +	unsigned long __gui_ptr = (unsigned long)ptr;	\
> +	struct ppc_inst __gui_inst;			\
> +	unsigned int prefix, suffix;			\
> +	__gui_ret = __get_user(prefix, (unsigned int __user *)__gui_ptr);	\

__get_user() can be costly especially with KUAP. I think you should 
perform a 64 bits read and fallback on a 32 bits read only if the 64 
bits read failed.

> +	if (!__gui_ret && (prefix >> 26) == OP_PREFIX) {	\

What about using get_op() from asm/disassemble.h instead of hardcodiing ?

> +		__gui_ret = __get_user(suffix,		\
> +				       (unsigned int __user *)__gui_ptr + 1);	\
> +		__gui_inst = ppc_inst_prefix(prefix, suffix);	\
> +	} else {					\
> +		__gui_inst = ppc_inst(prefix);		\
> +	}						\
> +	(x) = __gui_inst;				\
> +	__gui_ret;					\
> +})
> +
> +#define __get_user_instr_inatomic(x, ptr)		\
> +({							\
> +	long __gui_ret = 0;				\
> +	unsigned long __gui_ptr = (unsigned long)ptr;	\
> +	struct ppc_inst __gui_inst;			\
> +	unsigned int prefix, suffix;			\
> +	__gui_ret = __get_user_inatomic(prefix, (unsigned int __user *)__gui_ptr);	\

Same

> +	if (!__gui_ret && (prefix >> 26) == OP_PREFIX) {	\
> +		__gui_ret = __get_user_inatomic(suffix,	\
> +						(unsigned int __user *)__gui_ptr + 1);	\
> +		__gui_inst = ppc_inst_prefix(prefix, suffix);	\
> +	} else {					\
> +		__gui_inst = ppc_inst(prefix);		\
> +	}						\
> +	(x) = __gui_inst;				\
> +	__gui_ret;					\
> +})
> +#else
>   #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))
> +#endif
> +
>   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/crash_dump.c b/arch/powerpc/kernel/crash_dump.c
> index 72bafb47e757..735e89337398 100644
> --- a/arch/powerpc/kernel/crash_dump.c
> +++ b/arch/powerpc/kernel/crash_dump.c
> @@ -46,7 +46,7 @@ static void __init create_trampoline(unsigned long addr)
>   	 * two instructions it doesn't require any registers.
>   	 */
>   	patch_instruction(p, ppc_inst(PPC_INST_NOP));
> -	patch_branch(++p, addr + PHYSICAL_START, 0);
> +	patch_branch((void *)p + 4, addr + PHYSICAL_START, 0);
>   }
>   
>   void __init setup_kdump_trampoline(void)
> diff --git a/arch/powerpc/kernel/optprobes.c b/arch/powerpc/kernel/optprobes.c
> index 52c1ab3f85aa..a8e66603d12b 100644
> --- a/arch/powerpc/kernel/optprobes.c
> +++ b/arch/powerpc/kernel/optprobes.c
> @@ -162,43 +162,43 @@ 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)

I think this change should go in a separate patch.

>   {
> -	/* lis r3,(op)@highest */
> +	/* lis reg,(op)@highest */
>   	patch_instruction((struct ppc_inst *)addr,
> -			  ppc_inst(PPC_INST_ADDIS | ___PPC_RT(3) |
> +			  ppc_inst(PPC_INST_ADDIS | ___PPC_RT(reg) |
>   				   ((val >> 48) & 0xffff)));
>   	addr++;
>   
> -	/* ori r3,r3,(op)@higher */
> +	/* ori reg,reg,(op)@higher */
>   	patch_instruction((struct ppc_inst *)addr,
> -			  ppc_inst(PPC_INST_ORI | ___PPC_RA(3) |
> -				   ___PPC_RS(3) | ((val >> 32) & 0xffff)));
> +			  ppc_inst(PPC_INST_ORI | ___PPC_RA(reg) |
> +				   ___PPC_RS(reg) | ((val >> 32) & 0xffff)));
>   	addr++;
>   
> -	/* rldicr r3,r3,32,31 */
> +	/* rldicr reg,reg,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)));
> +			  ppc_inst(PPC_INST_RLDICR | ___PPC_RA(reg) |
> +				   ___PPC_RS(reg) | __PPC_SH64(32) | __PPC_ME64(31)));
>   	addr++;
>   
> -	/* oris r3,r3,(op)@h */
> +	/* oris reg,reg,(op)@h */
>   	patch_instruction((struct ppc_inst *)addr,
> -			  ppc_inst(PPC_INST_ORIS | ___PPC_RA(3) |
> -				   ___PPC_RS(3) | ((val >> 16) & 0xffff)));
> +			  ppc_inst(PPC_INST_ORIS | ___PPC_RA(reg) |
> +				   ___PPC_RS(reg) | ((val >> 16) & 0xffff)));
>   	addr++;
>   
> -	/* ori r3,r3,(op)@l */
> +	/* ori reg,reg,(op)@l */
>   	patch_instruction((struct ppc_inst *)addr,
> -			  ppc_inst(PPC_INST_ORI | ___PPC_RA(3) |
> -				   ___PPC_RS(3) | (val & 0xffff)));
> +			  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;
> @@ -249,7 +249,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()
> @@ -282,7 +282,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,

So now we are also using r4 ? Any explanation somewhere on the way it 
works ? This change seems unrelated to this patch, nothing in the 
description about it. Can we suddenly use a new register without problem ?

> +			       buff + TMPL_INSN_IDX);

What's the point with splitting this line in 4 lines ? Can't it fit in 2 
lines ?

>   
>   	/*
>   	 * 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/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
> index d946f7d6bb32..58b67b62d5d3 100644
> --- a/arch/powerpc/lib/code-patching.c
> +++ b/arch/powerpc/lib/code-patching.c
> @@ -24,13 +24,24 @@ 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;
> +	if (!ppc_inst_prefixed(instr)) {
> +		__put_user_asm(ppc_inst_val(instr), patch_addr, err, "stw");
> +		if (err)
> +			return err;

This test should remain outside of the if/else, it doesn't need to be 
duplicated.

> +	} else {
> +#ifdef CONFIG_CPU_LITTLE_ENDIAN
> +		__put_user_asm((u64)ppc_inst_suffix(instr) << 32 |
> +			       ppc_inst_val(instr), patch_addr, err, "std");
> +#else
> +		__put_user_asm((u64)ppc_inst_val(instr) << 32 |
> +			       ppc_inst_suffix(instr), patch_addr, err, "std");
> +#endif /* CONFIG_CPU_LITTLE_ENDIAN */
> +		if (err)
> +			return err;
> +	}
>   
>   	asm ("dcbst 0, %0; sync; icbi 0,%1; sync; isync" :: "r" (patch_addr),
>   							    "r" (exec_addr));
> -

Why remove the blank line ?

>   	return 0;
>   }
>   
> diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c
> index 2bd2b752de4f..a8238eff3a31 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)))) {

Can we do this outside the for() for readability ?

>   		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/inst.c b/arch/powerpc/lib/inst.c
> index 08dedd927268..eb6f9ee28ac6 100644
> --- a/arch/powerpc/lib/inst.c
> +++ b/arch/powerpc/lib/inst.c
> @@ -3,9 +3,49 @@
>    *  Copyright 2020, IBM Corporation.
>    */
>   
> +#include <asm/ppc-opcode.h>
>   #include <linux/uaccess.h>
>   #include <asm/inst.h>
>   
> +#ifdef __powerpc64__
> +int probe_user_read_inst(struct ppc_inst *inst,
> +			 struct ppc_inst *nip)
> +{
> +	unsigned int val, suffix;
> +	int err;
> +
> +	err = probe_user_read(&val, nip, sizeof(val));

A user read is costly with KUAP. Can we do a 64 bits read and perform a 
32 bits read only when 64 bits read fails ?

> +	if (err)
> +		return err;
> +	if ((val >> 26) == OP_PREFIX) {

What about using get_op() from asm/disassemble.h instead of hardcodiing ?

> +		err = probe_user_read(&suffix, (void *)nip + 4,

4 or sizeof(unsigned int) ? Why use both in the same line ?

> +				      sizeof(unsigned int));
> +		*inst = ppc_inst_prefix(val, suffix);
> +	} else {
> +		*inst = ppc_inst(val);
> +	}
> +	return err;
> +}
> +
> +int probe_kernel_read_inst(struct ppc_inst *inst,
> +			   struct ppc_inst *src)
> +{
> +	unsigned int val, suffix;
> +	int err;
> +
> +	err = probe_kernel_read(&val, src, sizeof(val));
> +	if (err)
> +		return err;
> +	if ((val >> 26) == OP_PREFIX) {
> +		err = probe_kernel_read(&suffix, (void *)src + 4,
> +					sizeof(unsigned int));
> +		*inst = ppc_inst_prefix(val, suffix);
> +	} else {
> +		*inst = ppc_inst(val);
> +	}
> +	return err;
> +}
> +#else
>   int probe_user_read_inst(struct ppc_inst *inst,
>   			 struct ppc_inst *nip)
>   {
> @@ -27,3 +67,4 @@ int probe_kernel_read_inst(struct ppc_inst *inst,
>   	*inst = ppc_inst(val);
>   	return err;
>   }
> +#endif /* __powerpc64__ */
> diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
> index 95a56bb1ba3f..ecd756c346fd 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 = ppc_inst_primary_opcode(instr);
> diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
> index 4d6980d51456..647b3829c4eb 100644
> --- a/arch/powerpc/xmon/xmon.c
> +++ b/arch/powerpc/xmon/xmon.c
> @@ -758,8 +758,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;
>   	}
> diff --git a/arch/powerpc/xmon/xmon_bpts.S b/arch/powerpc/xmon/xmon_bpts.S
> index f3ad0ab50854..69726814cd27 100644
> --- a/arch/powerpc/xmon/xmon_bpts.S
> +++ b/arch/powerpc/xmon/xmon_bpts.S
> @@ -4,6 +4,8 @@
>   #include <asm/asm-offsets.h>
>   #include "xmon_bpts.h"
>   
> +/* Prefixed instructions can not cross 64 byte boundaries */
> +.align 6
>   .global bpt_table
>   bpt_table:
>   	.space NBPTS * BPT_SIZE
> 

Christophe

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 28/30] powerpc: Support prefixed instructions in alignment handler
  2020-05-06  3:40 ` [PATCH v8 28/30] powerpc: Support prefixed instructions in alignment handler Jordan Niethe
@ 2020-05-14  6:14   ` Christophe Leroy
  2020-05-14 12:15     ` Alistair Popple
  0 siblings, 1 reply; 81+ messages in thread
From: Christophe Leroy @ 2020-05-14  6:14 UTC (permalink / raw)
  To: Jordan Niethe, linuxppc-dev
  Cc: christophe.leroy, alistair, npiggin, bala24, naveen.n.rao, dja



Le 06/05/2020 à 05:40, Jordan Niethe a écrit :
> 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().

Shouldn't this patch go before patch 23 ?

Christophe

> 
> Reviewed-by: Alistair Popple <alistair@popple.id.au>
> 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 493a3fa0ac1a..105242cc2f28 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
> 

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 29/30] powerpc sstep: Add support for prefixed load/stores
  2020-05-06  3:40 ` [PATCH v8 29/30] powerpc sstep: Add support for prefixed load/stores Jordan Niethe
@ 2020-05-14  6:15   ` Christophe Leroy
  2020-05-14 12:19     ` Alistair Popple
  2020-05-15  7:59   ` Jordan Niethe
  1 sibling, 1 reply; 81+ messages in thread
From: Christophe Leroy @ 2020-05-14  6:15 UTC (permalink / raw)
  To: Jordan Niethe, linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, dja

Shouldn't this patch go before patch 23 ?

Christophe


Le 06/05/2020 à 05:40, Jordan Niethe a écrit :
> 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
> v6: - Compile on ppc32
>      - Add back in + GETLENGTH(op->type)
> v8: Use fallthrough; keyword
> ---
>   arch/powerpc/include/asm/sstep.h |   4 +
>   arch/powerpc/lib/sstep.c         | 163 ++++++++++++++++++++++++++++++-
>   2 files changed, 165 insertions(+), 2 deletions(-)
> 
> 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 ecd756c346fd..6794a7672ad5 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,9 @@ 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;
> +#ifdef __powerpc64__
> +	unsigned int suffixopcode, prefixtype, prefix_r;
> +#endif
>   	unsigned long int imm;
>   	unsigned long int val, val2;
>   	unsigned int mb, me, sh;
> @@ -2652,6 +2693,124 @@ 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;
> +				fallthrough;
> +			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;
> +				fallthrough;
> +			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__ */
>   
>   	}
> @@ -2760,7 +2919,7 @@ void emulate_update_regs(struct pt_regs *regs, struct instruction_op *op)
>   {
>   	unsigned long next_pc;
>   
> -	next_pc = truncate_if_32bit(regs->msr, regs->nip + 4);
> +	next_pc = truncate_if_32bit(regs->msr, regs->nip + GETLENGTH(op->type));
>   	switch (GETTYPE(op->type)) {
>   	case COMPUTE:
>   		if (op->type & SETREG)
> @@ -3205,7 +3364,7 @@ int emulate_step(struct pt_regs *regs, struct ppc_inst instr)
>   	return 0;
>   
>    instr_done:
> -	regs->nip = truncate_if_32bit(regs->msr, regs->nip + 4);
> +	regs->nip = truncate_if_32bit(regs->msr, regs->nip + GETLENGTH(op.type));
>   	return 1;
>   }
>   NOKPROBE_SYMBOL(emulate_step);
> 

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 30/30] powerpc sstep: Add support for prefixed fixed-point arithmetic
  2020-05-06  3:40 ` [PATCH v8 30/30] powerpc sstep: Add support for prefixed fixed-point arithmetic Jordan Niethe
@ 2020-05-14  6:15   ` Christophe Leroy
  2020-05-15  8:02   ` Jordan Niethe
  1 sibling, 0 replies; 81+ messages in thread
From: Christophe Leroy @ 2020-05-14  6:15 UTC (permalink / raw)
  To: Jordan Niethe, linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, dja



Le 06/05/2020 à 05:40, Jordan Niethe a écrit :
> This adds emulation support for the following prefixed Fixed-Point
> Arithmetic instructions:
>    * Prefixed Add Immediate (paddi)

Shouldn't this patch go before patch 23 ?

Christophe

> 
> 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 6794a7672ad5..964fe7bbfce3 100644
> --- a/arch/powerpc/lib/sstep.c
> +++ b/arch/powerpc/lib/sstep.c
> @@ -1337,6 +1337,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;
> 

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 00/30] Initial Prefixed Instruction support
  2020-05-14  5:31 ` [PATCH v8 00/30] Initial Prefixed Instruction support Christophe Leroy
@ 2020-05-14 10:33   ` Jordan Niethe
  0 siblings, 0 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-14 10:33 UTC (permalink / raw)
  To: Christophe Leroy
  Cc: Alistair Popple, Nicholas Piggin, Balamuruhan S, naveen.n.rao,
	linuxppc-dev, Daniel Axtens

On Thu, May 14, 2020 at 3:31 PM Christophe Leroy
<christophe.leroy@csgroup.eu> wrote:
>
>
>
> Le 06/05/2020 à 05:40, Jordan Niethe a écrit :
> > 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.
> >
> > v8 incorporates feedback from Alistair Popple and Balamuruhan Suriyakumar.
> > The major changes:
> >      - Fix some style issues
> >      - Fix __patch_instruction() on big endian
> >      - Reintroduce v3's forbidding breakpoints on second word of prefix
> >        instructions for kprobes and xmon. Missed this when changing to
> >        using a data type.
> >      - Use the data type in some places that were missed.
>
> Checkpatch seems to report the following warnings for pmac32_defconfig,
> are they harmless ?
>
> +arch/powerpc/kernel/align.c:307:13: warning: cast removes address space
> '<asn:1>' of expression
> +arch/powerpc/kernel/align.c:307:13: warning: cast removes address space
> '<asn:1>' of expression
> +arch/powerpc/kernel/align.c:307:13: warning: cast removes address space
> '<asn:1>' of expression
> +arch/powerpc/kernel/align.c:307:13: warning: cast removes address space
> '<asn:1>' of expression
> +arch/powerpc/kernel/align.c:307:13: warning: cast removes address space
> '<asn:1>' of expression
> +arch/powerpc/kernel/align.c:307:13: warning: incorrect type in argument
> 1 (different address spaces) expected void const volatile [noderef]
> <asn:1> * got unsigned int [usertype] *
> +arch/powerpc/kernel/align.c:307:13: warning: incorrect type in
> initializer (different address spaces) expected unsigned int [noderef]
> <asn:1> *__gu_addr got unsigned int [usertype] *
> +arch/powerpc/kernel/hw_breakpoint.c:XX:13: warning: cast removes
> address space '<asn:1>' of expression
> +arch/powerpc/kernel/hw_breakpoint.c:XX:13: warning: cast removes
> address space '<asn:1>' of expression
> +arch/powerpc/kernel/hw_breakpoint.c:XX:13: warning: cast removes
> address space '<asn:1>' of expression
> +arch/powerpc/kernel/hw_breakpoint.c:XX:13: warning: cast removes
> address space '<asn:1>' of expression
> +arch/powerpc/kernel/hw_breakpoint.c:XX:13: warning: cast removes
> address space '<asn:1>' of expression
> -arch/powerpc/kernel/hw_breakpoint.c:XX:13: warning: incorrect type in
> argument 1 (different address spaces) expected void const volatile
> [noderef] <asn:1> * got unsigned int *
> +arch/powerpc/kernel/hw_breakpoint.c:XX:13: warning: incorrect type in
> argument 1 (different address spaces) expected void const volatile
> [noderef] <asn:1> * got unsigned int [usertype] *
> -arch/powerpc/kernel/hw_breakpoint.c:XX:13: warning: incorrect type in
> initializer (different address spaces) expected unsigned int [noderef]
> <asn:1> *__gu_addr got unsigned int *
> +arch/powerpc/kernel/hw_breakpoint.c:XX:13: warning: incorrect type in
> initializer (different address spaces) expected unsigned int [noderef]
> <asn:1> *__gu_addr got unsigned int [usertype] *
> +arch/powerpc/kernel/vecemu.c:269:13: warning: cast removes address
> space '<asn:1>' of expression
> +arch/powerpc/kernel/vecemu.c:269:13: warning: cast removes address
> space '<asn:1>' of expression
> +arch/powerpc/kernel/vecemu.c:269:13: warning: cast removes address
> space '<asn:1>' of expression
> +arch/powerpc/kernel/vecemu.c:269:13: warning: cast removes address
> space '<asn:1>' of expression
> +arch/powerpc/kernel/vecemu.c:269:13: warning: cast removes address
> space '<asn:1>' of expression
> +arch/powerpc/kernel/vecemu.c:269:13: warning: incorrect type in
> argument 1 (different address spaces) expected void const volatile
> [noderef] <asn:1> * got unsigned int [usertype] *
> +arch/powerpc/kernel/vecemu.c:269:13: warning: incorrect type in
> initializer (different address spaces) expected unsigned int [noderef]
> <asn:1> *__gu_addr got unsigned int [usertype] *
> +arch/powerpc/lib/inst.c:55:37: warning: incorrect type in argument 2
> (different address spaces) expected void const [noderef] <asn:1> *src
> got struct ppc_inst *nip
> +arch/powerpc/mm/fault.c:284:59: warning: incorrect type in argument 2
> (different address spaces) expected struct ppc_inst *nip got struct
> ppc_inst [noderef] <asn:1> *
Thanks, I was missing some __user.
--- a/arch/powerpc/include/asm/uaccess.h
+++ b/arch/powerpc/include/asm/uaccess.h
@@ -106,10 +106,10 @@ static inline int __access_ok(unsigned long
addr, unsigned long size,
        __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)
+       __get_user_nocheck((x).val, (u32 __user *)(ptr), sizeof(u32), true)

 #define __get_user_instr_inatomic(x, ptr) \
-       __get_user_nosleep((x).val, (u32 *)(ptr), sizeof(u32))
+       __get_user_nosleep((x).val, (u32 __user *)(ptr), sizeof(u32))
 extern long __put_user_bad(void);

 /*

--- a/arch/powerpc/include/asm/inst.h
+++ b/arch/powerpc/include/asm/inst.h
@@ -38,6 +38,6 @@ static inline bool ppc_inst_equal(struct ppc_inst x,
struct ppc_inst y)
 }

 int probe_user_read_inst(struct ppc_inst *inst,
-                        struct ppc_inst *nip);
+                        struct ppc_inst __user *nip);

 #endif /* _ASM_INST_H */
diff --git a/arch/powerpc/lib/inst.c b/arch/powerpc/lib/inst.c
index eaf786afad2b..c15611086d26 100644
--- a/arch/powerpc/lib/inst.c
+++ b/arch/powerpc/lib/inst.c
@@ -7,7 +7,7 @@
 #include <asm/inst.h>

 int probe_user_read_inst(struct ppc_inst *inst,
-                        struct ppc_inst *nip)
+                        struct ppc_inst __user *nip)
 {
        unsigned int val;
        int err;


>
> Christophe
>
> >
> > v7 fixes compilation issues for some configs reported by Alistair
> > Popple.
> >
> > v6 is based on feedback from Balamuruhan Suriyakumar, Alistair Popple,
> > Christophe Leroy and Segher Boessenkool.
> > The major changes:
> >      - Use the instruction type in more places that had been missed before
> >      - Fix issues with ppc32
> >      - Introduce new self tests for code patching and feature fixups
> >
> > 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 (29):
> >    powerpc/xmon: Remove store_inst() for patch_instruction()
> >    powerpc/xmon: Move breakpoint instructions to own array
> >    powerpc/xmon: Move breakpoints to text section
> >    powerpc/xmon: Use bitwise calculations in_breakpoint_table()
> >    powerpc: Change calling convention for create_branch() et. al.
> >    powerpc: Use a macro for creating instructions from u32s
> >    powerpc: Use an accessor for instructions
> >    powerpc: Use a function for getting the instruction op code
> >    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: Add a probe_user_read_inst() function
> >    powerpc: Add a probe_kernel_read_inst() function
> >    powerpc/kprobes: Use patch_instruction()
> >    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
> >    powerpc: Add prefixed instructions to instruction data type
> >    powerpc: Test prefixed code patching
> >    powerpc: Test prefixed instructions in feature fixups
> >    powerpc/xmon: Don't allow breakpoints on suffixes
> >    powerpc/kprobes: Don't allow breakpoints on suffixes
> >    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           | 107 +++++
> >   arch/powerpc/include/asm/kprobes.h        |   2 +-
> >   arch/powerpc/include/asm/ppc-opcode.h     |   3 +
> >   arch/powerpc/include/asm/reg.h            |   7 +-
> >   arch/powerpc/include/asm/sstep.h          |  15 +-
> >   arch/powerpc/include/asm/uaccess.h        |  43 ++
> >   arch/powerpc/include/asm/uprobes.h        |   7 +-
> >   arch/powerpc/kernel/align.c               |  13 +-
> >   arch/powerpc/kernel/asm-offsets.c         |   8 +
> >   arch/powerpc/kernel/crash_dump.c          |   7 +-
> >   arch/powerpc/kernel/epapr_paravirt.c      |   7 +-
> >   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             |  37 +-
> >   arch/powerpc/kernel/mce_power.c           |   5 +-
> >   arch/powerpc/kernel/module_64.c           |   3 +-
> >   arch/powerpc/kernel/optprobes.c           | 102 +++--
> >   arch/powerpc/kernel/optprobes_head.S      |   3 +
> >   arch/powerpc/kernel/security.c            |  12 +-
> >   arch/powerpc/kernel/setup_32.c            |   8 +-
> >   arch/powerpc/kernel/trace/ftrace.c        | 168 ++++----
> >   arch/powerpc/kernel/traps.c               |  20 +-
> >   arch/powerpc/kernel/uprobes.c             |   5 +-
> >   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/Makefile                 |   2 +-
> >   arch/powerpc/lib/code-patching.c          | 319 +++++++++------
> >   arch/powerpc/lib/feature-fixups-test.S    |  69 ++++
> >   arch/powerpc/lib/feature-fixups.c         | 160 ++++++--
> >   arch/powerpc/lib/inst.c                   |  70 ++++
> >   arch/powerpc/lib/sstep.c                  | 459 +++++++++++++++-------
> >   arch/powerpc/lib/test_code-patching.S     |  20 +
> >   arch/powerpc/lib/test_emulate_step.c      |  56 +--
> >   arch/powerpc/mm/fault.c                   |  15 +-
> >   arch/powerpc/mm/nohash/8xx.c              |   5 +-
> >   arch/powerpc/perf/8xx-pmu.c               |   9 +-
> >   arch/powerpc/perf/core-book3s.c           |   4 +-
> >   arch/powerpc/platforms/86xx/mpc86xx_smp.c |   5 +-
> >   arch/powerpc/platforms/powermac/smp.c     |   5 +-
> >   arch/powerpc/xmon/Makefile                |   2 +-
> >   arch/powerpc/xmon/xmon.c                  | 122 ++++--
> >   arch/powerpc/xmon/xmon_bpts.S             |  11 +
> >   arch/powerpc/xmon/xmon_bpts.h             |  14 +
> >   47 files changed, 1409 insertions(+), 602 deletions(-)
> >   create mode 100644 arch/powerpc/include/asm/inst.h
> >   create mode 100644 arch/powerpc/lib/inst.c
> >   create mode 100644 arch/powerpc/lib/test_code-patching.S
> >   create mode 100644 arch/powerpc/xmon/xmon_bpts.S
> >   create mode 100644 arch/powerpc/xmon/xmon_bpts.h
> >

^ permalink raw reply related	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 23/30] powerpc: Add prefixed instructions to instruction data type
  2020-05-14  6:11   ` Christophe Leroy
@ 2020-05-14 12:06     ` Alistair Popple
  2020-05-14 12:29       ` Jordan Niethe
  2020-05-14 12:57       ` Christophe Leroy
  2020-05-14 12:28     ` Jordan Niethe
  2020-05-15  1:33     ` Michael Ellerman
  2 siblings, 2 replies; 81+ messages in thread
From: Alistair Popple @ 2020-05-14 12:06 UTC (permalink / raw)
  To: Christophe Leroy
  Cc: christophe.leroy, Jordan Niethe, npiggin, bala24, naveen.n.rao,
	linuxppc-dev, dja

On Thursday, 14 May 2020 4:11:43 PM AEST Christophe Leroy wrote:
> @@ -249,7 +249,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()
> > @@ -282,7 +282,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,
> 
> So now we are also using r4 ? Any explanation somewhere on the way it
> works ? This change seems unrelated to this patch, nothing in the
> description about it. Can we suddenly use a new register without problem ?

Unless I missed something there is no change in register usage here that I 
could see. patch_imm32_load_insns() was/is hardcoded to use register r4.

- Alistair



^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 28/30] powerpc: Support prefixed instructions in alignment handler
  2020-05-14  6:14   ` Christophe Leroy
@ 2020-05-14 12:15     ` Alistair Popple
  2020-05-14 12:59       ` Christophe Leroy
  0 siblings, 1 reply; 81+ messages in thread
From: Alistair Popple @ 2020-05-14 12:15 UTC (permalink / raw)
  To: Christophe Leroy
  Cc: christophe.leroy, Jordan Niethe, npiggin, bala24, naveen.n.rao,
	linuxppc-dev, dja

On Thursday, 14 May 2020 4:14:12 PM AEST Christophe Leroy wrote:
> Le 06/05/2020 à 05:40, Jordan Niethe a écrit :
> > 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().
> 
> Shouldn't this patch go before patch 23 ?

Is there a particular reason you think it needs to go before patch 23? Neither 
seem particularly related to one another and it seems logical to me at least 
that you would introduce prefix support to the datatype prior to using them.

- Alistair
 
> Christophe
> 
> > Reviewed-by: Alistair Popple <alistair@popple.id.au>
> > 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 493a3fa0ac1a..105242cc2f28 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





^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 29/30] powerpc sstep: Add support for prefixed load/stores
  2020-05-14  6:15   ` Christophe Leroy
@ 2020-05-14 12:19     ` Alistair Popple
  2020-05-14 13:00       ` Christophe Leroy
  0 siblings, 1 reply; 81+ messages in thread
From: Alistair Popple @ 2020-05-14 12:19 UTC (permalink / raw)
  To: Christophe Leroy
  Cc: Jordan Niethe, npiggin, bala24, naveen.n.rao, linuxppc-dev, dja

On Thursday, 14 May 2020 4:15:06 PM AEST Christophe Leroy wrote:
> Shouldn't this patch go before patch 23 ?

Perhaps I am missing something, but it seems reasonable enough to me that you 
would introduce the machinery for dealing with prefix instructions prior to 
defining them. What would be the advantage of doing things the other way 
around?

- Alistair

> Christophe
> 
> Le 06/05/2020 à 05:40, Jordan Niethe a écrit :
> > 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
> > v6: - Compile on ppc32
> > 
> >      - Add back in + GETLENGTH(op->type)
> > 
> > v8: Use fallthrough; keyword
> > ---
> > 
> >   arch/powerpc/include/asm/sstep.h |   4 +
> >   arch/powerpc/lib/sstep.c         | 163 ++++++++++++++++++++++++++++++-
> >   2 files changed, 165 insertions(+), 2 deletions(-)
> > 
> > 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 ecd756c346fd..6794a7672ad5 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,9 @@ 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;
> > 
> > +#ifdef __powerpc64__
> > +	unsigned int suffixopcode, prefixtype, prefix_r;
> > +#endif
> > 
> >   	unsigned long int imm;
> >   	unsigned long int val, val2;
> >   	unsigned int mb, me, sh;
> > 
> > @@ -2652,6 +2693,124 @@ 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;
> > +				fallthrough;
> > +			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;
> > +				fallthrough;
> > +			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__ */
> >   
> >   	}
> > 
> > @@ -2760,7 +2919,7 @@ void emulate_update_regs(struct pt_regs *regs,
> > struct instruction_op *op)> 
> >   {
> >   
> >   	unsigned long next_pc;
> > 
> > -	next_pc = truncate_if_32bit(regs->msr, regs->nip + 4);
> > +	next_pc = truncate_if_32bit(regs->msr, regs->nip + GETLENGTH(op-
>type));
> > 
> >   	switch (GETTYPE(op->type)) {
> >   	
> >   	case COMPUTE:
> >   		if (op->type & SETREG)
> > 
> > @@ -3205,7 +3364,7 @@ int emulate_step(struct pt_regs *regs, struct
> > ppc_inst instr)> 
> >   	return 0;
> >   	
> >    instr_done:
> > -	regs->nip = truncate_if_32bit(regs->msr, regs->nip + 4);
> > +	regs->nip = truncate_if_32bit(regs->msr, regs->nip +
> > GETLENGTH(op.type));
> > 
> >   	return 1;
> >   
> >   }
> >   NOKPROBE_SYMBOL(emulate_step);





^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 23/30] powerpc: Add prefixed instructions to instruction data type
  2020-05-14  6:11   ` Christophe Leroy
  2020-05-14 12:06     ` Alistair Popple
@ 2020-05-14 12:28     ` Jordan Niethe
  2020-05-15  1:33     ` Michael Ellerman
  2 siblings, 0 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-14 12:28 UTC (permalink / raw)
  To: Christophe Leroy
  Cc: Christophe Leroy, Alistair Popple, Nicholas Piggin,
	Balamuruhan S, naveen.n.rao, linuxppc-dev, Daniel Axtens

On Thu, May 14, 2020 at 4:12 PM Christophe Leroy
<christophe.leroy@csgroup.eu> wrote:
>
>
>
> Le 06/05/2020 à 05:40, Jordan Niethe a écrit :
> > 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.
> >
> > Reviewed-by: Alistair Popple <alistair@popple.id.au>
> > 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
> > v6:  - Return false instead of 0 in ppc_inst_prefixed()
> >       - Fix up types for ppc32 so it compiles
> >       - remove ppc_inst_write()
> >       - __patching_instruction(): move flush out of condition
> > v8:  - style
> >       - Define and use OP_PREFIX instead of '1' (back from v3)
> >       - __patch_instruction() fix for big endian
> > ---
> >   arch/powerpc/include/asm/inst.h       | 69 ++++++++++++++++++++++++---
> >   arch/powerpc/include/asm/kprobes.h    |  2 +-
> >   arch/powerpc/include/asm/ppc-opcode.h |  3 ++
> >   arch/powerpc/include/asm/uaccess.h    | 40 +++++++++++++++-
> >   arch/powerpc/include/asm/uprobes.h    |  2 +-
> >   arch/powerpc/kernel/crash_dump.c      |  2 +-
> >   arch/powerpc/kernel/optprobes.c       | 42 ++++++++--------
> >   arch/powerpc/kernel/optprobes_head.S  |  3 ++
> >   arch/powerpc/lib/code-patching.c      | 19 ++++++--
> >   arch/powerpc/lib/feature-fixups.c     |  5 +-
> >   arch/powerpc/lib/inst.c               | 41 ++++++++++++++++
> >   arch/powerpc/lib/sstep.c              |  4 +-
> >   arch/powerpc/xmon/xmon.c              |  4 +-
> >   arch/powerpc/xmon/xmon_bpts.S         |  2 +
> >   14 files changed, 200 insertions(+), 38 deletions(-)
> >
> > diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h
> > index 2f3c9d5bcf7c..7868b80b610e 100644
> > --- a/arch/powerpc/include/asm/inst.h
> > +++ b/arch/powerpc/include/asm/inst.h
> > @@ -2,29 +2,79 @@
> >   #ifndef _ASM_INST_H
> >   #define _ASM_INST_H
> >
> > +#include <asm/ppc-opcode.h>
> >   /*
> >    * Instruction data type for POWER
> >    */
> >
> >   struct ppc_inst {
> >       u32 val;
> > +#ifdef __powerpc64__
>
> CONFIG_PPC64 should be used instead. This is also reported by checkpatch.
Sure will use that instead.
>
> > +     u32 suffix;
> > +#endif /* __powerpc64__ */
> >   } __packed;
> >
> > -#define ppc_inst(x) ((struct ppc_inst){ .val = x })
> > -
> >   static inline u32 ppc_inst_val(struct ppc_inst x)
> >   {
> >       return x.val;
> >   }
> >
> > -static inline int ppc_inst_len(struct ppc_inst x)
> > +static inline int ppc_inst_primary_opcode(struct ppc_inst x)
> >   {
> > -     return sizeof(struct ppc_inst);
> > +     return ppc_inst_val(x) >> 26;
>
> What about using get_op() from asm/disassemble.h instead of hardcodiing ?
Okay will use it here and the other places you point out.
>
> >   }
> >
> > -static inline int ppc_inst_primary_opcode(struct ppc_inst x)
> > +#ifdef __powerpc64__
>
> Use CONFIG_PPC64
>
> > +#define ppc_inst(x) ((struct ppc_inst){ .val = (x), .suffix = 0xff })
> > +
> > +#define ppc_inst_prefix(x, y) ((struct ppc_inst){ .val = (x), .suffix = (y) })
> > +
> > +static inline u32 ppc_inst_suffix(struct ppc_inst x)
> >   {
> > -     return ppc_inst_val(x) >> 26;
> > +     return x.suffix;
> > +}
> > +
> > +static inline bool ppc_inst_prefixed(struct ppc_inst x)
> > +{
> > +     return (ppc_inst_primary_opcode(x) == 1) && ppc_inst_suffix(x) != 0xff;
> > +}
> > +
> > +static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
> > +{
> > +     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;
> > +
> > +     val = *(u32 *)ptr;
> > +     if ((val >> 26) == 1) {
>
> Don't hardcode, use ppc_inst_primary_opcode() and compare it to OP_PREFIX
> Or use get_op() from asm/disassemble.h
>
>
> > +             suffix = *((u32 *)ptr + 1);
> > +             return ppc_inst_prefix(val, suffix);
> > +     } else {
> > +             return ppc_inst(val);
> > +     }
> > +}
> > +
> > +static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
> > +{
> > +     return *(u64 *)&x == *(u64 *)&y;
> > +}
> > +
> > +#else
> > +
> > +#define ppc_inst(x) ((struct ppc_inst){ .val = x })
> > +
> > +static inline bool ppc_inst_prefixed(struct ppc_inst x)
> > +{
> > +     return false;
> > +}
> > +
> > +static inline u32 ppc_inst_suffix(struct ppc_inst x)
> > +{
> > +     return 0;
> >   }
> >
> >   static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
> > @@ -42,6 +92,13 @@ static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
> >       return ppc_inst_val(x) == ppc_inst_val(y);
> >   }
> >
> > +#endif /* __powerpc64__ */
> > +
> > +static inline int ppc_inst_len(struct ppc_inst x)
> > +{
> > +     return (ppc_inst_prefixed(x)) ? 8  : 4;
> > +}
> > +
> >   int probe_user_read_inst(struct ppc_inst *inst,
> >                        struct ppc_inst *nip);
> >   int probe_kernel_read_inst(struct ppc_inst *inst,
> > 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/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h
> > index c1df75edde44..2a39c716c343 100644
> > --- a/arch/powerpc/include/asm/ppc-opcode.h
> > +++ b/arch/powerpc/include/asm/ppc-opcode.h
> > @@ -158,6 +158,9 @@
> >   /* VMX Vector Store Instructions */
> >   #define OP_31_XOP_STVX          231
> >
> > +/* Prefixed Instructions */
> > +#define OP_PREFIX            1
> > +
> >   #define OP_31   31
> >   #define OP_LWZ  32
> >   #define OP_STFS 52
> > diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h
> > index c0a35e4586a5..217897927926 100644
> > --- a/arch/powerpc/include/asm/uaccess.h
> > +++ b/arch/powerpc/include/asm/uaccess.h
> > @@ -105,11 +105,49 @@ static inline int __access_ok(unsigned long addr, unsigned long size,
> >   #define __put_user_inatomic(x, ptr) \
> >       __put_user_nosleep((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
> >
> > +#ifdef __powerpc64__
>
> Replace by CONFIG_PPC64
>
> > +#define __get_user_instr(x, ptr)                     \
> > +({                                                   \
> > +     long __gui_ret = 0;                             \
> > +     unsigned long __gui_ptr = (unsigned long)ptr;   \
> > +     struct ppc_inst __gui_inst;                     \
> > +     unsigned int prefix, suffix;                    \
> > +     __gui_ret = __get_user(prefix, (unsigned int __user *)__gui_ptr);       \
>
> __get_user() can be costly especially with KUAP. I think you should
> perform a 64 bits read and fallback on a 32 bits read only if the 64
> bits read failed.
Thanks, I will try doing it that way.
>
> > +     if (!__gui_ret && (prefix >> 26) == OP_PREFIX) {        \
>
> What about using get_op() from asm/disassemble.h instead of hardcodiing ?
>
> > +             __gui_ret = __get_user(suffix,          \
> > +                                    (unsigned int __user *)__gui_ptr + 1);   \
> > +             __gui_inst = ppc_inst_prefix(prefix, suffix);   \
> > +     } else {                                        \
> > +             __gui_inst = ppc_inst(prefix);          \
> > +     }                                               \
> > +     (x) = __gui_inst;                               \
> > +     __gui_ret;                                      \
> > +})
> > +
> > +#define __get_user_instr_inatomic(x, ptr)            \
> > +({                                                   \
> > +     long __gui_ret = 0;                             \
> > +     unsigned long __gui_ptr = (unsigned long)ptr;   \
> > +     struct ppc_inst __gui_inst;                     \
> > +     unsigned int prefix, suffix;                    \
> > +     __gui_ret = __get_user_inatomic(prefix, (unsigned int __user *)__gui_ptr);      \
>
> Same
>
> > +     if (!__gui_ret && (prefix >> 26) == OP_PREFIX) {        \
> > +             __gui_ret = __get_user_inatomic(suffix, \
> > +                                             (unsigned int __user *)__gui_ptr + 1);  \
> > +             __gui_inst = ppc_inst_prefix(prefix, suffix);   \
> > +     } else {                                        \
> > +             __gui_inst = ppc_inst(prefix);          \
> > +     }                                               \
> > +     (x) = __gui_inst;                               \
> > +     __gui_ret;                                      \
> > +})
> > +#else
> >   #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))
> > +#endif
> > +
> >   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/crash_dump.c b/arch/powerpc/kernel/crash_dump.c
> > index 72bafb47e757..735e89337398 100644
> > --- a/arch/powerpc/kernel/crash_dump.c
> > +++ b/arch/powerpc/kernel/crash_dump.c
> > @@ -46,7 +46,7 @@ static void __init create_trampoline(unsigned long addr)
> >        * two instructions it doesn't require any registers.
> >        */
> >       patch_instruction(p, ppc_inst(PPC_INST_NOP));
> > -     patch_branch(++p, addr + PHYSICAL_START, 0);
> > +     patch_branch((void *)p + 4, addr + PHYSICAL_START, 0);
> >   }
> >
> >   void __init setup_kdump_trampoline(void)
> > diff --git a/arch/powerpc/kernel/optprobes.c b/arch/powerpc/kernel/optprobes.c
> > index 52c1ab3f85aa..a8e66603d12b 100644
> > --- a/arch/powerpc/kernel/optprobes.c
> > +++ b/arch/powerpc/kernel/optprobes.c
> > @@ -162,43 +162,43 @@ 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)
>
> I think this change should go in a separate patch.
Okay.
>
> >   {
> > -     /* lis r3,(op)@highest */
> > +     /* lis reg,(op)@highest */
> >       patch_instruction((struct ppc_inst *)addr,
> > -                       ppc_inst(PPC_INST_ADDIS | ___PPC_RT(3) |
> > +                       ppc_inst(PPC_INST_ADDIS | ___PPC_RT(reg) |
> >                                  ((val >> 48) & 0xffff)));
> >       addr++;
> >
> > -     /* ori r3,r3,(op)@higher */
> > +     /* ori reg,reg,(op)@higher */
> >       patch_instruction((struct ppc_inst *)addr,
> > -                       ppc_inst(PPC_INST_ORI | ___PPC_RA(3) |
> > -                                ___PPC_RS(3) | ((val >> 32) & 0xffff)));
> > +                       ppc_inst(PPC_INST_ORI | ___PPC_RA(reg) |
> > +                                ___PPC_RS(reg) | ((val >> 32) & 0xffff)));
> >       addr++;
> >
> > -     /* rldicr r3,r3,32,31 */
> > +     /* rldicr reg,reg,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)));
> > +                       ppc_inst(PPC_INST_RLDICR | ___PPC_RA(reg) |
> > +                                ___PPC_RS(reg) | __PPC_SH64(32) | __PPC_ME64(31)));
> >       addr++;
> >
> > -     /* oris r3,r3,(op)@h */
> > +     /* oris reg,reg,(op)@h */
> >       patch_instruction((struct ppc_inst *)addr,
> > -                       ppc_inst(PPC_INST_ORIS | ___PPC_RA(3) |
> > -                                ___PPC_RS(3) | ((val >> 16) & 0xffff)));
> > +                       ppc_inst(PPC_INST_ORIS | ___PPC_RA(reg) |
> > +                                ___PPC_RS(reg) | ((val >> 16) & 0xffff)));
> >       addr++;
> >
> > -     /* ori r3,r3,(op)@l */
> > +     /* ori reg,reg,(op)@l */
> >       patch_instruction((struct ppc_inst *)addr,
> > -                       ppc_inst(PPC_INST_ORI | ___PPC_RA(3) |
> > -                                ___PPC_RS(3) | (val & 0xffff)));
> > +                       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;
> > @@ -249,7 +249,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()
> > @@ -282,7 +282,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,
>
> So now we are also using r4 ? Any explanation somewhere on the way it
> works ? This change seems unrelated to this patch, nothing in the
> description about it. Can we suddenly use a new register without problem ?
Sorry it is not very clear, r4 was always being used.
patch_imm32_load_insns() hardcoded r4. We now need to load 64 bits as
we just introduced prefixed instruction, so are using
patch_imm64_load_insns(). That is the connection to the patch. But a
separate patch and description would probably make that clearer.

>
> > +                            buff + TMPL_INSN_IDX);
>
> What's the point with splitting this line in 4 lines ? Can't it fit in 2
> lines ?
Sure.
>
> >
> >       /*
> >        * 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/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
> > index d946f7d6bb32..58b67b62d5d3 100644
> > --- a/arch/powerpc/lib/code-patching.c
> > +++ b/arch/powerpc/lib/code-patching.c
> > @@ -24,13 +24,24 @@ 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;
> > +     if (!ppc_inst_prefixed(instr)) {
> > +             __put_user_asm(ppc_inst_val(instr), patch_addr, err, "stw");
> > +             if (err)
> > +                     return err;
>
> This test should remain outside of the if/else, it doesn't need to be
> duplicated.
Okay.
>
> > +     } else {
> > +#ifdef CONFIG_CPU_LITTLE_ENDIAN
> > +             __put_user_asm((u64)ppc_inst_suffix(instr) << 32 |
> > +                            ppc_inst_val(instr), patch_addr, err, "std");
> > +#else
> > +             __put_user_asm((u64)ppc_inst_val(instr) << 32 |
> > +                            ppc_inst_suffix(instr), patch_addr, err, "std");
> > +#endif /* CONFIG_CPU_LITTLE_ENDIAN */
> > +             if (err)
> > +                     return err;
> > +     }
> >
> >       asm ("dcbst 0, %0; sync; icbi 0,%1; sync; isync" :: "r" (patch_addr),
> >                                                           "r" (exec_addr));
> > -
>
> Why remove the blank line ?
Sorry that was by mistake.
>
> >       return 0;
> >   }
> >
> > diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c
> > index 2bd2b752de4f..a8238eff3a31 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)))) {
>
> Can we do this outside the for() for readability ?
You are right, I will make it clearer.
>
> >               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/inst.c b/arch/powerpc/lib/inst.c
> > index 08dedd927268..eb6f9ee28ac6 100644
> > --- a/arch/powerpc/lib/inst.c
> > +++ b/arch/powerpc/lib/inst.c
> > @@ -3,9 +3,49 @@
> >    *  Copyright 2020, IBM Corporation.
> >    */
> >
> > +#include <asm/ppc-opcode.h>
> >   #include <linux/uaccess.h>
> >   #include <asm/inst.h>
> >
> > +#ifdef __powerpc64__
> > +int probe_user_read_inst(struct ppc_inst *inst,
> > +                      struct ppc_inst *nip)
> > +{
> > +     unsigned int val, suffix;
> > +     int err;
> > +
> > +     err = probe_user_read(&val, nip, sizeof(val));
>
> A user read is costly with KUAP. Can we do a 64 bits read and perform a
> 32 bits read only when 64 bits read fails ?
>
> > +     if (err)
> > +             return err;
> > +     if ((val >> 26) == OP_PREFIX) {
>
> What about using get_op() from asm/disassemble.h instead of hardcodiing ?
>
> > +             err = probe_user_read(&suffix, (void *)nip + 4,
>
> 4 or sizeof(unsigned int) ? Why use both in the same line ?
True, doesn't really make sense.
>
> > +                                   sizeof(unsigned int));
> > +             *inst = ppc_inst_prefix(val, suffix);
> > +     } else {
> > +             *inst = ppc_inst(val);
> > +     }
> > +     return err;
> > +}
> > +
> > +int probe_kernel_read_inst(struct ppc_inst *inst,
> > +                        struct ppc_inst *src)
> > +{
> > +     unsigned int val, suffix;
> > +     int err;
> > +
> > +     err = probe_kernel_read(&val, src, sizeof(val));
> > +     if (err)
> > +             return err;
> > +     if ((val >> 26) == OP_PREFIX) {
> > +             err = probe_kernel_read(&suffix, (void *)src + 4,
> > +                                     sizeof(unsigned int));
> > +             *inst = ppc_inst_prefix(val, suffix);
> > +     } else {
> > +             *inst = ppc_inst(val);
> > +     }
> > +     return err;
> > +}
> > +#else
> >   int probe_user_read_inst(struct ppc_inst *inst,
> >                        struct ppc_inst *nip)
> >   {
> > @@ -27,3 +67,4 @@ int probe_kernel_read_inst(struct ppc_inst *inst,
> >       *inst = ppc_inst(val);
> >       return err;
> >   }
> > +#endif /* __powerpc64__ */
> > diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
> > index 95a56bb1ba3f..ecd756c346fd 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 = ppc_inst_primary_opcode(instr);
> > diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
> > index 4d6980d51456..647b3829c4eb 100644
> > --- a/arch/powerpc/xmon/xmon.c
> > +++ b/arch/powerpc/xmon/xmon.c
> > @@ -758,8 +758,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;
> >       }
> > diff --git a/arch/powerpc/xmon/xmon_bpts.S b/arch/powerpc/xmon/xmon_bpts.S
> > index f3ad0ab50854..69726814cd27 100644
> > --- a/arch/powerpc/xmon/xmon_bpts.S
> > +++ b/arch/powerpc/xmon/xmon_bpts.S
> > @@ -4,6 +4,8 @@
> >   #include <asm/asm-offsets.h>
> >   #include "xmon_bpts.h"
> >
> > +/* Prefixed instructions can not cross 64 byte boundaries */
> > +.align 6
> >   .global bpt_table
> >   bpt_table:
> >       .space NBPTS * BPT_SIZE
> >
>
> Christophe

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 23/30] powerpc: Add prefixed instructions to instruction data type
  2020-05-14 12:06     ` Alistair Popple
@ 2020-05-14 12:29       ` Jordan Niethe
  2020-05-14 12:57       ` Christophe Leroy
  1 sibling, 0 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-14 12:29 UTC (permalink / raw)
  To: Alistair Popple
  Cc: Christophe Leroy, Nicholas Piggin, Balamuruhan S, naveen.n.rao,
	linuxppc-dev, Daniel Axtens

On Thu, May 14, 2020 at 10:06 PM Alistair Popple <alistair@popple.id.au> wrote:
>
> On Thursday, 14 May 2020 4:11:43 PM AEST Christophe Leroy wrote:
> > @@ -249,7 +249,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()
> > > @@ -282,7 +282,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,
> >
> > So now we are also using r4 ? Any explanation somewhere on the way it
> > works ? This change seems unrelated to this patch, nothing in the
> > description about it. Can we suddenly use a new register without problem ?
>
> Unless I missed something there is no change in register usage here that I
> could see. patch_imm32_load_insns() was/is hardcoded to use register r4.
Yes, that is right.
>
> - Alistair
>
>

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 23/30] powerpc: Add prefixed instructions to instruction data type
  2020-05-14 12:06     ` Alistair Popple
  2020-05-14 12:29       ` Jordan Niethe
@ 2020-05-14 12:57       ` Christophe Leroy
  1 sibling, 0 replies; 81+ messages in thread
From: Christophe Leroy @ 2020-05-14 12:57 UTC (permalink / raw)
  To: Alistair Popple
  Cc: christophe.leroy, Jordan Niethe, npiggin, bala24, naveen.n.rao,
	linuxppc-dev, dja



Le 14/05/2020 à 14:06, Alistair Popple a écrit :
> On Thursday, 14 May 2020 4:11:43 PM AEST Christophe Leroy wrote:
>> @@ -249,7 +249,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()
>>> @@ -282,7 +282,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,
>>
>> So now we are also using r4 ? Any explanation somewhere on the way it
>> works ? This change seems unrelated to this patch, nothing in the
>> description about it. Can we suddenly use a new register without problem ?
> 
> Unless I missed something there is no change in register usage here that I
> could see. patch_imm32_load_insns() was/is hardcoded to use register r4.
> 

Ah ... Euh ... Ok I missed the change from patch_imm32_load_insns() to 
patch_imm64_load_insns(), I'll check again.

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 28/30] powerpc: Support prefixed instructions in alignment handler
  2020-05-14 12:15     ` Alistair Popple
@ 2020-05-14 12:59       ` Christophe Leroy
  0 siblings, 0 replies; 81+ messages in thread
From: Christophe Leroy @ 2020-05-14 12:59 UTC (permalink / raw)
  To: Alistair Popple
  Cc: Jordan Niethe, npiggin, bala24, naveen.n.rao, linuxppc-dev, dja



Le 14/05/2020 à 14:15, Alistair Popple a écrit :
> On Thursday, 14 May 2020 4:14:12 PM AEST Christophe Leroy wrote:
>> Le 06/05/2020 à 05:40, Jordan Niethe a écrit :
>>> 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().
>>
>> Shouldn't this patch go before patch 23 ?
> 
> Is there a particular reason you think it needs to go before patch 23? Neither
> seem particularly related to one another and it seems logical to me at least
> that you would introduce prefix support to the datatype prior to using them.

If you enable prefix instruction and allow people to use them before you 
have implemented proper support in alignment handler, what will happen 
if an alignment exception occurs ?

Christophe

> 
> - Alistair
>   
>> Christophe
>>
>>> Reviewed-by: Alistair Popple <alistair@popple.id.au>
>>> 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 493a3fa0ac1a..105242cc2f28 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

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 29/30] powerpc sstep: Add support for prefixed load/stores
  2020-05-14 12:19     ` Alistair Popple
@ 2020-05-14 13:00       ` Christophe Leroy
  0 siblings, 0 replies; 81+ messages in thread
From: Christophe Leroy @ 2020-05-14 13:00 UTC (permalink / raw)
  To: Alistair Popple
  Cc: Jordan Niethe, npiggin, bala24, naveen.n.rao, linuxppc-dev, dja



Le 14/05/2020 à 14:19, Alistair Popple a écrit :
> On Thursday, 14 May 2020 4:15:06 PM AEST Christophe Leroy wrote:
>> Shouldn't this patch go before patch 23 ?
> 
> Perhaps I am missing something, but it seems reasonable enough to me that you
> would introduce the machinery for dealing with prefix instructions prior to
> defining them. What would be the advantage of doing things the other way
> around?

If someone single steps a prefixed instruction before the kernel is able 
to single step them, what happens ?

Christophe

> 
> - Alistair
> 
>> Christophe
>>
>> Le 06/05/2020 à 05:40, Jordan Niethe a écrit :
>>> 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
>>> v6: - Compile on ppc32
>>>
>>>       - Add back in + GETLENGTH(op->type)
>>>
>>> v8: Use fallthrough; keyword
>>> ---
>>>
>>>    arch/powerpc/include/asm/sstep.h |   4 +
>>>    arch/powerpc/lib/sstep.c         | 163 ++++++++++++++++++++++++++++++-
>>>    2 files changed, 165 insertions(+), 2 deletions(-)
>>>
>>> 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 ecd756c346fd..6794a7672ad5 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,9 @@ 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;
>>>
>>> +#ifdef __powerpc64__
>>> +	unsigned int suffixopcode, prefixtype, prefix_r;
>>> +#endif
>>>
>>>    	unsigned long int imm;
>>>    	unsigned long int val, val2;
>>>    	unsigned int mb, me, sh;
>>>
>>> @@ -2652,6 +2693,124 @@ 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;
>>> +				fallthrough;
>>> +			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;
>>> +				fallthrough;
>>> +			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__ */
>>>    
>>>    	}
>>>
>>> @@ -2760,7 +2919,7 @@ void emulate_update_regs(struct pt_regs *regs,
>>> struct instruction_op *op)>
>>>    {
>>>    
>>>    	unsigned long next_pc;
>>>
>>> -	next_pc = truncate_if_32bit(regs->msr, regs->nip + 4);
>>> +	next_pc = truncate_if_32bit(regs->msr, regs->nip + GETLENGTH(op-
>> type));
>>>
>>>    	switch (GETTYPE(op->type)) {
>>>    	
>>>    	case COMPUTE:
>>>    		if (op->type & SETREG)
>>>
>>> @@ -3205,7 +3364,7 @@ int emulate_step(struct pt_regs *regs, struct
>>> ppc_inst instr)>
>>>    	return 0;
>>>    	
>>>     instr_done:
>>> -	regs->nip = truncate_if_32bit(regs->msr, regs->nip + 4);
>>> +	regs->nip = truncate_if_32bit(regs->msr, regs->nip +
>>> GETLENGTH(op.type));
>>>
>>>    	return 1;
>>>    
>>>    }
>>>    NOKPROBE_SYMBOL(emulate_step);

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 23/30] powerpc: Add prefixed instructions to instruction data type
  2020-05-14  6:11   ` Christophe Leroy
  2020-05-14 12:06     ` Alistair Popple
  2020-05-14 12:28     ` Jordan Niethe
@ 2020-05-15  1:33     ` Michael Ellerman
  2020-05-15  7:52       ` Jordan Niethe
  2 siblings, 1 reply; 81+ messages in thread
From: Michael Ellerman @ 2020-05-15  1:33 UTC (permalink / raw)
  To: Christophe Leroy, Jordan Niethe, linuxppc-dev
  Cc: christophe.leroy, alistair, npiggin, bala24, naveen.n.rao, dja

Christophe Leroy <christophe.leroy@csgroup.eu> writes:
> Le 06/05/2020 à 05:40, Jordan Niethe a écrit :
>> 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.

...

>> diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h
>> index c0a35e4586a5..217897927926 100644
>> --- a/arch/powerpc/include/asm/uaccess.h
>> +++ b/arch/powerpc/include/asm/uaccess.h
>> @@ -105,11 +105,49 @@ static inline int __access_ok(unsigned long addr, unsigned long size,
>>   #define __put_user_inatomic(x, ptr) \
>>   	__put_user_nosleep((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
>>   
>> +#ifdef __powerpc64__
>
> Replace by CONFIG_PPC64
>
>> +#define __get_user_instr(x, ptr)			\
>> +({							\
>> +	long __gui_ret = 0;				\
>> +	unsigned long __gui_ptr = (unsigned long)ptr;	\
>> +	struct ppc_inst __gui_inst;			\
>> +	unsigned int prefix, suffix;			\
>> +	__gui_ret = __get_user(prefix, (unsigned int __user *)__gui_ptr);	\
>
> __get_user() can be costly especially with KUAP. I think you should 
> perform a 64 bits read and fallback on a 32 bits read only if the 64 
> bits read failed.

I worry that might break something.

It _should_ be safe, but I'm paranoid.

If we think the KUAP overhead is a problem then I think we'd be better
off pulling the KUAP disable/enable into this macro.

>> diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c
>> index 2bd2b752de4f..a8238eff3a31 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)))) {
>
> Can we do this outside the for() for readability ?

I have an idea for cleaning these up, will post it as a follow-up to the series.

>> diff --git a/arch/powerpc/lib/inst.c b/arch/powerpc/lib/inst.c
>> index 08dedd927268..eb6f9ee28ac6 100644
>> --- a/arch/powerpc/lib/inst.c
>> +++ b/arch/powerpc/lib/inst.c
>> @@ -3,9 +3,49 @@
>>    *  Copyright 2020, IBM Corporation.
>>    */
>>   
>> +#include <asm/ppc-opcode.h>
>>   #include <linux/uaccess.h>
>>   #include <asm/inst.h>
>>   
>> +#ifdef __powerpc64__
>> +int probe_user_read_inst(struct ppc_inst *inst,
>> +			 struct ppc_inst *nip)
>> +{
>> +	unsigned int val, suffix;
>> +	int err;
>> +
>> +	err = probe_user_read(&val, nip, sizeof(val));
>
> A user read is costly with KUAP. Can we do a 64 bits read and perform a 
> 32 bits read only when 64 bits read fails ?

Same comment as above.


cheers

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 13/30] powerpc: Add a probe_user_read_inst() function
  2020-05-14  5:46   ` Christophe Leroy
@ 2020-05-15  3:46     ` Jordan Niethe
  0 siblings, 0 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-15  3:46 UTC (permalink / raw)
  To: Christophe Leroy
  Cc: Christophe Leroy, Alistair Popple, Nicholas Piggin,
	Balamuruhan S, naveen.n.rao, linuxppc-dev, Daniel Axtens

On Thu, May 14, 2020 at 3:46 PM Christophe Leroy
<christophe.leroy@csgroup.eu> wrote:
>
>
>
> Le 06/05/2020 à 05:40, Jordan Niethe a écrit :
> > Introduce a probe_user_read_inst() function to use in cases where
> > probe_user_read() is used for getting an instruction. This will be more
> > useful for prefixed instructions.
> >
> > Reviewed-by: Alistair Popple <alistair@popple.id.au>
> > Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> > ---
> > v6: - New to series
> > ---
> >   arch/powerpc/include/asm/inst.h |  3 +++
> >   arch/powerpc/lib/Makefile       |  2 +-
> >   arch/powerpc/lib/inst.c         | 18 ++++++++++++++++++
> >   arch/powerpc/mm/fault.c         |  2 +-
> >   4 files changed, 23 insertions(+), 2 deletions(-)
> >   create mode 100644 arch/powerpc/lib/inst.c
> >
> > diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h
> > index 552e953bf04f..3e9a58420151 100644
> > --- a/arch/powerpc/include/asm/inst.h
> > +++ b/arch/powerpc/include/asm/inst.h
> > @@ -37,4 +37,7 @@ static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
> >       return ppc_inst_val(x) == ppc_inst_val(y);
> >   }
> >
> > +int probe_user_read_inst(struct ppc_inst *inst,
> > +                      struct ppc_inst *nip);
> > +
> >   #endif /* _ASM_INST_H */
> > diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
> > index b8de3be10eb4..546591848219 100644
> > --- a/arch/powerpc/lib/Makefile
> > +++ b/arch/powerpc/lib/Makefile
> > @@ -16,7 +16,7 @@ CFLAGS_code-patching.o += -DDISABLE_BRANCH_PROFILING
> >   CFLAGS_feature-fixups.o += -DDISABLE_BRANCH_PROFILING
> >   endif
> >
> > -obj-y += alloc.o code-patching.o feature-fixups.o pmem.o
> > +obj-y += alloc.o code-patching.o feature-fixups.o pmem.o inst.o
> >
> >   ifndef CONFIG_KASAN
> >   obj-y       +=      string.o memcmp_$(BITS).o
> > diff --git a/arch/powerpc/lib/inst.c b/arch/powerpc/lib/inst.c
> > new file mode 100644
> > index 000000000000..eaf786afad2b
> > --- /dev/null
> > +++ b/arch/powerpc/lib/inst.c
> > @@ -0,0 +1,18 @@
> > +// SPDX-License-Identifier: GPL-2.0-or-later
> > +/*
> > + *  Copyright 2020, IBM Corporation.
> > + */
> > +
> > +#include <linux/uaccess.h>
> > +#include <asm/inst.h>
> > +
> > +int probe_user_read_inst(struct ppc_inst *inst,
> > +                      struct ppc_inst *nip)
> > +{
> > +     unsigned int val;
> > +     int err;
> > +
> > +     err = probe_user_read(&val, nip, sizeof(val));
> > +     *inst = ppc_inst(val);
> > +     return err;
> > +}
> > diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
> > index 4a50f125ec18..f3a943eae305 100644
> > --- a/arch/powerpc/mm/fault.c
> > +++ b/arch/powerpc/mm/fault.c
> > @@ -281,7 +281,7 @@ static bool bad_stack_expansion(struct pt_regs *regs, unsigned long address,
> >                   access_ok(nip, sizeof(*nip))) {
> >                       struct ppc_inst inst;
> >
> > -                     if (!probe_user_read(&inst, nip, sizeof(inst)))
> > +                     if (!probe_user_read_inst(&inst, (struct ppc_inst __user *)nip))
>
> Shouldn't 'nip' become de 'struct ppc_inst __user *' instead of casting ?
>
> >                               return !store_updates_sp(inst);
> >                       *must_retry = true;
> >               }
> >
Yeah it would make more sense to do it like this.
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -256,7 +256,7 @@ static bool bad_stack_expansion(struct pt_regs
*regs, unsigned long address,
      * expand to 1MB without further checks.
      */
     if (address + 0x100000 < vma->vm_end) {
-        unsigned int __user *nip = (unsigned int __user *)regs->nip;
+        struct ppc_inst __user *nip = (struct ppc_inst __user *)regs->nip;
         /* get user regs even if this fault is in kernel mode */
         struct pt_regs *uregs = current->thread.regs;
         if (uregs == NULL)
@@ -281,7 +281,7 @@ static bool bad_stack_expansion(struct pt_regs
*regs, unsigned long address,
             access_ok(nip, sizeof(*nip))) {
             struct ppc_inst inst;

-            if (!probe_user_read_inst(&inst, (struct ppc_inst __user *)nip))
+            if (!probe_user_read_inst(&inst, nip))
                 return !store_updates_sp(inst);
             *must_retry = true;
         }
-- 
2.17.1
>
> Christophe

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 08/30] powerpc: Use a function for getting the instruction op code
  2020-05-06  3:40 ` [PATCH v8 08/30] powerpc: Use a function for getting the instruction op code Jordan Niethe
@ 2020-05-15  7:48   ` Jordan Niethe
  2020-05-16 11:08     ` Michael Ellerman
  0 siblings, 1 reply; 81+ messages in thread
From: Jordan Niethe @ 2020-05-15  7:48 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Christophe Leroy, Alistair Popple, Nicholas Piggin,
	Balamuruhan S, naveen.n.rao, Daniel Axtens

mpe, as suggested by Christophe could you please add this.
diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h
--- a/arch/powerpc/include/asm/inst.h
+++ b/arch/powerpc/include/asm/inst.h
@@ -2,6 +2,8 @@
 #ifndef _ASM_INST_H
 #define _ASM_INST_H

+#include <asm/disassemble.h>
+
 /*
  * Instruction data type for POWER
  */
@@ -15,7 +17,7 @@ static inline u32 ppc_inst_val(u32 x)

 static inline int ppc_inst_primary_opcode(u32 x)
 {
-    return ppc_inst_val(x) >> 26;
+    return get_op(ppc_inst_val(x));
 }

 #endif /* _ASM_INST_H */
-- 
2.17.1

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 23/30] powerpc: Add prefixed instructions to instruction data type
  2020-05-15  1:33     ` Michael Ellerman
@ 2020-05-15  7:52       ` Jordan Niethe
  0 siblings, 0 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-15  7:52 UTC (permalink / raw)
  To: Michael Ellerman
  Cc: Christophe Leroy, Alistair Popple, Nicholas Piggin,
	Balamuruhan S, naveen.n.rao, linuxppc-dev, Daniel Axtens

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

^ permalink raw reply related	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 24/30] powerpc: Test prefixed code patching
  2020-05-06  3:40 ` [PATCH v8 24/30] powerpc: Test prefixed code patching Jordan Niethe
@ 2020-05-15  7:54   ` Jordan Niethe
  0 siblings, 0 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-15  7:54 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Christophe Leroy, Alistair Popple, Nicholas Piggin,
	Balamuruhan S, naveen.n.rao, Daniel Axtens

Hey mpe could you add this please.
diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -707,7 +707,7 @@ static void __init test_translate_branch(void)
     vfree(buf);
 }

-#ifdef __powerpc64__
+#ifdef CONFIG_PPC64
 static void __init test_prefixed_patching(void)
 {
     extern unsigned int code_patching_test1[];
@@ -733,7 +733,7 @@ static int __init test_code_patching(void)
     test_branch_bform();
     test_create_function_call();
     test_translate_branch();
-#ifdef __powerpc64__
+#ifdef CONFIG_PPC64
     test_prefixed_patching();
 #endif

-- 
2.17.1

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 25/30] powerpc: Test prefixed instructions in feature fixups
  2020-05-06  3:40 ` [PATCH v8 25/30] powerpc: Test prefixed instructions in feature fixups Jordan Niethe
@ 2020-05-15  7:57   ` Jordan Niethe
  0 siblings, 0 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-15  7:57 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Christophe Leroy, Alistair Popple, Nicholas Piggin,
	Balamuruhan S, naveen.n.rao, Daniel Axtens

Hey mpe, could you add this thanks.
diff --git a/arch/powerpc/lib/feature-fixups.c
b/arch/powerpc/lib/feature-fixups.c
--- a/arch/powerpc/lib/feature-fixups.c
+++ b/arch/powerpc/lib/feature-fixups.c
@@ -689,7 +689,7 @@ static void test_lwsync_macros(void)
     }
 }

-#ifdef __powerpc64__
+#ifdef CONFIG_PPC64
 static void __init test_prefix_patching(void)
 {
     extern unsigned int ftr_fixup_prefix1[];
@@ -755,7 +755,7 @@ static void __init test_prefix_word_alt_patching(void)
     patch_feature_section(0, &fixup);
     check(memcmp(ftr_fixup_prefix3, ftr_fixup_prefix3_orig, size) != 0);
 }
-#endif /* __powerpc64__ */
+#endif /* CONFIG_PPC64 */

 static int __init test_feature_fixups(void)
 {
@@ -771,7 +771,7 @@ static int __init test_feature_fixups(void)
     test_cpu_macros();
     test_fw_macros();
     test_lwsync_macros();
-#ifdef __powerpc64__
+#ifdef CONFIG_PPC64
     test_prefix_patching();
     test_prefix_alt_patching();
     test_prefix_word_alt_patching();
--

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 29/30] powerpc sstep: Add support for prefixed load/stores
  2020-05-06  3:40 ` [PATCH v8 29/30] powerpc sstep: Add support for prefixed load/stores Jordan Niethe
  2020-05-14  6:15   ` Christophe Leroy
@ 2020-05-15  7:59   ` Jordan Niethe
  1 sibling, 0 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-15  7:59 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Christophe Leroy, Alistair Popple, Nicholas Piggin,
	Balamuruhan S, naveen.n.rao, Daniel Axtens

mpe, and this thanks.
----
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -1204,7 +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;
-#ifdef __powerpc64__
+#ifdef CONFIG_PPC64
     unsigned int suffixopcode, prefixtype, prefix_r;
 #endif
     unsigned long int imm;
@@ -2701,7 +2701,7 @@ int analyse_instr(struct instruction_op *op,
const struct pt_regs *regs,
         op->reg = rd;
         op->val = regs->gpr[rd];

-        suffixopcode = suffix >> 26;
+        suffixopcode = get_op(suffix);
         prefixtype = (word >> 24) & 0x3;
         switch (prefixtype) {
         case 0: /* Type 00  Eight-Byte Load/Store */
-- 
2.17.1

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 30/30] powerpc sstep: Add support for prefixed fixed-point arithmetic
  2020-05-06  3:40 ` [PATCH v8 30/30] powerpc sstep: Add support for prefixed fixed-point arithmetic Jordan Niethe
  2020-05-14  6:15   ` Christophe Leroy
@ 2020-05-15  8:02   ` Jordan Niethe
  1 sibling, 0 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-15  8:02 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Christophe Leroy, Alistair Popple, Nicholas Piggin,
	Balamuruhan S, naveen.n.rao, Daniel Axtens

mpe, and this thanks.
---
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -1343,7 +1343,7 @@ int analyse_instr(struct instruction_op *op,
const struct pt_regs *regs,
         rd = (suffix >> 21) & 0x1f;
         op->reg = rd;
         op->val = regs->gpr[rd];
-        suffixopcode = suffix >> 26;
+        suffixopcode = get_op(suffix);
         prefixtype = (word >> 24) & 0x3;
         switch (prefixtype) {
         case 2:
-- 
2.17.1

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 08/30] powerpc: Use a function for getting the instruction op code
  2020-05-15  7:48   ` Jordan Niethe
@ 2020-05-16 11:08     ` Michael Ellerman
  2020-05-17  7:41       ` Jordan Niethe
  0 siblings, 1 reply; 81+ messages in thread
From: Michael Ellerman @ 2020-05-16 11:08 UTC (permalink / raw)
  To: Jordan Niethe, linuxppc-dev
  Cc: Christophe Leroy, Alistair Popple, Nicholas Piggin,
	Balamuruhan S, naveen.n.rao, Daniel Axtens

Jordan Niethe <jniethe5@gmail.com> writes:
> mpe, as suggested by Christophe could you please add this.

I did that and ...

> diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h
> --- a/arch/powerpc/include/asm/inst.h
> +++ b/arch/powerpc/include/asm/inst.h
> @@ -2,6 +2,8 @@
>  #ifndef _ASM_INST_H
>  #define _ASM_INST_H
>
> +#include <asm/disassemble.h>

.. this eventually breaks the build in some driver, because get_ra() is
redefined.

So I've backed out this change for now.

If we want to use the macros in disassemble.h we'll need to namespace
them better, eg. make them ppc_get_ra() and so on.

cheers

>  /*
>   * Instruction data type for POWER
>   */
> @@ -15,7 +17,7 @@ static inline u32 ppc_inst_val(u32 x)
>
>  static inline int ppc_inst_primary_opcode(u32 x)
>  {
> -    return ppc_inst_val(x) >> 26;
> +    return get_op(ppc_inst_val(x));
>  }
>
>  #endif /* _ASM_INST_H */
> -- 
> 2.17.1

^ permalink raw reply	[flat|nested] 81+ messages in thread

* [PATCH v8 22.5/30] powerpc/optprobes: Add register argument to patch_imm64_load_insns()
  2020-05-06  3:40 ` [PATCH v8 23/30] powerpc: Add prefixed instructions to instruction data type Jordan Niethe
  2020-05-14  1:40   ` Jordan Niethe
  2020-05-14  6:11   ` Christophe Leroy
@ 2020-05-16 11:54   ` Michael Ellerman
  2020-06-09  5:51     ` Michael Ellerman
  2 siblings, 1 reply; 81+ messages in thread
From: Michael Ellerman @ 2020-05-16 11:54 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: christophe.leroy, jniethe5

From: Jordan Niethe <jniethe5@gmail.com>

Currently patch_imm32_load_insns() is used to load an instruction to
r4 to be emulated by emulate_step(). For prefixed instructions we
would like to be able to load a 64bit immediate to r4. To prepare for
this make patch_imm64_load_insns() take an argument that decides which
register to load an immediate to - rather than hardcoding r3.

Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
 arch/powerpc/kernel/optprobes.c | 34 ++++++++++++++++-----------------
 1 file changed, 17 insertions(+), 17 deletions(-)

v8: Split out of patch 23.

diff --git a/arch/powerpc/kernel/optprobes.c b/arch/powerpc/kernel/optprobes.c
index 52c1ab3f85aa..8eea8dbb93fa 100644
--- a/arch/powerpc/kernel/optprobes.c
+++ b/arch/powerpc/kernel/optprobes.c
@@ -162,38 +162,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 */
+	/* lis reg,(op)@highest */
 	patch_instruction((struct ppc_inst *)addr,
-			  ppc_inst(PPC_INST_ADDIS | ___PPC_RT(3) |
+			  ppc_inst(PPC_INST_ADDIS | ___PPC_RT(reg) |
 				   ((val >> 48) & 0xffff)));
 	addr++;
 
-	/* ori r3,r3,(op)@higher */
+	/* ori reg,reg,(op)@higher */
 	patch_instruction((struct ppc_inst *)addr,
-			  ppc_inst(PPC_INST_ORI | ___PPC_RA(3) |
-				   ___PPC_RS(3) | ((val >> 32) & 0xffff)));
+			  ppc_inst(PPC_INST_ORI | ___PPC_RA(reg) |
+				   ___PPC_RS(reg) | ((val >> 32) & 0xffff)));
 	addr++;
 
-	/* rldicr r3,r3,32,31 */
+	/* rldicr reg,reg,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)));
+			  ppc_inst(PPC_INST_RLDICR | ___PPC_RA(reg) |
+				   ___PPC_RS(reg) | __PPC_SH64(32) | __PPC_ME64(31)));
 	addr++;
 
-	/* oris r3,r3,(op)@h */
+	/* oris reg,reg,(op)@h */
 	patch_instruction((struct ppc_inst *)addr,
-			  ppc_inst(PPC_INST_ORIS | ___PPC_RA(3) |
-				   ___PPC_RS(3) | ((val >> 16) & 0xffff)));
+			  ppc_inst(PPC_INST_ORIS | ___PPC_RA(reg) |
+				   ___PPC_RS(reg) | ((val >> 16) & 0xffff)));
 	addr++;
 
-	/* ori r3,r3,(op)@l */
+	/* ori reg,reg,(op)@l */
 	patch_instruction((struct ppc_inst *)addr,
-			  ppc_inst(PPC_INST_ORI | ___PPC_RA(3) |
-				   ___PPC_RS(3) | (val & 0xffff)));
+			  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)
@@ -249,7 +249,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()
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 12/30] powerpc: Use a function for reading instructions
  2020-05-06  3:40 ` [PATCH v8 12/30] powerpc: Use a function for reading instructions Jordan Niethe
@ 2020-05-16 18:39   ` Christophe Leroy
  2020-05-17 10:44     ` Jordan Niethe
  0 siblings, 1 reply; 81+ messages in thread
From: Christophe Leroy @ 2020-05-16 18:39 UTC (permalink / raw)
  To: Jordan Niethe, linuxppc-dev
  Cc: christophe.leroy, alistair, npiggin, bala24, naveen.n.rao, dja



Le 06/05/2020 à 05:40, Jordan Niethe a écrit :
> 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.


Shouldn't this function be used in mmu_patch_addis() in mm/nohash/8xx.c ?

Christophe

> 
> Reviewed-by: Alistair Popple <alistair@popple.id.au>
> 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
> v6: - feature-fixups.c: do_final_fixups(): Use here
>      - arch_prepare_kprobe(): patch_instruction(): no longer part of this
>        patch
>      - Move probe_kernel_read_inst() out of this patch
>      - Use in uprobes
> v8: style
> ---
>   arch/powerpc/include/asm/inst.h    |  5 +++++
>   arch/powerpc/kernel/kprobes.c      |  6 +++---
>   arch/powerpc/kernel/mce_power.c    |  2 +-
>   arch/powerpc/kernel/optprobes.c    |  4 ++--
>   arch/powerpc/kernel/trace/ftrace.c |  4 ++--
>   arch/powerpc/kernel/uprobes.c      |  2 +-
>   arch/powerpc/lib/code-patching.c   | 26 ++++++++++++++------------
>   arch/powerpc/lib/feature-fixups.c  |  4 ++--
>   arch/powerpc/xmon/xmon.c           |  6 +++---
>   9 files changed, 33 insertions(+), 26 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h
> index 19d8bb7a1c2b..552e953bf04f 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 ppc_inst_val(x) == ppc_inst_val(y);
> diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
> index a08ae5803622..f64312dca84f 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");
> @@ -127,7 +127,7 @@ 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;
> +		p->opcode = ppc_inst_val(insn);
>   		flush_icache_range((unsigned long)p->ainsn.insn,
>   			(unsigned long)p->ainsn.insn + sizeof(kprobe_opcode_t));
>   	}
> @@ -217,7 +217,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 cd23218c60bb..45c51ba0071b 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 5a71fef71c22..52c1ab3f85aa 100644
> --- a/arch/powerpc/kernel/optprobes.c
> +++ b/arch/powerpc/kernel/optprobes.c
> @@ -100,9 +100,9 @@ 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) &&
> +	if (!is_conditional_branch(ppc_inst_read((struct ppc_inst *)p->ainsn.insn)) &&
>   	    analyse_instr(&op, &regs,
> -			  *(struct ppc_inst *)p->ainsn.insn) == 1) {
> +			  ppc_inst_read((struct ppc_inst *)p->ainsn.insn)) == 1) {
>   		emulate_update_regs(&regs, &op);
>   		nip = regs.nip;
>   	}
> diff --git a/arch/powerpc/kernel/trace/ftrace.c b/arch/powerpc/kernel/trace/ftrace.c
> index 3117ed675735..acd5b889815f 100644
> --- a/arch/powerpc/kernel/trace/ftrace.c
> +++ b/arch/powerpc/kernel/trace/ftrace.c
> @@ -848,7 +848,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);
>   
> @@ -856,7 +856,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/kernel/uprobes.c b/arch/powerpc/kernel/uprobes.c
> index 31c870287f2b..6893d40a48c5 100644
> --- a/arch/powerpc/kernel/uprobes.c
> +++ b/arch/powerpc/kernel/uprobes.c
> @@ -174,7 +174,7 @@ bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
>   	 * emulate_step() returns 1 if the insn was successfully emulated.
>   	 * For all other cases, we need to single-step in hardware.
>   	 */
> -	ret = emulate_step(regs, auprobe->insn);
> +	ret = emulate_step(regs, ppc_inst_read(&auprobe->insn));
>   	if (ret > 0)
>   		return true;
>   
> diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
> index 1dff9d9d6645..435fc8e9f45d 100644
> --- a/arch/powerpc/lib/code-patching.c
> +++ b/arch/powerpc/lib/code-patching.c
> @@ -348,9 +348,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;
> @@ -358,7 +358,8 @@ 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 +369,14 @@ 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 +600,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 +611,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 +657,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 +669,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 fb6e8e8abf4e..c0d3ed4efb7e 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);
> @@ -403,7 +403,7 @@ static void do_final_fixups(void)
>   	length = (__end_interrupts - _stext) / sizeof(struct ppc_inst);
>   
>   	while (length--) {
> -		raw_patch_instruction(dest, *src);
> +		raw_patch_instruction(dest, ppc_inst_read(src));
>   		src++;
>   		dest++;
>   	}
> diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
> index e0132d6d24d0..68e0b05d9226 100644
> --- a/arch/powerpc/xmon/xmon.c
> +++ b/arch/powerpc/xmon/xmon.c
> @@ -702,13 +702,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");
>   			}
>   		}
>   	}
> @@ -949,7 +949,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] 81+ messages in thread

* Re: [PATCH v8 08/30] powerpc: Use a function for getting the instruction op code
  2020-05-16 11:08     ` Michael Ellerman
@ 2020-05-17  7:41       ` Jordan Niethe
  0 siblings, 0 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-17  7:41 UTC (permalink / raw)
  To: Michael Ellerman
  Cc: Christophe Leroy, Alistair Popple, Nicholas Piggin,
	Balamuruhan S, naveen.n.rao, linuxppc-dev, Daniel Axtens

On Sat, May 16, 2020 at 9:08 PM Michael Ellerman <mpe@ellerman.id.au> wrote:
>
> Jordan Niethe <jniethe5@gmail.com> writes:
> > mpe, as suggested by Christophe could you please add this.
>
> I did that and ...
>
> > diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h
> > --- a/arch/powerpc/include/asm/inst.h
> > +++ b/arch/powerpc/include/asm/inst.h
> > @@ -2,6 +2,8 @@
> >  #ifndef _ASM_INST_H
> >  #define _ASM_INST_H
> >
> > +#include <asm/disassemble.h>
>
> .. this eventually breaks the build in some driver, because get_ra() is
> redefined.
>
> So I've backed out this change for now.
Thanks, that is fine with me.
>
> If we want to use the macros in disassemble.h we'll need to namespace
> them better, eg. make them ppc_get_ra() and so on.
>
> cheers
>
> >  /*
> >   * Instruction data type for POWER
> >   */
> > @@ -15,7 +17,7 @@ static inline u32 ppc_inst_val(u32 x)
> >
> >  static inline int ppc_inst_primary_opcode(u32 x)
> >  {
> > -    return ppc_inst_val(x) >> 26;
> > +    return get_op(ppc_inst_val(x));
> >  }
> >
> >  #endif /* _ASM_INST_H */
> > --
> > 2.17.1

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 12/30] powerpc: Use a function for reading instructions
  2020-05-16 18:39   ` Christophe Leroy
@ 2020-05-17 10:44     ` Jordan Niethe
  2020-05-19  4:05       ` Michael Ellerman
  0 siblings, 1 reply; 81+ messages in thread
From: Jordan Niethe @ 2020-05-17 10:44 UTC (permalink / raw)
  To: Christophe Leroy
  Cc: Christophe Leroy, Alistair Popple, Nicholas Piggin,
	Balamuruhan S, naveen.n.rao, linuxppc-dev, Daniel Axtens

On Sun, May 17, 2020 at 4:39 AM Christophe Leroy
<christophe.leroy@csgroup.eu> wrote:
>
>
>
> Le 06/05/2020 à 05:40, Jordan Niethe a écrit :
> > 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.
>
>
> Shouldn't this function be used in mmu_patch_addis() in mm/nohash/8xx.c ?
>
> Christophe
Yes, that would be a good idea. mpe here is a fix, along with one I'll
post for [PATCH v8 11/30] powerpc: Use a datatype for instructions.

diff --git a/arch/powerpc/mm/nohash/8xx.c b/arch/powerpc/mm/nohash/8xx.c
--- a/arch/powerpc/mm/nohash/8xx.c
+++ b/arch/powerpc/mm/nohash/8xx.c
@@ -98,7 +98,7 @@ static void mmu_patch_cmp_limit(s32 *site, unsigned
long mapped)

 static void mmu_patch_addis(s32 *site, long simm)
 {
-    struct ppc_inst instr = *(struct ppc_inst *)patch_site_addr(site);
+    struct ppc_inst instr = ppc_inst_read((struct ppc_inst
*)patch_site_addr(site));
     unsigned int val = ppc_inst_val(instr);

     val &= 0xffff0000;
-- 
>
> >
> > Reviewed-by: Alistair Popple <alistair@popple.id.au>
> > 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
> > v6: - feature-fixups.c: do_final_fixups(): Use here
> >      - arch_prepare_kprobe(): patch_instruction(): no longer part of this
> >        patch
> >      - Move probe_kernel_read_inst() out of this patch
> >      - Use in uprobes
> > v8: style
> > ---
> >   arch/powerpc/include/asm/inst.h    |  5 +++++
> >   arch/powerpc/kernel/kprobes.c      |  6 +++---
> >   arch/powerpc/kernel/mce_power.c    |  2 +-
> >   arch/powerpc/kernel/optprobes.c    |  4 ++--
> >   arch/powerpc/kernel/trace/ftrace.c |  4 ++--
> >   arch/powerpc/kernel/uprobes.c      |  2 +-
> >   arch/powerpc/lib/code-patching.c   | 26 ++++++++++++++------------
> >   arch/powerpc/lib/feature-fixups.c  |  4 ++--
> >   arch/powerpc/xmon/xmon.c           |  6 +++---
> >   9 files changed, 33 insertions(+), 26 deletions(-)
> >
> > diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h
> > index 19d8bb7a1c2b..552e953bf04f 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 ppc_inst_val(x) == ppc_inst_val(y);
> > diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
> > index a08ae5803622..f64312dca84f 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");
> > @@ -127,7 +127,7 @@ 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;
> > +             p->opcode = ppc_inst_val(insn);
> >               flush_icache_range((unsigned long)p->ainsn.insn,
> >                       (unsigned long)p->ainsn.insn + sizeof(kprobe_opcode_t));
> >       }
> > @@ -217,7 +217,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 cd23218c60bb..45c51ba0071b 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 5a71fef71c22..52c1ab3f85aa 100644
> > --- a/arch/powerpc/kernel/optprobes.c
> > +++ b/arch/powerpc/kernel/optprobes.c
> > @@ -100,9 +100,9 @@ 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) &&
> > +     if (!is_conditional_branch(ppc_inst_read((struct ppc_inst *)p->ainsn.insn)) &&
> >           analyse_instr(&op, &regs,
> > -                       *(struct ppc_inst *)p->ainsn.insn) == 1) {
> > +                       ppc_inst_read((struct ppc_inst *)p->ainsn.insn)) == 1) {
> >               emulate_update_regs(&regs, &op);
> >               nip = regs.nip;
> >       }
> > diff --git a/arch/powerpc/kernel/trace/ftrace.c b/arch/powerpc/kernel/trace/ftrace.c
> > index 3117ed675735..acd5b889815f 100644
> > --- a/arch/powerpc/kernel/trace/ftrace.c
> > +++ b/arch/powerpc/kernel/trace/ftrace.c
> > @@ -848,7 +848,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);
> >
> > @@ -856,7 +856,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/kernel/uprobes.c b/arch/powerpc/kernel/uprobes.c
> > index 31c870287f2b..6893d40a48c5 100644
> > --- a/arch/powerpc/kernel/uprobes.c
> > +++ b/arch/powerpc/kernel/uprobes.c
> > @@ -174,7 +174,7 @@ bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
> >        * emulate_step() returns 1 if the insn was successfully emulated.
> >        * For all other cases, we need to single-step in hardware.
> >        */
> > -     ret = emulate_step(regs, auprobe->insn);
> > +     ret = emulate_step(regs, ppc_inst_read(&auprobe->insn));
> >       if (ret > 0)
> >               return true;
> >
> > diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
> > index 1dff9d9d6645..435fc8e9f45d 100644
> > --- a/arch/powerpc/lib/code-patching.c
> > +++ b/arch/powerpc/lib/code-patching.c
> > @@ -348,9 +348,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;
> > @@ -358,7 +358,8 @@ 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 +369,14 @@ 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 +600,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 +611,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 +657,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 +669,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 fb6e8e8abf4e..c0d3ed4efb7e 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);
> > @@ -403,7 +403,7 @@ static void do_final_fixups(void)
> >       length = (__end_interrupts - _stext) / sizeof(struct ppc_inst);
> >
> >       while (length--) {
> > -             raw_patch_instruction(dest, *src);
> > +             raw_patch_instruction(dest, ppc_inst_read(src));
> >               src++;
> >               dest++;
> >       }
> > diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
> > index e0132d6d24d0..68e0b05d9226 100644
> > --- a/arch/powerpc/xmon/xmon.c
> > +++ b/arch/powerpc/xmon/xmon.c
> > @@ -702,13 +702,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");
> >                       }
> >               }
> >       }
> > @@ -949,7 +949,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] 81+ messages in thread

* Re: [PATCH v8 11/30] powerpc: Use a datatype for instructions
  2020-05-06  3:40 ` [PATCH v8 11/30] powerpc: Use a datatype for instructions Jordan Niethe
                     ` (2 preceding siblings ...)
  2020-05-08  9:23   ` kbuild test robot
@ 2020-05-17 10:48   ` Jordan Niethe
  3 siblings, 0 replies; 81+ messages in thread
From: Jordan Niethe @ 2020-05-17 10:48 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Christophe Leroy, Alistair Popple, Nicholas Piggin,
	Balamuruhan S, naveen.n.rao, Daniel Axtens

mpe, this is to go with the fixup I posted for mmu_patch_addis() in
[PATCH v8 12/30] powerpc: Use a function for reading instructions.
Thanks to Christophe pointing it out.

diff --git a/arch/powerpc/mm/nohash/8xx.c b/arch/powerpc/mm/nohash/8xx.c
--- a/arch/powerpc/mm/nohash/8xx.c
+++ b/arch/powerpc/mm/nohash/8xx.c
@@ -98,11 +98,12 @@ static void mmu_patch_cmp_limit(s32 *site,
unsigned long mapped)

 static void mmu_patch_addis(s32 *site, long simm)
 {
-    unsigned int instr = *(unsigned int *)patch_site_addr(site);
+    struct ppc_inst instr = *(struct ppc_inst *)patch_site_addr(site);
+    unsigned int val = ppc_inst_val(instr);

-    instr &= 0xffff0000;
-    instr |= ((unsigned long)simm) >> 16;
-    patch_instruction_site(site, ppc_inst(instr));
+    val &= 0xffff0000;
+    val |= ((unsigned long)simm) >> 16;
+    patch_instruction_site(site, ppc_inst(val));
 }

 static void mmu_mapin_ram_chunk(unsigned long offset, unsigned long
top, pgprot_t prot)
--

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 12/30] powerpc: Use a function for reading instructions
  2020-05-17 10:44     ` Jordan Niethe
@ 2020-05-19  4:05       ` Michael Ellerman
  2020-05-19  5:03         ` Christophe Leroy
  0 siblings, 1 reply; 81+ messages in thread
From: Michael Ellerman @ 2020-05-19  4:05 UTC (permalink / raw)
  To: Jordan Niethe, Christophe Leroy
  Cc: Christophe Leroy, Alistair Popple, Nicholas Piggin,
	Balamuruhan S, naveen.n.rao, linuxppc-dev, Daniel Axtens

Jordan Niethe <jniethe5@gmail.com> writes:
> On Sun, May 17, 2020 at 4:39 AM Christophe Leroy
> <christophe.leroy@csgroup.eu> wrote:
>>
>> Le 06/05/2020 à 05:40, Jordan Niethe a écrit :
>> > 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.
>>
>>
>> Shouldn't this function be used in mmu_patch_addis() in mm/nohash/8xx.c ?
>>
>> Christophe

> Yes, that would be a good idea.

> mpe here is a fix, along with one I'll
> post for [PATCH v8 11/30] powerpc: Use a datatype for instructions.

I didn't fold this in because I'd prefer one of you send me a patch on
top of the series that converts that code to use the new type.

That way it can be tested separately from this big series.

cheers

> diff --git a/arch/powerpc/mm/nohash/8xx.c b/arch/powerpc/mm/nohash/8xx.c
> --- a/arch/powerpc/mm/nohash/8xx.c
> +++ b/arch/powerpc/mm/nohash/8xx.c
> @@ -98,7 +98,7 @@ static void mmu_patch_cmp_limit(s32 *site, unsigned
> long mapped)
>
>  static void mmu_patch_addis(s32 *site, long simm)
>  {
> -    struct ppc_inst instr = *(struct ppc_inst *)patch_site_addr(site);
> +    struct ppc_inst instr = ppc_inst_read((struct ppc_inst
> *)patch_site_addr(site));
>      unsigned int val = ppc_inst_val(instr);
>
>      val &= 0xffff0000;
> -- 
>>
>> >
>> > Reviewed-by: Alistair Popple <alistair@popple.id.au>
>> > 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
>> > v6: - feature-fixups.c: do_final_fixups(): Use here
>> >      - arch_prepare_kprobe(): patch_instruction(): no longer part of this
>> >        patch
>> >      - Move probe_kernel_read_inst() out of this patch
>> >      - Use in uprobes
>> > v8: style
>> > ---
>> >   arch/powerpc/include/asm/inst.h    |  5 +++++
>> >   arch/powerpc/kernel/kprobes.c      |  6 +++---
>> >   arch/powerpc/kernel/mce_power.c    |  2 +-
>> >   arch/powerpc/kernel/optprobes.c    |  4 ++--
>> >   arch/powerpc/kernel/trace/ftrace.c |  4 ++--
>> >   arch/powerpc/kernel/uprobes.c      |  2 +-
>> >   arch/powerpc/lib/code-patching.c   | 26 ++++++++++++++------------
>> >   arch/powerpc/lib/feature-fixups.c  |  4 ++--
>> >   arch/powerpc/xmon/xmon.c           |  6 +++---
>> >   9 files changed, 33 insertions(+), 26 deletions(-)
>> >
>> > diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h
>> > index 19d8bb7a1c2b..552e953bf04f 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 ppc_inst_val(x) == ppc_inst_val(y);
>> > diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
>> > index a08ae5803622..f64312dca84f 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");
>> > @@ -127,7 +127,7 @@ 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;
>> > +             p->opcode = ppc_inst_val(insn);
>> >               flush_icache_range((unsigned long)p->ainsn.insn,
>> >                       (unsigned long)p->ainsn.insn + sizeof(kprobe_opcode_t));
>> >       }
>> > @@ -217,7 +217,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 cd23218c60bb..45c51ba0071b 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 5a71fef71c22..52c1ab3f85aa 100644
>> > --- a/arch/powerpc/kernel/optprobes.c
>> > +++ b/arch/powerpc/kernel/optprobes.c
>> > @@ -100,9 +100,9 @@ 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) &&
>> > +     if (!is_conditional_branch(ppc_inst_read((struct ppc_inst *)p->ainsn.insn)) &&
>> >           analyse_instr(&op, &regs,
>> > -                       *(struct ppc_inst *)p->ainsn.insn) == 1) {
>> > +                       ppc_inst_read((struct ppc_inst *)p->ainsn.insn)) == 1) {
>> >               emulate_update_regs(&regs, &op);
>> >               nip = regs.nip;
>> >       }
>> > diff --git a/arch/powerpc/kernel/trace/ftrace.c b/arch/powerpc/kernel/trace/ftrace.c
>> > index 3117ed675735..acd5b889815f 100644
>> > --- a/arch/powerpc/kernel/trace/ftrace.c
>> > +++ b/arch/powerpc/kernel/trace/ftrace.c
>> > @@ -848,7 +848,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);
>> >
>> > @@ -856,7 +856,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/kernel/uprobes.c b/arch/powerpc/kernel/uprobes.c
>> > index 31c870287f2b..6893d40a48c5 100644
>> > --- a/arch/powerpc/kernel/uprobes.c
>> > +++ b/arch/powerpc/kernel/uprobes.c
>> > @@ -174,7 +174,7 @@ bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
>> >        * emulate_step() returns 1 if the insn was successfully emulated.
>> >        * For all other cases, we need to single-step in hardware.
>> >        */
>> > -     ret = emulate_step(regs, auprobe->insn);
>> > +     ret = emulate_step(regs, ppc_inst_read(&auprobe->insn));
>> >       if (ret > 0)
>> >               return true;
>> >
>> > diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
>> > index 1dff9d9d6645..435fc8e9f45d 100644
>> > --- a/arch/powerpc/lib/code-patching.c
>> > +++ b/arch/powerpc/lib/code-patching.c
>> > @@ -348,9 +348,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;
>> > @@ -358,7 +358,8 @@ 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 +369,14 @@ 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 +600,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 +611,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 +657,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 +669,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 fb6e8e8abf4e..c0d3ed4efb7e 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);
>> > @@ -403,7 +403,7 @@ static void do_final_fixups(void)
>> >       length = (__end_interrupts - _stext) / sizeof(struct ppc_inst);
>> >
>> >       while (length--) {
>> > -             raw_patch_instruction(dest, *src);
>> > +             raw_patch_instruction(dest, ppc_inst_read(src));
>> >               src++;
>> >               dest++;
>> >       }
>> > diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
>> > index e0132d6d24d0..68e0b05d9226 100644
>> > --- a/arch/powerpc/xmon/xmon.c
>> > +++ b/arch/powerpc/xmon/xmon.c
>> > @@ -702,13 +702,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");
>> >                       }
>> >               }
>> >       }
>> > @@ -949,7 +949,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] 81+ messages in thread

* Re: [PATCH v8 12/30] powerpc: Use a function for reading instructions
  2020-05-19  4:05       ` Michael Ellerman
@ 2020-05-19  5:03         ` Christophe Leroy
  2020-05-20  4:16           ` Michael Ellerman
  0 siblings, 1 reply; 81+ messages in thread
From: Christophe Leroy @ 2020-05-19  5:03 UTC (permalink / raw)
  To: Michael Ellerman, Jordan Niethe
  Cc: Christophe Leroy, Alistair Popple, Nicholas Piggin,
	Balamuruhan S, naveen.n.rao, linuxppc-dev, Daniel Axtens



Le 19/05/2020 à 06:05, Michael Ellerman a écrit :
> Jordan Niethe <jniethe5@gmail.com> writes:
>> On Sun, May 17, 2020 at 4:39 AM Christophe Leroy
>> <christophe.leroy@csgroup.eu> wrote:
>>>
>>> Le 06/05/2020 à 05:40, Jordan Niethe a écrit :
>>>> 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.
>>>
>>>
>>> Shouldn't this function be used in mmu_patch_addis() in mm/nohash/8xx.c ?
>>>
>>> Christophe
> 
>> Yes, that would be a good idea.
> 
>> mpe here is a fix, along with one I'll
>> post for [PATCH v8 11/30] powerpc: Use a datatype for instructions.
> 
> I didn't fold this in because I'd prefer one of you send me a patch on
> top of the series that converts that code to use the new type.
> 
> That way it can be tested separately from this big series.
> 

All this code is going away with the series implementing the use of 
hugepages for kernel mappings on 8xx 
(https://patchwork.ozlabs.org/project/linuxppc-dev/list/?series=176094) 
that I hope will go in 5.8, so there is no point in sending a patch to 
change that I guess.

Is there anything special I need to do to secure the merging of that 
series in 5.8 ?

Christophe

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 12/30] powerpc: Use a function for reading instructions
  2020-05-19  5:03         ` Christophe Leroy
@ 2020-05-20  4:16           ` Michael Ellerman
  0 siblings, 0 replies; 81+ messages in thread
From: Michael Ellerman @ 2020-05-20  4:16 UTC (permalink / raw)
  To: Christophe Leroy, Jordan Niethe
  Cc: Christophe Leroy, Alistair Popple, Nicholas Piggin,
	Balamuruhan S, naveen.n.rao, linuxppc-dev, Daniel Axtens

Christophe Leroy <christophe.leroy@csgroup.eu> writes:
> Le 19/05/2020 à 06:05, Michael Ellerman a écrit :
>> Jordan Niethe <jniethe5@gmail.com> writes:
>>> On Sun, May 17, 2020 at 4:39 AM Christophe Leroy
>>> <christophe.leroy@csgroup.eu> wrote:
>>>>
>>>> Le 06/05/2020 à 05:40, Jordan Niethe a écrit :
>>>>> 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.
>>>>
>>>> Shouldn't this function be used in mmu_patch_addis() in mm/nohash/8xx.c ?
>> 
>>> Yes, that would be a good idea.
>> 
>>> mpe here is a fix, along with one I'll
>>> post for [PATCH v8 11/30] powerpc: Use a datatype for instructions.
>> 
>> I didn't fold this in because I'd prefer one of you send me a patch on
>> top of the series that converts that code to use the new type.
>> 
>> That way it can be tested separately from this big series.
>> 
>
> All this code is going away with the series implementing the use of 
> hugepages for kernel mappings on 8xx 
> (https://patchwork.ozlabs.org/project/linuxppc-dev/list/?series=176094) 
> that I hope will go in 5.8, so there is no point in sending a patch to 
> change that I guess.

OK.

> Is there anything special I need to do to secure the merging of that 
> series in 5.8 ?

Review it for me :P

As long as it is only touching 8xx I'm happy to defer to you. So I guess
any parts that affect other platforms will be where I need to spend more
effort reviewing it.

I'll try and get it into my test branch today and get some testing done
on it.

cheers

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 00/30] Initial Prefixed Instruction support
  2020-05-06  3:40 [PATCH v8 00/30] Initial Prefixed Instruction support Jordan Niethe
                   ` (30 preceding siblings ...)
  2020-05-14  5:31 ` [PATCH v8 00/30] Initial Prefixed Instruction support Christophe Leroy
@ 2020-05-20 10:59 ` Michael Ellerman
  31 siblings, 0 replies; 81+ messages in thread
From: Michael Ellerman @ 2020-05-20 10:59 UTC (permalink / raw)
  To: linuxppc-dev, Jordan Niethe; +Cc: alistair, naveen.n.rao, dja, npiggin, bala24

On Wed, 6 May 2020 13:40:20 +1000, 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.
> 
> [...]

Applied to powerpc/next.

[01/30] powerpc/xmon: Remove store_inst() for patch_instruction()
        https://git.kernel.org/powerpc/c/802268fd82676ffce432776f60b93a0b15e58e0c
[02/30] powerpc/xmon: Move breakpoint instructions to own array
        https://git.kernel.org/powerpc/c/51c9ba11f17f25ace1ea6bbfd4586c59105432de
[03/30] powerpc/xmon: Move breakpoints to text section
        https://git.kernel.org/powerpc/c/4eff2b4f32a309e2171bfe53db3e93b5614f77cb
[04/30] powerpc/xmon: Use bitwise calculations in_breakpoint_table()
        https://git.kernel.org/powerpc/c/5a7fdcab54ef17c395fc47e73c828a1432e51683
[05/30] powerpc: Change calling convention for create_branch() et. al.
        https://git.kernel.org/powerpc/c/7c95d8893fb55869882c9f68f4c94840dc43f18f
[06/30] powerpc: Use a macro for creating instructions from u32s
        https://git.kernel.org/powerpc/c/753462512868674a788ecc77bb96752efb818785
[07/30] powerpc: Use an accessor for instructions
        https://git.kernel.org/powerpc/c/777e26f0edf8dab58b8dd474d35d83bde0ac6d76
[08/30] powerpc: Use a function for getting the instruction op code
        https://git.kernel.org/powerpc/c/8094892d1aff14269d3b7bfcd8b941217eecd81f
[09/30] powerpc: Use a function for byte swapping instructions
        https://git.kernel.org/powerpc/c/aabd2233b6aefeee6d7a2f667076d8346be1d30a
[10/30] powerpc: Introduce functions for instruction equality
        https://git.kernel.org/powerpc/c/217862d9b98bf08958d57fd7b31b9de0f1a9477d
[11/30] powerpc: Use a datatype for instructions
        https://git.kernel.org/powerpc/c/94afd069d937d84fb4f696eb9a78db4084e43d21
[12/30] powerpc: Use a function for reading instructions
        https://git.kernel.org/powerpc/c/f8faaffaa7d99028e457ef2d1dcb43a98f736938
[13/30] powerpc: Add a probe_user_read_inst() function
        https://git.kernel.org/powerpc/c/7ba68b2172c19031fdc2a2caf37328edd146e299
[14/30] powerpc: Add a probe_kernel_read_inst() function
        https://git.kernel.org/powerpc/c/95b980a00d1220ca67550a933166704db8bc5c14
[15/30] powerpc/kprobes: Use patch_instruction()
        https://git.kernel.org/powerpc/c/a8646f43ba5046e7f5c4396125d5136bfcb17b49
[16/30] powerpc: Define and use get_user_instr() et. al.
        https://git.kernel.org/powerpc/c/5249385ad7f0ac178433f0ae9cc5b64612c8ff77
[17/30] powerpc: Introduce a function for reporting instruction length
        https://git.kernel.org/powerpc/c/622cf6f436a12338bbcfbb3474629755547fd112
[18/30] powerpc/xmon: Use a function for reading instructions
        https://git.kernel.org/powerpc/c/6c7a4f0a9f66fc7fdc6e208559e5d562f53e0991
[19/30] powerpc/xmon: Move insertion of breakpoint for xol'ing
        https://git.kernel.org/powerpc/c/7fccfcfba04f9cb46438f368755d368f6c57f3a0
[20/30] powerpc: Make test_translate_branch() independent of instruction length
        https://git.kernel.org/powerpc/c/0b582db5490a1f250ef63337dd46d5c7599dae80
[21/30] powerpc: Enable Prefixed Instructions
        https://git.kernel.org/powerpc/c/2aa6195e43b3740258ead93aee42ac719dd4c4b0
[22/30] powerpc: Define new SRR1 bits for a ISA v3.1
        https://git.kernel.org/powerpc/c/b691505ef9232a6e82f1c160911afcb4cb20487b
[23/30] powerpc: Add prefixed instructions to instruction data type
        https://git.kernel.org/powerpc/c/650b55b707fdfa764e9f2b81314d3eb4216fb962
[24/30] powerpc: Test prefixed code patching
        https://git.kernel.org/powerpc/c/f77f8ff7f13e6411c2e0ba25bb7e012a5ae6c927
[25/30] powerpc: Test prefixed instructions in feature fixups
        https://git.kernel.org/powerpc/c/785b79d1e02873c2088ee1301154c66dace66ce5
[26/30] powerpc/xmon: Don't allow breakpoints on suffixes
        https://git.kernel.org/powerpc/c/c9c831aebd8663d0129bbcee4d76be889f0627fe
[27/30] powerpc/kprobes: Don't allow breakpoints on suffixes
        https://git.kernel.org/powerpc/c/b4657f7650babc9bfb41ce875abe41b18604a105
[28/30] powerpc: Support prefixed instructions in alignment handler
        https://git.kernel.org/powerpc/c/9409d2f9dad2f0679d67dc24d8116dd3e837b035
[29/30] powerpc sstep: Add support for prefixed load/stores
        https://git.kernel.org/powerpc/c/50b80a12e4ccff46d53b93754d817acd98bc9ae0
[30/30] powerpc sstep: Add support for prefixed fixed-point arithmetic
        https://git.kernel.org/powerpc/c/3920742b92f5ea19a220edb947b6f33c99f501da

cheers

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 22.5/30] powerpc/optprobes: Add register argument to patch_imm64_load_insns()
  2020-05-16 11:54   ` [PATCH v8 22.5/30] powerpc/optprobes: Add register argument to patch_imm64_load_insns() Michael Ellerman
@ 2020-06-09  5:51     ` Michael Ellerman
  0 siblings, 0 replies; 81+ messages in thread
From: Michael Ellerman @ 2020-06-09  5:51 UTC (permalink / raw)
  To: Michael Ellerman, linuxppc-dev; +Cc: christophe.leroy, jniethe5

On Sat, 2020-05-16 at 11:54:49 UTC, Michael Ellerman wrote:
> From: Jordan Niethe <jniethe5@gmail.com>
> 
> Currently patch_imm32_load_insns() is used to load an instruction to
> r4 to be emulated by emulate_step(). For prefixed instructions we
> would like to be able to load a 64bit immediate to r4. To prepare for
> this make patch_imm64_load_insns() take an argument that decides which
> register to load an immediate to - rather than hardcoding r3.
> 
> Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>

Applied to powerpc next.

https://git.kernel.org/powerpc/c/7a8818e0df5c6b53c89c7c928498668a2bbb3de0

cheers

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 27/30] powerpc/kprobes: Don't allow breakpoints on suffixes
  2020-05-06  3:40 ` [PATCH v8 27/30] powerpc/kprobes: " Jordan Niethe
@ 2021-05-18 18:43   ` Christophe Leroy
  2021-05-18 19:52     ` Gabriel Paubert
  2021-05-19  8:11     ` Naveen N. Rao
  0 siblings, 2 replies; 81+ messages in thread
From: Christophe Leroy @ 2021-05-18 18:43 UTC (permalink / raw)
  To: Jordan Niethe, linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, dja



Le 06/05/2020 à 05:40, Jordan Niethe a écrit :
> Do not allow inserting breakpoints on the suffix of a prefix instruction
> in kprobes.
> 
> Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> ---
> v8: Add this back from v3
> ---
>   arch/powerpc/kernel/kprobes.c | 13 +++++++++++++
>   1 file changed, 13 insertions(+)
> 
> diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
> index 33d54b091c70..227510df8c55 100644
> --- a/arch/powerpc/kernel/kprobes.c
> +++ b/arch/powerpc/kernel/kprobes.c
> @@ -106,7 +106,9 @@ kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset)
>   int arch_prepare_kprobe(struct kprobe *p)
>   {
>   	int ret = 0;
> +	struct kprobe *prev;
>   	struct ppc_inst insn = ppc_inst_read((struct ppc_inst *)p->addr);
> +	struct ppc_inst prefix = ppc_inst_read((struct ppc_inst *)(p->addr - 1));

What if p->addr is the first word of a page and the previous page is not mapped ?

>   
>   	if ((unsigned long)p->addr & 0x03) {
>   		printk("Attempt to register kprobe at an unaligned address\n");
> @@ -114,6 +116,17 @@ int arch_prepare_kprobe(struct kprobe *p)
>   	} else if (IS_MTMSRD(insn) || IS_RFID(insn) || IS_RFI(insn)) {
>   		printk("Cannot register a kprobe on rfi/rfid or mtmsr[d]\n");
>   		ret = -EINVAL;
> +	} else if (ppc_inst_prefixed(prefix)) {

If p->addr - 2 contains a valid prefixed instruction, then p->addr - 1 contains the suffix of that 
prefixed instruction. Are we sure a suffix can never ever be misinterpreted as the prefix of a 
prefixed instruction ?


> +		printk("Cannot register a kprobe on the second word of prefixed instruction\n");
> +		ret = -EINVAL;
> +	}
> +	preempt_disable();
> +	prev = get_kprobe(p->addr - 1);
> +	preempt_enable_no_resched();
> +	if (prev &&
> +	    ppc_inst_prefixed(ppc_inst_read((struct ppc_inst *)prev->ainsn.insn))) {
> +		printk("Cannot register a kprobe on the second word of prefixed instruction\n");
> +		ret = -EINVAL;
>   	}
>   
>   	/* insn must be on a special executable page on ppc64.  This is
> 

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 27/30] powerpc/kprobes: Don't allow breakpoints on suffixes
  2021-05-18 18:43   ` Christophe Leroy
@ 2021-05-18 19:52     ` Gabriel Paubert
  2021-05-19  8:11     ` Naveen N. Rao
  1 sibling, 0 replies; 81+ messages in thread
From: Gabriel Paubert @ 2021-05-18 19:52 UTC (permalink / raw)
  To: Christophe Leroy
  Cc: Jordan Niethe, npiggin, bala24, alistair, naveen.n.rao,
	linuxppc-dev, dja

On Tue, May 18, 2021 at 08:43:39PM +0200, Christophe Leroy wrote:
> 
> 
> Le 06/05/2020 à 05:40, Jordan Niethe a écrit :
> > Do not allow inserting breakpoints on the suffix of a prefix instruction
> > in kprobes.
> > 
> > Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> > ---
> > v8: Add this back from v3
> > ---
> >   arch/powerpc/kernel/kprobes.c | 13 +++++++++++++
> >   1 file changed, 13 insertions(+)
> > 
> > diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
> > index 33d54b091c70..227510df8c55 100644
> > --- a/arch/powerpc/kernel/kprobes.c
> > +++ b/arch/powerpc/kernel/kprobes.c
> > @@ -106,7 +106,9 @@ kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset)
> >   int arch_prepare_kprobe(struct kprobe *p)
> >   {
> >   	int ret = 0;
> > +	struct kprobe *prev;
> >   	struct ppc_inst insn = ppc_inst_read((struct ppc_inst *)p->addr);
> > +	struct ppc_inst prefix = ppc_inst_read((struct ppc_inst *)(p->addr - 1));
> 
> What if p->addr is the first word of a page and the previous page is not mapped ?

IIRC prefixed instructions can't straddle 64 byte boundaries (or was it
128 bytes?), much less page boundaries.

> 
> >   	if ((unsigned long)p->addr & 0x03) {
> >   		printk("Attempt to register kprobe at an unaligned address\n");
> > @@ -114,6 +116,17 @@ int arch_prepare_kprobe(struct kprobe *p)
> >   	} else if (IS_MTMSRD(insn) || IS_RFID(insn) || IS_RFI(insn)) {
> >   		printk("Cannot register a kprobe on rfi/rfid or mtmsr[d]\n");
> >   		ret = -EINVAL;
> > +	} else if (ppc_inst_prefixed(prefix)) {
> 
> If p->addr - 2 contains a valid prefixed instruction, then p->addr - 1
> contains the suffix of that prefixed instruction. Are we sure a suffix can
> never ever be misinterpreted as the prefix of a prefixed instruction ?
> 

Prefixes are easy to decode, the 6 MSB are 0b000001 (from memory).

After some digging on the 'net: "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."

IOW, detecting prefixes is trivial. It's not x86...

	Gabriel

> 
> > +		printk("Cannot register a kprobe on the second word of prefixed instruction\n");
> > +		ret = -EINVAL;
> > +	}
> > +	preempt_disable();
> > +	prev = get_kprobe(p->addr - 1);
> > +	preempt_enable_no_resched();
> > +	if (prev &&
> > +	    ppc_inst_prefixed(ppc_inst_read((struct ppc_inst *)prev->ainsn.insn))) {
> > +		printk("Cannot register a kprobe on the second word of prefixed instruction\n");
> > +		ret = -EINVAL;
> >   	}
> >   	/* insn must be on a special executable page on ppc64.  This is
> > 



^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 27/30] powerpc/kprobes: Don't allow breakpoints on suffixes
  2021-05-18 18:43   ` Christophe Leroy
  2021-05-18 19:52     ` Gabriel Paubert
@ 2021-05-19  8:11     ` Naveen N. Rao
  2021-05-20  3:45       ` Jordan Niethe
  1 sibling, 1 reply; 81+ messages in thread
From: Naveen N. Rao @ 2021-05-19  8:11 UTC (permalink / raw)
  To: Christophe Leroy, Jordan Niethe, linuxppc-dev
  Cc: alistair, npiggin, bala24, dja

Christophe Leroy wrote:
> 
> 
> Le 06/05/2020 à 05:40, Jordan Niethe a écrit :
>> Do not allow inserting breakpoints on the suffix of a prefix instruction
>> in kprobes.
>> 
>> Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
>> ---
>> v8: Add this back from v3
>> ---
>>   arch/powerpc/kernel/kprobes.c | 13 +++++++++++++
>>   1 file changed, 13 insertions(+)
>> 
>> diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
>> index 33d54b091c70..227510df8c55 100644
>> --- a/arch/powerpc/kernel/kprobes.c
>> +++ b/arch/powerpc/kernel/kprobes.c
>> @@ -106,7 +106,9 @@ kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset)
>>   int arch_prepare_kprobe(struct kprobe *p)
>>   {
>>   	int ret = 0;
>> +	struct kprobe *prev;
>>   	struct ppc_inst insn = ppc_inst_read((struct ppc_inst *)p->addr);
>> +	struct ppc_inst prefix = ppc_inst_read((struct ppc_inst *)(p->addr - 1));
> 
> What if p->addr is the first word of a page and the previous page is 
> not mapped ?

Good catch!
I think we can just skip validation if the instruction is at the 
beginning of a page. I have a few cleanups in this area - I will post a 
patchset soon.

> 
>>   
>>   	if ((unsigned long)p->addr & 0x03) {
>>   		printk("Attempt to register kprobe at an unaligned address\n");
>> @@ -114,6 +116,17 @@ int arch_prepare_kprobe(struct kprobe *p)
>>   	} else if (IS_MTMSRD(insn) || IS_RFID(insn) || IS_RFI(insn)) {
>>   		printk("Cannot register a kprobe on rfi/rfid or mtmsr[d]\n");
>>   		ret = -EINVAL;
>> +	} else if (ppc_inst_prefixed(prefix)) {
> 
> If p->addr - 2 contains a valid prefixed instruction, then p->addr - 1 contains the suffix of that 
> prefixed instruction. Are we sure a suffix can never ever be misinterpreted as the prefix of a 
> prefixed instruction ?

Yes. Per the ISA:
  Bits 0:5 of all prefixes are assigned the primary opcode
  value 0b000001. 0b000001 is not available for use as a
  primary opcode for either word instructions or suffixes
  of prefixed instructions.


- Naveen


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 27/30] powerpc/kprobes: Don't allow breakpoints on suffixes
  2021-05-19  8:11     ` Naveen N. Rao
@ 2021-05-20  3:45       ` Jordan Niethe
  0 siblings, 0 replies; 81+ messages in thread
From: Jordan Niethe @ 2021-05-20  3:45 UTC (permalink / raw)
  To: Naveen N. Rao
  Cc: Alistair Popple, Balamuruhan S, Nicholas Piggin, linuxppc-dev,
	Daniel Axtens

On Wed, May 19, 2021 at 6:11 PM Naveen N. Rao
<naveen.n.rao@linux.vnet.ibm.com> wrote:
>
> Christophe Leroy wrote:
> >
> >
> > Le 06/05/2020 à 05:40, Jordan Niethe a écrit :
> >> Do not allow inserting breakpoints on the suffix of a prefix instruction
> >> in kprobes.
> >>
> >> Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> >> ---
> >> v8: Add this back from v3
> >> ---
> >>   arch/powerpc/kernel/kprobes.c | 13 +++++++++++++
> >>   1 file changed, 13 insertions(+)
> >>
> >> diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
> >> index 33d54b091c70..227510df8c55 100644
> >> --- a/arch/powerpc/kernel/kprobes.c
> >> +++ b/arch/powerpc/kernel/kprobes.c
> >> @@ -106,7 +106,9 @@ kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset)
> >>   int arch_prepare_kprobe(struct kprobe *p)
> >>   {
> >>      int ret = 0;
> >> +    struct kprobe *prev;
> >>      struct ppc_inst insn = ppc_inst_read((struct ppc_inst *)p->addr);
> >> +    struct ppc_inst prefix = ppc_inst_read((struct ppc_inst *)(p->addr - 1));
> >
> > What if p->addr is the first word of a page and the previous page is
> > not mapped ?
>
> Good catch!
> I think we can just skip validation if the instruction is at the
> beginning of a page. I have a few cleanups in this area - I will post a
> patchset soon.
Yeah thanks Christophe for noticing that. And thanks Naveen that
sounds like it should fix it.
>
> >
> >>
> >>      if ((unsigned long)p->addr & 0x03) {
> >>              printk("Attempt to register kprobe at an unaligned address\n");
> >> @@ -114,6 +116,17 @@ int arch_prepare_kprobe(struct kprobe *p)
> >>      } else if (IS_MTMSRD(insn) || IS_RFID(insn) || IS_RFI(insn)) {
> >>              printk("Cannot register a kprobe on rfi/rfid or mtmsr[d]\n");
> >>              ret = -EINVAL;
> >> +    } else if (ppc_inst_prefixed(prefix)) {
> >
> > If p->addr - 2 contains a valid prefixed instruction, then p->addr - 1 contains the suffix of that
> > prefixed instruction. Are we sure a suffix can never ever be misinterpreted as the prefix of a
> > prefixed instruction ?
>
> Yes. Per the ISA:
>   Bits 0:5 of all prefixes are assigned the primary opcode
>   value 0b000001. 0b000001 is not available for use as a
>   primary opcode for either word instructions or suffixes
>   of prefixed instructions.
Yep, a prefix will never be a valid word instruction or suffix.
>
>
> - Naveen
>

^ permalink raw reply	[flat|nested] 81+ messages in thread

end of thread, other threads:[~2021-05-20  3:46 UTC | newest]

Thread overview: 81+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-06  3:40 [PATCH v8 00/30] Initial Prefixed Instruction support Jordan Niethe
2020-05-06  3:40 ` [PATCH v8 01/30] powerpc/xmon: Remove store_inst() for patch_instruction() Jordan Niethe
2020-05-06  3:40 ` [PATCH v8 02/30] powerpc/xmon: Move breakpoint instructions to own array Jordan Niethe
2020-05-06  3:40 ` [PATCH v8 03/30] powerpc/xmon: Move breakpoints to text section Jordan Niethe
2020-05-06  3:40 ` [PATCH v8 04/30] powerpc/xmon: Use bitwise calculations in_breakpoint_table() Jordan Niethe
2020-05-06  3:40 ` [PATCH v8 05/30] powerpc: Change calling convention for create_branch() et. al Jordan Niethe
2020-05-06  3:40 ` [PATCH v8 06/30] powerpc: Use a macro for creating instructions from u32s Jordan Niethe
2020-05-06  3:40 ` [PATCH v8 07/30] powerpc: Use an accessor for instructions Jordan Niethe
2020-05-06  3:40 ` [PATCH v8 08/30] powerpc: Use a function for getting the instruction op code Jordan Niethe
2020-05-15  7:48   ` Jordan Niethe
2020-05-16 11:08     ` Michael Ellerman
2020-05-17  7:41       ` Jordan Niethe
2020-05-06  3:40 ` [PATCH v8 09/30] powerpc: Use a function for byte swapping instructions Jordan Niethe
2020-05-06  3:40 ` [PATCH v8 10/30] powerpc: Introduce functions for instruction equality Jordan Niethe
2020-05-06  3:40 ` [PATCH v8 11/30] powerpc: Use a datatype for instructions Jordan Niethe
2020-05-08  1:51   ` Jordan Niethe
2020-05-08  7:17     ` Christophe Leroy
2020-05-11  1:19       ` Jordan Niethe
2020-05-08  2:15   ` Jordan Niethe
2020-05-08  9:23   ` kbuild test robot
2020-05-17 10:48   ` Jordan Niethe
2020-05-06  3:40 ` [PATCH v8 12/30] powerpc: Use a function for reading instructions Jordan Niethe
2020-05-16 18:39   ` Christophe Leroy
2020-05-17 10:44     ` Jordan Niethe
2020-05-19  4:05       ` Michael Ellerman
2020-05-19  5:03         ` Christophe Leroy
2020-05-20  4:16           ` Michael Ellerman
2020-05-06  3:40 ` [PATCH v8 13/30] powerpc: Add a probe_user_read_inst() function Jordan Niethe
2020-05-13 12:52   ` Michael Ellerman
2020-05-13 23:51     ` Jordan Niethe
2020-05-14  5:46   ` Christophe Leroy
2020-05-15  3:46     ` Jordan Niethe
2020-05-06  3:40 ` [PATCH v8 14/30] powerpc: Add a probe_kernel_read_inst() function Jordan Niethe
2020-05-06  3:40 ` [PATCH v8 15/30] powerpc/kprobes: Use patch_instruction() Jordan Niethe
2020-05-06  3:40 ` [PATCH v8 16/30] powerpc: Define and use __get_user_instr{, inatomic}() Jordan Niethe
2020-05-13 14:18   ` Michael Ellerman
2020-05-13 23:54     ` Jordan Niethe
2020-05-14  1:43       ` Jordan Niethe
2020-05-06  3:40 ` [PATCH v8 17/30] powerpc: Introduce a function for reporting instruction length Jordan Niethe
2020-05-06  3:40 ` [PATCH v8 18/30] powerpc/xmon: Use a function for reading instructions Jordan Niethe
2020-05-06  3:40 ` [PATCH v8 19/30] powerpc/xmon: Move insertion of breakpoint for xol'ing Jordan Niethe
2020-05-06  3:40 ` [PATCH v8 20/30] powerpc: Make test_translate_branch() independent of instruction length Jordan Niethe
2020-05-06  3:40 ` [PATCH v8 21/30] powerpc: Enable Prefixed Instructions Jordan Niethe
2020-05-06  3:40 ` [PATCH v8 22/30] powerpc: Define new SRR1 bits for a future ISA version Jordan Niethe
2020-05-08  2:26   ` Jordan Niethe
2020-05-06  3:40 ` [PATCH v8 23/30] powerpc: Add prefixed instructions to instruction data type Jordan Niethe
2020-05-14  1:40   ` Jordan Niethe
2020-05-14  6:11   ` Christophe Leroy
2020-05-14 12:06     ` Alistair Popple
2020-05-14 12:29       ` Jordan Niethe
2020-05-14 12:57       ` Christophe Leroy
2020-05-14 12:28     ` Jordan Niethe
2020-05-15  1:33     ` Michael Ellerman
2020-05-15  7:52       ` Jordan Niethe
2020-05-16 11:54   ` [PATCH v8 22.5/30] powerpc/optprobes: Add register argument to patch_imm64_load_insns() Michael Ellerman
2020-06-09  5:51     ` Michael Ellerman
2020-05-06  3:40 ` [PATCH v8 24/30] powerpc: Test prefixed code patching Jordan Niethe
2020-05-15  7:54   ` Jordan Niethe
2020-05-06  3:40 ` [PATCH v8 25/30] powerpc: Test prefixed instructions in feature fixups Jordan Niethe
2020-05-15  7:57   ` Jordan Niethe
2020-05-06  3:40 ` [PATCH v8 26/30] powerpc/xmon: Don't allow breakpoints on suffixes Jordan Niethe
2020-05-06  3:40 ` [PATCH v8 27/30] powerpc/kprobes: " Jordan Niethe
2021-05-18 18:43   ` Christophe Leroy
2021-05-18 19:52     ` Gabriel Paubert
2021-05-19  8:11     ` Naveen N. Rao
2021-05-20  3:45       ` Jordan Niethe
2020-05-06  3:40 ` [PATCH v8 28/30] powerpc: Support prefixed instructions in alignment handler Jordan Niethe
2020-05-14  6:14   ` Christophe Leroy
2020-05-14 12:15     ` Alistair Popple
2020-05-14 12:59       ` Christophe Leroy
2020-05-06  3:40 ` [PATCH v8 29/30] powerpc sstep: Add support for prefixed load/stores Jordan Niethe
2020-05-14  6:15   ` Christophe Leroy
2020-05-14 12:19     ` Alistair Popple
2020-05-14 13:00       ` Christophe Leroy
2020-05-15  7:59   ` Jordan Niethe
2020-05-06  3:40 ` [PATCH v8 30/30] powerpc sstep: Add support for prefixed fixed-point arithmetic Jordan Niethe
2020-05-14  6:15   ` Christophe Leroy
2020-05-15  8:02   ` Jordan Niethe
2020-05-14  5:31 ` [PATCH v8 00/30] Initial Prefixed Instruction support Christophe Leroy
2020-05-14 10:33   ` Jordan Niethe
2020-05-20 10:59 ` Michael Ellerman

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.