[CRIU] [PATCH v2 5/5] s390: Add test case for RI

Alice Frosi alice at linux.vnet.ibm.com
Thu Oct 5 16:50:43 MSK 2017


 - Add new test "s390x_runtime_instr" to check if the RI control block is
   correctly restored when the RI is active.

 - Add RI control block in test s390x_regs_check.c

The original test case for RI has been provided by
Martin Schwidefsky <schwidefsky at de.ibm.com>

Signed-off-by: Alice Frosi <alice at linux.vnet.ibm.com>
Reviewed-by: Michael Holzheu <holzheu at linux.vnet.ibm.com>
---
 test/zdtm/static/Makefile              |   3 +-
 test/zdtm/static/s390x_regs_check.c    |  31 +++++
 test/zdtm/static/s390x_runtime_instr.c | 212 +++++++++++++++++++++++++++++++++
 3 files changed, 245 insertions(+), 1 deletion(-)
 create mode 100644 test/zdtm/static/s390x_runtime_instr.c

diff --git a/test/zdtm/static/Makefile b/test/zdtm/static/Makefile
index 1030f0610..f3040ba0f 100644
--- a/test/zdtm/static/Makefile
+++ b/test/zdtm/static/Makefile
@@ -206,7 +206,8 @@ endif
 
 ifeq ($(SRCARCH),s390)
         TST_NOFILE +=	s390x_regs_check	\
-			s390x_gs_threads
+			s390x_gs_threads	\
+			s390x_runtime_instr
 endif
 
 TST_FILE	=				\
