linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] powerpc: sstep: Emulation test infrastructure
@ 2019-02-20  6:56 Sandipan Das
  2019-02-20  6:56 ` [PATCH 1/3] powerpc: sstep: Add tests for compute type instructions Sandipan Das
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Sandipan Das @ 2019-02-20  6:56 UTC (permalink / raw)
  To: mpe; +Cc: naveen.n.rao, paulus, linuxppc-dev, ravi.bangoria, dja

This aims to extend the current test infrastructure for in-kernel
instruction emulation by adding support for validating basic integer
operations and will verify the GPRs, LR, XER and CR.

There can be multiple test cases for each instruction. Each test case
has to be provided with the initial register state (in the form of a
pt_regs) and the 32-bit instruction to test.

Apart from verifying the end result, problems with the behaviour of
certain instructions for things like setting certain bits in CR or
XER (which can also be processor dependent) can be identified.

For example, the newly introduced CA32 bit in XER, exclusive to P9
CPUs as of now, was not being set when expected for some of the
arithmetic and shift instructions. With this infrastructure, it will
be easier to identify such problems and rectify them. The test cases
for the addc[.] instruction demonstrate this for different scenarios
where the CA and CA32 bits of XER should be set.

Changelog:
  RFC -> v1:
    - Integrate with current test infrastructure that already tests
      some load and store instructions.
    - Remove first two patches that introduce new instructions fields
      in favour of extending the macros in the current infrastructure.
    - Add a message to indicate that the tests are being run based on
      suggestions from Daniel.

Sandipan Das (3):
  powerpc: sstep: Add tests for compute type instructions
  powerpc: sstep: Add tests for add[.] instruction
  powerpc: sstep: Add tests for addc[.] instruction

 arch/powerpc/include/asm/ppc-opcode.h         |   1 +
 arch/powerpc/lib/Makefile                     |   3 +-
 arch/powerpc/lib/test_emulate_step.c          | 535 +++++++++++++++++-
 .../lib/test_emulate_step_exec_instr.S        | 150 +++++
 4 files changed, 684 insertions(+), 5 deletions(-)
 create mode 100644 arch/powerpc/lib/test_emulate_step_exec_instr.S

-- 
2.19.2


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

* [PATCH 1/3] powerpc: sstep: Add tests for compute type instructions
  2019-02-20  6:56 [PATCH 0/3] powerpc: sstep: Emulation test infrastructure Sandipan Das
@ 2019-02-20  6:56 ` Sandipan Das
  2019-02-21 11:13   ` Michael Ellerman
  2019-02-26  3:27   ` [1/3] " Michael Ellerman
  2019-02-20  6:56 ` [PATCH 2/3] powerpc: sstep: Add tests for add[.] instruction Sandipan Das
  2019-02-20  6:57 ` [PATCH 3/3] powerpc: sstep: Add tests for addc[.] instruction Sandipan Das
  2 siblings, 2 replies; 7+ messages in thread
From: Sandipan Das @ 2019-02-20  6:56 UTC (permalink / raw)
  To: mpe; +Cc: naveen.n.rao, paulus, linuxppc-dev, ravi.bangoria, dja

This enhances the current selftest framework for validating
the in-kernel instruction emulation infrastructure by adding
support for compute type instructions i.e. integer ALU-based
instructions. Originally, this framework was limited to only
testing load and store instructions.

While most of the GPRs can be validated, support for SPRs is
limited to LR, CR and XER for now.

When writing the test cases, one must ensure that the Stack
Pointer (GPR1) or the Thread Pointer (GPR13) are not touched
by any means as these are vital non-volatile registers.

Signed-off-by: Sandipan Das <sandipan@linux.ibm.com>
---
 arch/powerpc/lib/Makefile                     |   3 +-
 arch/powerpc/lib/test_emulate_step.c          | 167 +++++++++++++++++-
 .../lib/test_emulate_step_exec_instr.S        | 150 ++++++++++++++++
 3 files changed, 315 insertions(+), 5 deletions(-)
 create mode 100644 arch/powerpc/lib/test_emulate_step_exec_instr.S

diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index 3bf9fc6fd36c..79396e184bca 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -30,7 +30,8 @@ obj64-y	+= copypage_64.o copyuser_64.o mem_64.o hweight_64.o \
 
 obj64-$(CONFIG_SMP)	+= locks.o
 obj64-$(CONFIG_ALTIVEC)	+= vmx-helper.o
-obj64-$(CONFIG_KPROBES_SANITY_TEST) += test_emulate_step.o
+obj64-$(CONFIG_KPROBES_SANITY_TEST)	+= test_emulate_step.o \
+					   test_emulate_step_exec_instr.o
 
 obj-y			+= checksum_$(BITS).o checksum_wrappers.o \
 			   string_$(BITS).o memcmp_$(BITS).o