diff --git a/test/zdtm/static/s390x_regs_check.c b/test/zdtm/static/s390x_regs_check.c
index ab9d7d139..9aaf41951 100644
--- a/test/zdtm/static/s390x_regs_check.c
+++ b/test/zdtm/static/s390x_regs_check.c
@@ -227,6 +227,36 @@ struct reg_set reg_set_gs_bc = {
 };
 
 /*
+ * s390 runtime-instrumentation control block
+ */
+#define NT_S390_RI_CB		0x30d
+
+struct ri_cb {
+	uint64_t regs[8];
+};
+
+struct ri_cb ri_cb_data = {
+	.regs = {
+			0x000002aa13aae000,
+			0x000002aa13aad000,
+			0x000002aa13aadfff,
+			0xe0a1000400000000,
+			0x0000000000000000,
+			0x0000000000004e20,
+			0x0000000000003479,
+			0x0000000000000000,
+	}
+};
+
+struct reg_set reg_set_ri_cb = {
+	.name		= "RI_CB",
+	.nr		= NT_S390_RI_CB,
+	.data		= &ri_cb_data,
+	.len		= sizeof(ri_cb_data),
+	.optional	= true,
+};
+
+/*
  * Vector with all regsets
  */
 struct reg_set *reg_set_vec[] = {
@@ -235,6 +265,7 @@ struct reg_set *reg_set_vec[] = {
 	&reg_set_vxrs_high,
 	&reg_set_gs_cb,
 	&reg_set_gs_bc,
+	&reg_set_ri_cb,
 	NULL,
 };
 
diff --git a/test/zdtm/static/s390x_runtime_instr.c b/test/zdtm/static/s390x_runtime_instr.c
new file mode 100644
index 000000000..6be32c3c1
--- /dev/null
+++ b/test/zdtm/static/s390x_runtime_instr.c
@@ -0,0 +1,212 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <errno.h>
+#include <sys/ptrace.h>
+#include <stdlib.h>
+#include <sys/uio.h>
+#include <asm/ptrace.h>
+#include <linux/elf.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <ucontext.h>
+#include <signal.h>
+#include <string.h>
+
+#include "zdtmtst.h"
+
+#ifndef __NR_s390_runtime_instr
+#define __NR_s390_runtime_instr		342
+#endif
+#define NT_S390_RI_CB			0x30d
+
+#define BUF_SIZE (1024*1024)
+
+const char *test_doc	= "Check runtime-instrumentation";
+/* Original test provided by Martin Schwidefsky <schwidefsky at de.ibm.com> */
+const char *test_author	= "Alice Frosi <alice at linux.vnet.ibm.com>";
+
+struct runtime_instr_cb {
+	unsigned long rca;
+	unsigned long roa;
+	unsigned long rla;
+
+	unsigned int v			: 1;
+	unsigned int s			: 1;
+	unsigned int k			: 1;
+	unsigned int h			: 1;
+	unsigned int a			: 1;
+	unsigned int reserved1		: 3;
+	unsigned int ps		: 1;
+	unsigned int qs		: 1;
+	unsigned int pc		: 1;
+	unsigned int qc		: 1;
+	unsigned int reserved2		: 1;
+	unsigned int g			: 1;
+	unsigned int u			: 1;
+	unsigned int l			: 1;
+	unsigned int key		: 4;
+	unsigned int reserved3		: 8;
+	unsigned int t			: 1;
+	unsigned int rgs		: 3;
+
+	unsigned int m			: 4;
+	unsigned int n			: 1;
+	unsigned int mae		: 1;
+	unsigned int reserved4		: 2;
+	unsigned int c			: 1;
+	unsigned int r			: 1;
+	unsigned int b			: 1;
+	unsigned int j			: 1;
+	unsigned int e			: 1;
+	unsigned int x			: 1;
+	unsigned int reserved5		: 2;
+	unsigned int bpxn		: 1;
+	unsigned int bpxt		: 1;
+	unsigned int bpti		: 1;
+	unsigned int bpni		: 1;
+	unsigned int reserved6		: 2;
+
+	unsigned int d			: 1;
+	unsigned int f			: 1;
+	unsigned int ic		: 4;
+	unsigned int dc		: 4;
+
+	unsigned long reserved7;
+	unsigned long sf;
+	unsigned long rsic;
+	unsigned long reserved8;
+};
+
+/*
+ * Return PSW mask
+ */
+static inline unsigned long extract_psw(void)
+{
+	unsigned int reg1, reg2;
+
+	asm volatile("epsw %0,%1" : "=d" (reg1), "=a" (reg2));
+	return (((unsigned long) reg1) << 32) | ((unsigned long) reg2);
+}
+
+/*
+ * Enable runtime-instrumentation
+ */
+static inline void rion(void)
+{
+	asm volatile (".word 0xaa01, 0x0000");
+}
+
+/*
+ * Disable runtime-instrumentation
+ */
+static inline void rioff(void)
+{
+	asm volatile (".word 0xaa03, 0x0000");
+}
+
+/*
+ * Modify the current runtime-instrumentation control block
+ */
+static inline void mric(struct runtime_instr_cb *cb)
+{
+	asm volatile(".insn rsy,0xeb0000000062,0,0,%0" : : "Q" (*cb));
+}
+
+/*
+ * Store the current runtime-instrumentation control block
+ */
+static inline void stric(struct runtime_instr_cb *cb)
+{
+	asm volatile(".insn rsy,0xeb0000000061,0,0,%0" : "=Q" (*cb) : : "cc");
+}
+
+/*
+ * Ensure that runtime-intstrumentation is still working after C/R
+ */
+int main(int argc, char **argv)
+{
+	struct runtime_instr_cb ricb, ricb_check;
+	unsigned long *ricb_check_ptr = (unsigned long *) &ricb_check;
+	unsigned long *ricb_ptr = (unsigned long *) &ricb;
+	unsigned long psw_mask;
+	void *buf;
+	int i;
+
+	test_init(argc, argv);
+	buf = malloc(BUF_SIZE);
+	memset(buf, 0, BUF_SIZE);
+	memset(&ricb, 0, sizeof(ricb));
+	/* Initialize the default RI control block in the kernel */
+	if (syscall(__NR_s390_runtime_instr, 1, NULL) < 0) {
+		if (errno == EOPNOTSUPP) {
+			test_daemon();
+			test_waitsig();
+			skip("RI not supported");
+			pass();
+			return 0;
+		}
+		fail("Fail with error %d", errno);
+		return -1;
+	}
+	/* Set buffer for RI */
+	ricb.rca = ricb.roa = (unsigned long) buf;
+	ricb.rla = (unsigned long) buf + BUF_SIZE;
+	mric(&ricb);
+	/* Enable RI - afterwards the PSW will have RI bit set */
+	rion();
+	psw_mask = extract_psw();
+	/* Verify that the RI bit is set in the PSW */
+	if (!(psw_mask & PSW_MASK_RI)) {
+		fail("Failed to enable RI");
+		return -1;
+	}
+	/* Collect RI records until we hit buffer-full condition */
+	while (ricb.rca < ricb.rla + 1) {
+		for (i = 0; i < 10000; i++)
+			asm volatile("" : : : "memory");
+		rioff();
+		stric(&ricb);
+		rion();
+	}
+	/* Disable RI */
+	rioff();
+	/* Save the current RI control block */
+	stric(&ricb);
+	ricb_check = ricb;
+	/* Re-enable RI for checkpoint */
+	rion();
+
+	/* Do C/R now */
+	test_daemon();
+	test_waitsig();
+
+	/* Verify that the RI bit is set in the PSW */
+	psw_mask = extract_psw();
+	if (!(psw_mask & PSW_MASK_RI)) {
+		fail("RI bit in PSW not set");
+		return -1;
+	}
+	/*
+	 * Verify that the RI block has been restored correctly
+	 * and the buffer is unchanged
+	 */
+	rioff();
+	stric(&ricb);
+	for (i = 0; i < 8; i++) {
+		if (ricb_ptr[i] == ricb_check_ptr[i])
+			continue;
+		/* Skip sf field because its value may change */
+		if (i == 6)
+			continue;
+		fail("%d:Got %016lx expected %016lx",
+		     i, ricb_ptr[i], ricb_check_ptr[i]);
+		return -1;
+	}
+
+	pass();
+	return 0;
+}
-- 
2.13.5



More information about the CRIU mailing list