diff --git a/arch/powerpc/lib/test_emulate_step.c b/arch/powerpc/lib/test_emulate_step.c
index 6c47daa61614..3d7f7bae51cc 100644
--- a/arch/powerpc/lib/test_emulate_step.c
+++ b/arch/powerpc/lib/test_emulate_step.c
@@ -1,5 +1,5 @@
 /*
- * Simple sanity test for emulate_step load/store instructions.
+ * Simple sanity tests for instruction emulation infrastructure.
  *
  * Copyright IBM Corp. 2016
  *
@@ -14,6 +14,7 @@
 #include <linux/ptrace.h>
 #include <asm/sstep.h>
 #include <asm/ppc-opcode.h>
+#include <asm/code-patching.h>
 
 #define IMM_L(i)		((uintptr_t)(i) & 0xffff)
 
@@ -49,6 +50,11 @@
 #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 MAX_SUBTESTS	16
+
+#define IGNORE_GPR(n)	(0x1UL << (n))
+#define IGNORE_XER	(0x1UL << 32)
+#define IGNORE_CCR	(0x1UL << 33)
 
 static void __init init_pt_regs(struct pt_regs *regs)
 {
@@ -72,9 +78,15 @@ static void __init init_pt_regs(struct pt_regs *regs)
 	msr_cached = true;
 }
 
-static void __init show_result(char *ins, char *result)
+static void __init show_result(char *mnemonic, char *result)
 {
-	pr_info("%-14s : %s\n", ins, result);
+	pr_info("%-14s : %s\n", mnemonic, result);
+}
+
+static void __init show_result_with_descr(char *mnemonic, char *descr,
+					  char *result)
+{
+	pr_info("%-14s : %-50s %s\n", mnemonic, descr, result);
 }
 
 static void __init test_ld(void)
@@ -426,7 +438,7 @@ static void __init test_lxvd2x_stxvd2x(void)
 }
 #endif /* CONFIG_VSX */
 
-static int __init test_emulate_step(void)
+static void __init run_tests_load_store(void)
 {
 	test_ld();
 	test_lwz();
@@ -437,6 +449,153 @@ static int __init test_emulate_step(void)
 	test_lfdx_stfdx();
 	test_lvx_stvx();
 	test_lxvd2x_stxvd2x();
+}
+
+struct compute_test {
+	char *mnemonic;
+	struct {
+		char *descr;
+		unsigned long flags;
+		unsigned int instr;
+		struct pt_regs regs;
+	} subtests[MAX_SUBTESTS + 1];
+};
+
+static struct compute_test compute_tests[] = {
+	{
+		.mnemonic = "nop",
+		.subtests = {
+			{
+				.descr = "R0 = LONG_MAX",
+				.instr = PPC_INST_NOP,
+				.regs = {
+					.gpr[0] = LONG_MAX,
+				}
+			}
+		}
+	}
+};
+
+static int __init emulate_compute_instr(struct pt_regs *regs,
+					unsigned int instr)
+{
+	struct instruction_op op;
+
+	if (!regs || !instr)
+		return -EINVAL;
+
+	if (analyse_instr(&op, regs, instr) != 1 ||
+	    GETTYPE(op.type) != COMPUTE) {
+		pr_info("emulation failed, instruction = 0x%08x\n", instr);
+		return -EFAULT;
+	}
+
+	emulate_update_regs(regs, &op);
+	return 0;
+}
+
+static int __init execute_compute_instr(struct pt_regs *regs,
+					unsigned int instr)
+{
+	extern unsigned int exec_instr_execute[];
+	extern int exec_instr(struct pt_regs *regs);
+
+	if (!regs || !instr)
+		return -EINVAL;
+
+	/* Patch the NOP with the actual instruction */
+	patch_instruction(&exec_instr_execute[0], instr);
+	if (exec_instr(regs)) {
+		pr_info("execution failed, instruction = 0x%08x\n", instr);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+#define gpr_mismatch(gprn, exp, got)	\
+	pr_info("GPR%u mismatch, exp = 0x%016lx, got = 0x%016lx\n",	\
+		gprn, exp, got)
+
+#define reg_mismatch(name, exp, got)	\
+	pr_info("%s mismatch, exp = 0x%016lx, got = 0x%016lx\n",	\
+		name, exp, got)
+
+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;
+	bool ignore_gpr, ignore_xer, ignore_ccr, passed;
+
+	for (i = 0; i < ARRAY_SIZE(compute_tests); i++) {
+		test = &compute_tests[i];
+
+		for (j = 0; j < MAX_SUBTESTS && test->subtests[j].descr; j++) {
+			instr = test->subtests[j].instr;
+			flags = test->subtests[j].flags;
+			regs = &test->subtests[j].regs;
+			ignore_xer = flags & IGNORE_XER;
+			ignore_ccr = flags & IGNORE_CCR;
+			passed = true;
+
+			memcpy(&exp, regs, sizeof(struct pt_regs));
+			memcpy(&got, regs, sizeof(struct pt_regs));
+
+			/*
+			 * Set a compatible MSR value explicitly to ensure
+			 * that XER and CR bits are updated appropriately
+			 */
+			exp.msr = MSR_KERNEL;
+			got.msr = MSR_KERNEL;
+
+			if (emulate_compute_instr(&got, instr) ||
+			    execute_compute_instr(&exp, instr)) {
+				passed = false;
+				goto print;
+			}
+
+			/* Verify GPR values */
+			for (k = 0; k < 32; k++) {
+				ignore_gpr = flags & IGNORE_GPR(k);
+				if (!ignore_gpr && exp.gpr[k] != got.gpr[k]) {
+					passed = false;
+					gpr_mismatch(k, exp.gpr[k], got.gpr[k]);
+				}
+			}
+
+			/* Verify LR value */
+			if (exp.link != got.link) {
+				passed = false;
+				reg_mismatch("LR", exp.link, got.link);
+			}
+
+			/* Verify XER value */
+			if (!ignore_xer && exp.xer != got.xer) {
+				passed = false;
+				reg_mismatch("XER", exp.xer, got.xer);
+			}
+
+			/* Verify CR value */
+			if (!ignore_ccr && exp.ccr != got.ccr) {
+				passed = false;
+				reg_mismatch("CR", exp.ccr, got.ccr);
+			}
+
+print:
+			show_result_with_descr(test->mnemonic,
+					       test->subtests[j].descr,
+					       passed ? "PASS" : "FAIL");
+		}
+	}
+}
+
+static int __init test_emulate_step(void)
+{
+	printk(KERN_INFO "Running instruction emulation self-tests ...\n");
+	run_tests_load_store();
+	run_tests_compute();
 
 	return 0;
 }
diff --git a/arch/powerpc/lib/test_emulate_step_exec_instr.S b/arch/powerpc/lib/test_emulate_step_exec_instr.S
new file mode 100644
index 000000000000..84cef7d78d9d
--- /dev/null
+++ b/arch/powerpc/lib/test_emulate_step_exec_instr.S
@@ -0,0 +1,150 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Non-emulated single-stepping support (currently limited to basic integer
+ * computations) used to validate the instruction emulation infrastructure.
+ *
+ * Copyright (C) 2019 IBM Corporation
+ */
+
+#include <asm/asm-offsets.h>
+#include <asm/ppc_asm.h>
+#include <linux/errno.h>
+
+/* int exec_instr(struct pt_regs *regs) */
+_GLOBAL(exec_instr)
+
+	/*
+	 * Stack frame layout (INT_FRAME_SIZE bytes)
+	 *   In-memory pt_regs	(SP + STACK_FRAME_OVERHEAD)
+	 *   Scratch space	(SP + 8)
+	 *   Back chain		(SP + 0)
+	 */
+
+	/*
+	 * Allocate a new stack frame with enough space to hold the register
+	 * states in an in-memory pt_regs and also create the back chain to
+	 * the caller's stack frame.
+	 */
+	stdu	r1, -INT_FRAME_SIZE(r1)
+
+	/*
+	 * Save non-volatile GPRs on stack. This includes TOC pointer (GPR2)
+	 * and local variables (GPR14 to GPR31). The register for the pt_regs
+	 * parameter (GPR3) is saved additionally to ensure that the resulting
+	 * register state can still be saved even if GPR3 gets overwritten
+	 * when loading the initial register state for the test instruction.
+	 * The stack pointer (GPR1) and the thread pointer (GPR13) are not
+	 * saved as these should not be modified anyway.
+	 */
+	SAVE_2GPRS(2, r1)
+	SAVE_NVGPRS(r1)
+
+	/*
+	 * Save LR on stack to ensure that the return address is available
+	 * even if it gets overwritten by the test instruction.
+	 */
+	mflr	r0
+	std	r0, _LINK(r1)
+
+	/*
+	 * Save CR on stack. For simplicity, the entire register is saved
+	 * even though only fields 2 to 4 are non-volatile.
+	 */
+	mfcr	r0
+	std	r0, _CCR(r1)
+
+	/*
+	 * Load register state for the test instruction without touching the
+	 * critical non-volatile registers. The register state is passed as a
+	 * pointer to a pt_regs instance.
+	 */
+	subi	r31, r3, GPR0
+
+	/* Load LR from pt_regs */
+	ld	r0, _LINK(r31)
+	mtlr	r0
+
+	/* Load CR from pt_regs */
+	ld	r0, _CCR(r31)
+	mtcr	r0
+
+	/* Load XER from pt_regs */
+	ld	r0, _XER(r31)
+	mtxer	r0
+
+	/* Load GPRs from pt_regs */
+	REST_GPR(0, r31)
+	REST_10GPRS(2, r31)
+	REST_GPR(12, r31)
+	REST_NVGPRS(r31)
+
+	.global	exec_instr_execute
+exec_instr_execute:
+	/* Placeholder for the test instruction */
+1:	nop
+
+	/*
+	 * Since GPR3 is overwritten, temporarily restore it back to its
+	 * original state, i.e. the pointer to pt_regs, to ensure that the
+	 * resulting register state can be saved. Before doing this, a copy
+	 * of it is created in the scratch space which is used later on to
+	 * save it to pt_regs.
+	 */
+	std	r3, 8(r1)
+	REST_GPR(3, r1)
+
+	/* Save resulting GPR state to pt_regs */
+	subi	r3, r3, GPR0
+	SAVE_GPR(0, r3)
+	SAVE_GPR(2, r3)
+	SAVE_8GPRS(4, r3)
+	SAVE_GPR(12, r3)
+	SAVE_NVGPRS(r3)
+
+	/* Save resulting LR to pt_regs */
+	mflr	r0
+	std	r0, _LINK(r3)
+
+	/* Save resulting CR to pt_regs */
+	mfcr	r0
+	std	r0, _CCR(r3)
+
+	/* Save resulting XER to pt_regs */
+	mfxer	r0
+	std	r0, _XER(r3)
+
+	/* Restore resulting GPR3 from scratch space and save it to pt_regs */
+	ld	r0, 8(r1)
+	std	r0, GPR3(r3)
+
+	/* Set return value to denote execution success */
+	li	r3, 0
+
+	/* Continue */
+	b	3f
+
+	/* Set return value to denote execution failure */
+2:	li	r3, -EFAULT
+
+	/* Restore the non-volatile GPRs from stack */
+3:	REST_GPR(2, r1)
+	REST_NVGPRS(r1)
+
+	/* Restore LR from stack to be able to return */
+	ld	r0, _LINK(r1)
+	mtlr	r0
+
+	/* Restore CR from stack */
+	ld	r0, _CCR(r1)
+	mtcr	r0
+
+	/* Tear down stack frame */
+	addi	r1, r1, INT_FRAME_SIZE
+
+	/* Return */
+	blr
+
+	/* Setup exception table */
+	EX_TABLE(1b, 2b)
+
+_ASM_NOKPROBE_SYMBOL(exec_instr)
-- 
2.19.2


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

* [PATCH 2/3] powerpc: sstep: Add tests for add[.] instruction
  2019-02-20  6:56 [PATCH 0/3] powerpc: sstep: Emulation test infrastructure Sandipan Das
  2019-02-20  6:56 ` [PATCH 1/3] powerpc: sstep: Add tests for compute type instructions Sandipan Das
@ 2019-02-20  6:56 ` Sandipan Das
  2019-02-20  6:57 ` [PATCH 3/3] powerpc: sstep: Add tests for addc[.] instruction Sandipan Das
  2 siblings, 0 replies; 7+ messages in thread
From: Sandipan Das @ 2019-02-20  6:56 UTC (permalink / raw)
  To: mpe; +Cc: naveen.n.rao, paulus, linuxppc-dev, ravi.bangoria, dja

This adds test cases for the add[.] instruction.

Signed-off-by: Sandipan Das <sandipan@linux.ibm.com>
---
 arch/powerpc/lib/test_emulate_step.c | 176 +++++++++++++++++++++++++++
 1 file changed, 176 insertions(+)

diff --git a/arch/powerpc/lib/test_emulate_step.c b/arch/powerpc/lib/test_emulate_step.c
index 3d7f7bae51cc..bf88b20e53d7 100644
--- a/arch/powerpc/lib/test_emulate_step.c
+++ b/arch/powerpc/lib/test_emulate_step.c
@@ -49,6 +49,10 @@
 					___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) |		\
+					___PPC_RA(a) | ___PPC_RB(b))
+#define TEST_ADD_DOT(t, a, b)	(PPC_INST_ADD | ___PPC_RT(t) |		\
+					___PPC_RA(a) | ___PPC_RB(b) | 0x1)
 
 #define MAX_SUBTESTS	16
 
@@ -473,6 +477,178 @@ static struct compute_test compute_tests[] = {
 				}
 			}
 		}
+	},
+	{
+		.mnemonic = "add",
+		.subtests = {
+			{
+				.descr = "RA = LONG_MIN, RB = LONG_MIN",
+				.instr = TEST_ADD(20, 21, 22),
+				.regs = {
+					.gpr[21] = LONG_MIN,
+					.gpr[22] = LONG_MIN,
+				}
+			},
+			{
+				.descr = "RA = LONG_MIN, RB = LONG_MAX",
+				.instr = TEST_ADD(20, 21, 22),
+				.regs = {
+					.gpr[21] = LONG_MIN,
+					.gpr[22] = LONG_MAX,
+				}
+			},
+			{
+				.descr = "RA = LONG_MAX, RB = LONG_MAX",
+				.instr = TEST_ADD(20, 21, 22),
+				.regs = {
+					.gpr[21] = LONG_MAX,
+					.gpr[22] = LONG_MAX,
+				}
+			},
+			{
+				.descr = "RA = ULONG_MAX, RB = ULONG_MAX",
+				.instr = TEST_ADD(20, 21, 22),
+				.regs = {
+					.gpr[21] = ULONG_MAX,
+					.gpr[22] = ULONG_MAX,
+				}
+			},
+			{
+				.descr = "RA = ULONG_MAX, RB = 0x1",
+				.instr = TEST_ADD(20, 21, 22),
+				.regs = {
+					.gpr[21] = ULONG_MAX,
+					.gpr[22] = 0x1,
+				}
+			},
+			{
+				.descr = "RA = INT_MIN, RB = INT_MIN",
+				.instr = TEST_ADD(20, 21, 22),
+				.regs = {
+					.gpr[21] = INT_MIN,
+					.gpr[22] = INT_MIN,
+				}
+			},
+			{
+				.descr = "RA = INT_MIN, RB = INT_MAX",
+				.instr = TEST_ADD(20, 21, 22),
+				.regs = {
+					.gpr[21] = INT_MIN,
+					.gpr[22] = INT_MAX,
+				}
+			},
+			{
+				.descr = "RA = INT_MAX, RB = INT_MAX",
+				.instr = TEST_ADD(20, 21, 22),
+				.regs = {
+					.gpr[21] = INT_MAX,
+					.gpr[22] = INT_MAX,
+				}
+			},
+			{
+				.descr = "RA = UINT_MAX, RB = UINT_MAX",
+				.instr = TEST_ADD(20, 21, 22),
+				.regs = {
+					.gpr[21] = UINT_MAX,
+					.gpr[22] = UINT_MAX,
+				}
+			},
+			{
+				.descr = "RA = UINT_MAX, RB = 0x1",
+				.instr = TEST_ADD(20, 21, 22),
+				.regs = {
+					.gpr[21] = UINT_MAX,
+					.gpr[22] = 0x1,
+				}
+			}
+		}
+	},
+	{
+		.mnemonic = "add.",
+		.subtests = {
+			{
+				.descr = "RA = LONG_MIN, RB = LONG_MIN",
+				.flags = IGNORE_CCR,
+				.instr = TEST_ADD_DOT(20, 21, 22),
+				.regs = {
+					.gpr[21] = LONG_MIN,
+					.gpr[22] = LONG_MIN,
+				}
+			},
+			{
+				.descr = "RA = LONG_MIN, RB = LONG_MAX",
+				.instr = TEST_ADD_DOT(20, 21, 22),
+				.regs = {
+					.gpr[21] = LONG_MIN,
+					.gpr[22] = LONG_MAX,
+				}
+			},
+			{
+				.descr = "RA = LONG_MAX, RB = LONG_MAX",
+				.flags = IGNORE_CCR,
+				.instr = TEST_ADD_DOT(20, 21, 22),
+				.regs = {
+					.gpr[21] = LONG_MAX,
+					.gpr[22] = LONG_MAX,
+				}
+			},
+			{
+				.descr = "RA = ULONG_MAX, RB = ULONG_MAX",
+				.instr = TEST_ADD_DOT(20, 21, 22),
+				.regs = {
+					.gpr[21] = ULONG_MAX,
+					.gpr[22] = ULONG_MAX,
+				}
+			},
+			{
+				.descr = "RA = ULONG_MAX, RB = 0x1",
+				.instr = TEST_ADD_DOT(20, 21, 22),
+				.regs = {
+					.gpr[21] = ULONG_MAX,
+					.gpr[22] = 0x1,
+				}
+			},
+			{
+				.descr = "RA = INT_MIN, RB = INT_MIN",
+				.instr = TEST_ADD_DOT(20, 21, 22),
+				.regs = {
+					.gpr[21] = INT_MIN,
+					.gpr[22] = INT_MIN,
+				}
+			},
+			{
+				.descr = "RA = INT_MIN, RB = INT_MAX",
+				.instr = TEST_ADD_DOT(20, 21, 22),
+				.regs = {
+					.gpr[21] = INT_MIN,
+					.gpr[22] = INT_MAX,
+				}
+			},
+			{
+				.descr = "RA = INT_MAX, RB = INT_MAX",
+				.instr = TEST_ADD_DOT(20, 21, 22),
+				.regs = {
+					.gpr[21] = INT_MAX,
+					.gpr[22] = INT_MAX,
+				}
+			},
+			{
+				.descr = "RA = UINT_MAX, RB = UINT_MAX",
+				.instr = TEST_ADD_DOT(20, 21, 22),
+				.regs = {
+					.gpr[21] = UINT_MAX,
+					.gpr[22] = UINT_MAX,
+				}
+			},
+			{
+				.descr = "RA = UINT_MAX, RB = 0x1",
+				.instr = TEST_ADD_DOT(20, 21, 22),
+				.regs = {
+					.gpr[21] = UINT_MAX,
+					.gpr[22] = 0x1,
+				}
+			}
+		}
 	}
 };
 
-- 
2.19.2


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

* [PATCH 3/3] powerpc: sstep: Add tests for addc[.] instruction
  2019-02-20  6:56 [PATCH 0/3] powerpc: sstep: Emulation test infrastructure Sandipan Das
  2019-02-20  6:56 ` [PATCH 1/3] powerpc: sstep: Add tests for compute type instructions Sandipan Das
  2019-02-20  6:56 ` [PATCH 2/3] powerpc: sstep: Add tests for add[.] instruction Sandipan Das
@ 2019-02-20  6:57 ` Sandipan Das
  2 siblings, 0 replies; 7+ messages in thread
From: Sandipan Das @ 2019-02-20  6:57 UTC (permalink / raw)
  To: mpe; +Cc: naveen.n.rao, paulus, linuxppc-dev, ravi.bangoria, dja

This adds test cases for the addc[.] instruction.

Signed-off-by: Sandipan Das <sandipan@linux.ibm.com>
---
 arch/powerpc/include/asm/ppc-opcode.h |   1 +
 arch/powerpc/lib/test_emulate_step.c  | 192 ++++++++++++++++++++++++++
 2 files changed, 193 insertions(+)

diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h
index 19a8834e0398..87b73aa56b53 100644
--- a/arch/powerpc/include/asm/ppc-opcode.h
+++ b/arch/powerpc/include/asm/ppc-opcode.h
@@ -326,6 +326,7 @@
 #define PPC_INST_ADDI			0x38000000
 #define PPC_INST_ADDIS			0x3c000000
 #define PPC_INST_ADD			0x7c000214
+#define PPC_INST_ADDC			0x7c000014
 #define PPC_INST_SUB			0x7c000050
 #define PPC_INST_BLR			0x4e800020
 #define PPC_INST_BLRL			0x4e800021
diff --git a/arch/powerpc/lib/test_emulate_step.c b/arch/powerpc/lib/test_emulate_step.c
index bf88b20e53d7..1c13b3bebeca 100644
--- a/arch/powerpc/lib/test_emulate_step.c
+++ b/arch/powerpc/lib/test_emulate_step.c
@@ -53,6 +53,10 @@
 					___PPC_RA(a) | ___PPC_RB(b))
 #define TEST_ADD_DOT(t, a, b)	(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) |		\
+					___PPC_RA(a) | ___PPC_RB(b))
+#define TEST_ADDC_DOT(t, a, b)	(PPC_INST_ADDC | ___PPC_RT(t) |		\
+					___PPC_RA(a) | ___PPC_RB(b) | 0x1)
 
 #define MAX_SUBTESTS	16
 
@@ -649,6 +653,194 @@ static struct compute_test compute_tests[] = {
 				}
 			}
 		}
+	},
+	{
+		.mnemonic = "addc",
+		.subtests = {
+			{
+				.descr = "RA = LONG_MIN, RB = LONG_MIN",
+				.instr = TEST_ADDC(20, 21, 22),
+				.regs = {
+					.gpr[21] = LONG_MIN,
+					.gpr[22] = LONG_MIN,
+				}
+			},
+			{
+				.descr = "RA = LONG_MIN, RB = LONG_MAX",
+				.instr = TEST_ADDC(20, 21, 22),
+				.regs = {
+					.gpr[21] = LONG_MIN,
+					.gpr[22] = LONG_MAX,
+				}
+			},
+			{
+				.descr = "RA = LONG_MAX, RB = LONG_MAX",
+				.instr = TEST_ADDC(20, 21, 22),
+				.regs = {
+					.gpr[21] = LONG_MAX,
+					.gpr[22] = LONG_MAX,
+				}
+			},
+			{
+				.descr = "RA = ULONG_MAX, RB = ULONG_MAX",
+				.instr = TEST_ADDC(20, 21, 22),
+				.regs = {
+					.gpr[21] = ULONG_MAX,
+					.gpr[22] = ULONG_MAX,
+				}
+			},
+			{
+				.descr = "RA = ULONG_MAX, RB = 0x1",
+				.instr = TEST_ADDC(20, 21, 22),
+				.regs = {
+					.gpr[21] = ULONG_MAX,
+					.gpr[22] = 0x1,
+				}
+			},
+			{
+				.descr = "RA = INT_MIN, RB = INT_MIN",
+				.instr = TEST_ADDC(20, 21, 22),
+				.regs = {
+					.gpr[21] = INT_MIN,
+					.gpr[22] = INT_MIN,
+				}
+			},
+			{
+				.descr = "RA = INT_MIN, RB = INT_MAX",
+				.instr = TEST_ADDC(20, 21, 22),
+				.regs = {
+					.gpr[21] = INT_MIN,
+					.gpr[22] = INT_MAX,
+				}
+			},
+			{
+				.descr = "RA = INT_MAX, RB = INT_MAX",
+				.instr = TEST_ADDC(20, 21, 22),
+				.regs = {
+					.gpr[21] = INT_MAX,
+					.gpr[22] = INT_MAX,
+				}
+			},
+			{
+				.descr = "RA = UINT_MAX, RB = UINT_MAX",
+				.instr = TEST_ADDC(20, 21, 22),
+				.regs = {
+					.gpr[21] = UINT_MAX,
+					.gpr[22] = UINT_MAX,
+				}
+			},
+			{
+				.descr = "RA = UINT_MAX, RB = 0x1",
+				.instr = TEST_ADDC(20, 21, 22),
+				.regs = {
+					.gpr[21] = UINT_MAX,
+					.gpr[22] = 0x1,
+				}
+			},
+			{
+				.descr = "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN",
+				.instr = TEST_ADDC(20, 21, 22),
+				.regs = {
+					.gpr[21] = LONG_MIN | (uint)INT_MIN,
+					.gpr[22] = LONG_MIN | (uint)INT_MIN,
+				}
+			}
+		}
+	},
+	{
+		.mnemonic = "addc.",
+		.subtests = {
+			{
+				.descr = "RA = LONG_MIN, RB = LONG_MIN",
+				.flags = IGNORE_CCR,
+				.instr = TEST_ADDC_DOT(20, 21, 22),
+				.regs = {
+					.gpr[21] = LONG_MIN,
+					.gpr[22] = LONG_MIN,
+				}
+			},
+			{
+				.descr = "RA = LONG_MIN, RB = LONG_MAX",
+				.instr = TEST_ADDC_DOT(20, 21, 22),
+				.regs = {
+					.gpr[21] = LONG_MIN,
+					.gpr[22] = LONG_MAX,
+				}
+			},
+			{
+				.descr = "RA = LONG_MAX, RB = LONG_MAX",
+				.flags = IGNORE_CCR,
+				.instr = TEST_ADDC_DOT(20, 21, 22),
+				.regs = {
+					.gpr[21] = LONG_MAX,
+					.gpr[22] = LONG_MAX,
+				}
+			},
+			{
+				.descr = "RA = ULONG_MAX, RB = ULONG_MAX",
+				.instr = TEST_ADDC_DOT(20, 21, 22),
+				.regs = {
+					.gpr[21] = ULONG_MAX,
+					.gpr[22] = ULONG_MAX,
+				}
+			},
+			{
+				.descr = "RA = ULONG_MAX, RB = 0x1",
+				.instr = TEST_ADDC_DOT(20, 21, 22),
+				.regs = {
+					.gpr[21] = ULONG_MAX,
+					.gpr[22] = 0x1,
+				}
+			},
+			{
+				.descr = "RA = INT_MIN, RB = INT_MIN",
+				.instr = TEST_ADDC_DOT(20, 21, 22),
+				.regs = {
+					.gpr[21] = INT_MIN,
+					.gpr[22] = INT_MIN,
+				}
+			},
+			{
+				.descr = "RA = INT_MIN, RB = INT_MAX",
+				.instr = TEST_ADDC_DOT(20, 21, 22),
+				.regs = {
+					.gpr[21] = INT_MIN,
+					.gpr[22] = INT_MAX,
+				}
+			},
+			{
+				.descr = "RA = INT_MAX, RB = INT_MAX",
+				.instr = TEST_ADDC_DOT(20, 21, 22),
+				.regs = {
+					.gpr[21] = INT_MAX,
+					.gpr[22] = INT_MAX,
+				}
+			},
+			{
+				.descr = "RA = UINT_MAX, RB = UINT_MAX",
+				.instr = TEST_ADDC_DOT(20, 21, 22),
+				.regs = {
+					.gpr[21] = UINT_MAX,
+					.gpr[22] = UINT_MAX,
+				}
+			},
+			{
+				.descr = "RA = UINT_MAX, RB = 0x1",
+				.instr = TEST_ADDC_DOT(20, 21, 22),
+				.regs = {
+					.gpr[21] = UINT_MAX,
+					.gpr[22] = 0x1,
+				}
+			},
+			{
+				.descr = "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN",
+				.instr = TEST_ADDC_DOT(20, 21, 22),
+				.regs = {
+					.gpr[21] = LONG_MIN | (uint)INT_MIN,
+					.gpr[22] = LONG_MIN | (uint)INT_MIN,
+				}
+			}
+		}
 	}
 };
 
-- 
2.19.2


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

* Re: [PATCH 1/3] powerpc: sstep: Add tests for compute type instructions
  2019-02-20  6:56 ` [PATCH 1/3] powerpc: sstep: Add tests for compute type instructions Sandipan Das
@ 2019-02-21 11:13   ` Michael Ellerman
  2019-02-22  6:49     ` Sandipan Das
  2019-02-26  3:27   ` [1/3] " Michael Ellerman
  1 sibling, 1 reply; 7+ messages in thread
From: Michael Ellerman @ 2019-02-21 11:13 UTC (permalink / raw)
  To: Sandipan Das; +Cc: naveen.n.rao, paulus, linuxppc-dev, ravi.bangoria, dja

Sandipan Das <sandipan@linux.ibm.com> writes:
> This enhances the current selftest framework for validating
> the in-kernel instruction emulation infrastructure by adding
> support for compute type instructions i.e. integer ALU-based
> instructions. Originally, this framework was limited to only
> testing load and store instructions.
>
> While most of the GPRs can be validated, support for SPRs is
> limited to LR, CR and XER for now.
>
> When writing the test cases, one must ensure that the Stack
> Pointer (GPR1) or the Thread Pointer (GPR13) are not touched
> by any means as these are vital non-volatile registers.
>
> Signed-off-by: Sandipan Das <sandipan@linux.ibm.com>
> ---
>  arch/powerpc/lib/Makefile                     |   3 +-
>  arch/powerpc/lib/test_emulate_step.c          | 167 +++++++++++++++++-
>  .../lib/test_emulate_step_exec_instr.S        | 150 ++++++++++++++++
>  3 files changed, 315 insertions(+), 5 deletions(-)
>  create mode 100644 arch/powerpc/lib/test_emulate_step_exec_instr.S

Hi Sandipan,

Thanks for the exceptionally well written asm, I wish all our asm code
was that neat and well commented :)

I'd like to get this merged today so I tweaked it slightly when
applying to use the new patch_site helpers we added recently, see diff
below.

cheers


diff --git a/arch/powerpc/lib/test_emulate_step.c b/arch/powerpc/lib/test_emulate_step.c
index 1c13b3bebeca..9992c1ea7a1d 100644
--- a/arch/powerpc/lib/test_emulate_step.c
+++ b/arch/powerpc/lib/test_emulate_step.c
@@ -865,14 +865,14 @@ static int __init emulate_compute_instr(struct pt_regs *regs,
 static int __init execute_compute_instr(struct pt_regs *regs,
 					unsigned int instr)
 {
-	extern unsigned int exec_instr_execute[];
 	extern int exec_instr(struct pt_regs *regs);
+	extern s32 patch__exec_instr;
 
 	if (!regs || !instr)
 		return -EINVAL;
 
 	/* Patch the NOP with the actual instruction */
-	patch_instruction(&exec_instr_execute[0], instr);
+	patch_instruction_site(&patch__exec_instr, instr);
 	if (exec_instr(regs)) {
 		pr_info("execution failed, instruction = 0x%08x\n", instr);
 		return -EFAULT;
diff --git a/arch/powerpc/lib/test_emulate_step_exec_instr.S b/arch/powerpc/lib/test_emulate_step_exec_instr.S
index 84cef7d78d9d..1580f34f4f4f 100644
--- a/arch/powerpc/lib/test_emulate_step_exec_instr.S
+++ b/arch/powerpc/lib/test_emulate_step_exec_instr.S
@@ -8,6 +8,7 @@
 
 #include <asm/asm-offsets.h>
 #include <asm/ppc_asm.h>
+#include <asm/code-patching-asm.h>
 #include <linux/errno.h>
 
 /* int exec_instr(struct pt_regs *regs) */
@@ -78,10 +79,9 @@ _GLOBAL(exec_instr)
 	REST_GPR(12, r31)
 	REST_NVGPRS(r31)
 
-	.global	exec_instr_execute
-exec_instr_execute:
 	/* Placeholder for the test instruction */
 1:	nop
+	patch_site 1b patch__exec_instr
 
 	/*
 	 * Since GPR3 is overwritten, temporarily restore it back to its

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

* Re: [PATCH 1/3] powerpc: sstep: Add tests for compute type instructions
  2019-02-21 11:13   ` Michael Ellerman
@ 2019-02-22  6:49     ` Sandipan Das
  0 siblings, 0 replies; 7+ messages in thread
From: Sandipan Das @ 2019-02-22  6:49 UTC (permalink / raw)
  To: Michael Ellerman; +Cc: naveen.n.rao, paulus, linuxppc-dev, ravi.bangoria, dja

Hi Michael,

On 21/02/19 4:43 PM, Michael Ellerman wrote:
> Sandipan Das <sandipan@linux.ibm.com> writes:
>> This enhances the current selftest framework for validating
>> the in-kernel instruction emulation infrastructure by adding
>> support for compute type instructions i.e. integer ALU-based
>> instructions. Originally, this framework was limited to only
>> testing load and store instructions.
>>
>> While most of the GPRs can be validated, support for SPRs is
>> limited to LR, CR and XER for now.
>>
>> When writing the test cases, one must ensure that the Stack
>> Pointer (GPR1) or the Thread Pointer (GPR13) are not touched
>> by any means as these are vital non-volatile registers.
>>
>> Signed-off-by: Sandipan Das <sandipan@linux.ibm.com>
>> ---
>>  arch/powerpc/lib/Makefile                     |   3 +-
>>  arch/powerpc/lib/test_emulate_step.c          | 167 +++++++++++++++++-
>>  .../lib/test_emulate_step_exec_instr.S        | 150 ++++++++++++++++
>>  3 files changed, 315 insertions(+), 5 deletions(-)
>>  create mode 100644 arch/powerpc/lib/test_emulate_step_exec_instr.S
> 
> Hi Sandipan,
> 
> Thanks for the exceptionally well written asm, I wish all our asm code
> was that neat and well commented :)
> 
> I'd like to get this merged today so I tweaked it slightly when
> applying to use the new patch_site helpers we added recently, see diff
> below.
> 
> cheers
> 
> 

Thanks for modernizing it :)

- Sandipan


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

* Re: [1/3] powerpc: sstep: Add tests for compute type instructions
  2019-02-20  6:56 ` [PATCH 1/3] powerpc: sstep: Add tests for compute type instructions Sandipan Das
  2019-02-21 11:13   ` Michael Ellerman
@ 2019-02-26  3:27   ` Michael Ellerman
  1 sibling, 0 replies; 7+ messages in thread
From: Michael Ellerman @ 2019-02-26  3:27 UTC (permalink / raw)
  To: Sandipan Das; +Cc: naveen.n.rao, linuxppc-dev, dja, paulus, ravi.bangoria

On Wed, 2019-02-20 at 06:56:58 UTC, Sandipan Das wrote:
> This enhances the current selftest framework for validating
> the in-kernel instruction emulation infrastructure by adding
> support for compute type instructions i.e. integer ALU-based
> instructions. Originally, this framework was limited to only
> testing load and store instructions.
> 
> While most of the GPRs can be validated, support for SPRs is
> limited to LR, CR and XER for now.
> 
> When writing the test cases, one must ensure that the Stack
> Pointer (GPR1) or the Thread Pointer (GPR13) are not touched
> by any means as these are vital non-volatile registers.
> 
> Signed-off-by: Sandipan Das <sandipan@linux.ibm.com>

Series applied to powerpc next, thanks.

https://git.kernel.org/powerpc/c/84022ac17327c5383917f46c162fd943

cheers

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

end of thread, other threads:[~2019-02-26  3:34 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-20  6:56 [PATCH 0/3] powerpc: sstep: Emulation test infrastructure Sandipan Das
2019-02-20  6:56 ` [PATCH 1/3] powerpc: sstep: Add tests for compute type instructions Sandipan Das
2019-02-21 11:13   ` Michael Ellerman
2019-02-22  6:49     ` Sandipan Das
2019-02-26  3:27   ` [1/3] " Michael Ellerman
2019-02-20  6:56 ` [PATCH 2/3] powerpc: sstep: Add tests for add[.] instruction Sandipan Das
2019-02-20  6:57 ` [PATCH 3/3] powerpc: sstep: Add tests for addc[.] instruction Sandipan Das

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).