public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
From: Janosch Frank <frankja@linux.ibm.com>
To: pbonzini@redhat.com
Cc: kvm@vger.kernel.org, frankja@linux.ibm.com, david@redhat.com,
	borntraeger@de.ibm.com, cohuck@redhat.com,
	linux-s390@vger.kernel.org, imbrenda@linux.ibm.com
Subject: [kvm-unit-tests GIT PULL 15/16] s390x: mvpg: simple test
Date: Mon,  8 Mar 2021 15:31:46 +0100	[thread overview]
Message-ID: <20210308143147.64755-16-frankja@linux.ibm.com> (raw)
In-Reply-To: <20210308143147.64755-1-frankja@linux.ibm.com>

From: Claudio Imbrenda <imbrenda@linux.ibm.com>

A simple unit test for the MVPG instruction.

The timeout is set to 10 seconds because the test should complete in a
fraction of a second even on busy machines. If the test is run in VSIE
and the host of the host is not handling MVPG properly, the test will
probably hang.

Testing MVPG behaviour in VSIE is the main motivation for this test.

Anything related to storage keys is not tested.

Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Link: https://lore.kernel.org/kvm/20210302114107.501837-3-imbrenda@linux.ibm.com/
Acked-by: Janosch Frank <frankja@linux.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
---
 s390x/Makefile      |   1 +
 s390x/mvpg.c        | 267 ++++++++++++++++++++++++++++++++++++++++++++
 s390x/unittests.cfg |   4 +
 3 files changed, 272 insertions(+)
 create mode 100644 s390x/mvpg.c

diff --git a/s390x/Makefile b/s390x/Makefile
index 20bb5683..b92de9c5 100644
--- a/s390x/Makefile
+++ b/s390x/Makefile
@@ -20,6 +20,7 @@ tests += $(TEST_DIR)/sclp.elf
 tests += $(TEST_DIR)/css.elf
 tests += $(TEST_DIR)/uv-guest.elf
 tests += $(TEST_DIR)/sie.elf
+tests += $(TEST_DIR)/mvpg.elf
 
 tests_binary = $(patsubst %.elf,%.bin,$(tests))
 ifneq ($(HOST_KEY_DOCUMENT),)
diff --git a/s390x/mvpg.c b/s390x/mvpg.c
new file mode 100644
index 00000000..1776ec6e
--- /dev/null
+++ b/s390x/mvpg.c
@@ -0,0 +1,267 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Move Page instruction tests
+ *
+ * Copyright (c) 2021 IBM Corp
+ *
+ * Authors:
+ *  Claudio Imbrenda <imbrenda@linux.ibm.com>
+ */
+#include <libcflat.h>
+#include <asm/asm-offsets.h>
+#include <asm-generic/barrier.h>
+#include <asm/interrupt.h>
+#include <asm/pgtable.h>
+#include <mmu.h>
+#include <asm/page.h>
+#include <asm/facility.h>
+#include <asm/mem.h>
+#include <asm/sigp.h>
+#include <smp.h>
+#include <alloc_page.h>
+#include <bitops.h>
+
+/* Used to build the appropriate test values for register 0 */
+#define KFC(x) ((x) << 10)
+#define CCO 0x100
+
+/* How much memory to allocate for the test */
+#define MEM_ORDER 12
+/* How many iterations to perform in the loops */
+#define ITER 8
+
+/* Used to generate the simple pattern */
+#define MAGIC 42
+
+static uint8_t source[PAGE_SIZE]  __attribute__((aligned(PAGE_SIZE)));
+static uint8_t buffer[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE)));
+
+/* Keep track of fresh memory */
+static uint8_t *fresh;
+
+static inline int mvpg(unsigned long r0, void *dest, void *src)
+{
+	register unsigned long reg0 asm ("0") = r0;
+	int cc;
+
+	asm volatile("	mvpg    %1,%2\n"
+		     "	ipm     %0\n"
+		     "	srl     %0,28"
+		: "=&d" (cc) : "a" (dest), "a" (src), "d" (reg0)
+		: "memory", "cc");
+	return cc;
+}
+
+/*
+ * Initialize a page with a simple pattern
+ */
+static void init_page(uint8_t *p)
+{
+	int i;
+
+	for (i = 0; i < PAGE_SIZE; i++)
+		p[i] = i + MAGIC;
+}
+
+/*
+ * Check if the given page contains the simple pattern
+ */
+static int page_ok(const uint8_t *p)
+{
+	int i;
+
+	for (i = 0; i < PAGE_SIZE; i++)
+		if (p[i] != (uint8_t)(i + MAGIC))
+			return 0;
+	return 1;
+}
+
+static void test_exceptions(void)
+{
+	int i, expected;
+
+	report_prefix_push("exceptions");
+
+	/*
+	 * Key Function Control values 4 and 5 are allowed only in supervisor
+	 * state, and even then, only if the move-page-and-set-key facility
+	 * is present (STFLE bit 149)
+	 */
+	report_prefix_push("privileged");
+	if (test_facility(149)) {
+		expected = PGM_INT_CODE_PRIVILEGED_OPERATION;
+		for (i = 4; i < 6; i++) {
+			expect_pgm_int();
+			enter_pstate();
+			mvpg(KFC(i), buffer, source);
+			report(clear_pgm_int() == expected, "Key Function Control value %d", i);
+		}
+	} else {
+		report_skip("Key Function Control value %d", 4);
+		report_skip("Key Function Control value %d", 5);
+		i = 4;
+	}
+	report_prefix_pop();
+
+	/*
+	 * Invalid values of the Key Function Control, or setting the
+	 * reserved bits, should result in a specification exception
+	 */
+	report_prefix_push("specification");
+	expected = PGM_INT_CODE_SPECIFICATION;
+	expect_pgm_int();
+	mvpg(KFC(3), buffer, source);
+	report(clear_pgm_int() == expected, "Key Function Control value 3");
+	for (; i < 32; i++) {
+		expect_pgm_int();
+		mvpg(KFC(i), buffer, source);
+		report(clear_pgm_int() == expected, "Key Function Control value %d", i);
+	}
+	report_prefix_pop();
+
+	/* Operands outside memory result in addressing exceptions, as usual */
+	report_prefix_push("addressing");
+	expected = PGM_INT_CODE_ADDRESSING;
+	expect_pgm_int();
+	mvpg(0, buffer, (void *)PAGE_MASK);
+	report(clear_pgm_int() == expected, "Second operand outside memory");
+
+	expect_pgm_int();
+	mvpg(0, (void *)PAGE_MASK, source);
+	report(clear_pgm_int() == expected, "First operand outside memory");
+	report_prefix_pop();
+
+	report_prefix_pop();
+}
+
+static void test_success(void)
+{
+	int cc;
+
+	report_prefix_push("success");
+	/* Test successful scenarios, both in supervisor and problem state */
+	cc = mvpg(0, buffer, source);
+	report(page_ok(buffer) && !cc, "Supervisor state MVPG successful");
+	memset(buffer, 0xff, PAGE_SIZE);
+
+	enter_pstate();
+	cc = mvpg(0, buffer, source);
+	leave_pstate();
+	report(page_ok(buffer) && !cc, "Problem state MVPG successful");
+
+	report_prefix_pop();
+}
+
+static void test_small_loop(const void *string)
+{
+	uint8_t *dest;
+	int i, cc;
+
+	/* Looping over cold and warm pages helps catch VSIE bugs */
+	report_prefix_push(string);
+	dest = fresh;
+	for (i = 0; i < ITER; i++) {
+		cc = mvpg(0, fresh, source);
+		report(page_ok(fresh) && !cc, "cold: %p, %p", source, fresh);
+		fresh += PAGE_SIZE;
+	}
+
+	for (i = 0; i < ITER; i++) {
+		memset(dest, 0, PAGE_SIZE);
+		cc = mvpg(0, dest, source);
+		report(page_ok(dest) && !cc, "warm: %p, %p", source, dest);
+		dest += PAGE_SIZE;
+	}
+	report_prefix_pop();
+}
+
+static void test_mmu_prot(void)
+{
+	int cc;
+
+	report_prefix_push("protection");
+	report_prefix_push("cco=0");
+
+	/* MVPG should still succeed when the source is read-only */
+	protect_page(source, PAGE_ENTRY_P);
+	cc = mvpg(0, fresh, source);
+	report(page_ok(fresh) && !cc, "source read only");
+	unprotect_page(source, PAGE_ENTRY_P);
+	fresh += PAGE_SIZE;
+
+	/*
+	 * When the source or destination are invalid, a page translation
+	 * exception should be raised; when the destination is read-only,
+	 * a protection exception should be raised.
+	 */
+	protect_page(fresh, PAGE_ENTRY_P);
+	expect_pgm_int();
+	mvpg(0, fresh, source);
+	report(clear_pgm_int() == PGM_INT_CODE_PROTECTION, "destination read only");
+	fresh += PAGE_SIZE;
+
+	protect_page(source, PAGE_ENTRY_I);
+	expect_pgm_int();
+	mvpg(0, fresh, source);
+	report(clear_pgm_int() == PGM_INT_CODE_PAGE_TRANSLATION, "source invalid");
+	unprotect_page(source, PAGE_ENTRY_I);
+	fresh += PAGE_SIZE;
+
+	protect_page(fresh, PAGE_ENTRY_I);
+	expect_pgm_int();
+	mvpg(0, fresh, source);
+	report(clear_pgm_int() == PGM_INT_CODE_PAGE_TRANSLATION, "destination invalid");
+	fresh += PAGE_SIZE;
+
+	report_prefix_pop();
+	report_prefix_push("cco=1");
+	/*
+	 * Setting the CCO bit should suppress page translation exceptions,
+	 * but not protection exceptions.
+	 */
+	protect_page(fresh, PAGE_ENTRY_P);
+	expect_pgm_int();
+	mvpg(CCO, fresh, source);
+	report(clear_pgm_int() == PGM_INT_CODE_PROTECTION, "destination read only");
+	fresh += PAGE_SIZE;
+
+	protect_page(fresh, PAGE_ENTRY_I);
+	cc = mvpg(CCO, fresh, source);
+	report(cc == 1, "destination invalid");
+	fresh += PAGE_SIZE;
+
+	protect_page(source, PAGE_ENTRY_I);
+	cc = mvpg(CCO, fresh, source);
+	report(cc == 2, "source invalid");
+	fresh += PAGE_SIZE;
+
+	protect_page(fresh, PAGE_ENTRY_I);
+	cc = mvpg(CCO, fresh, source);
+	report(cc == 2, "source and destination invalid");
+	fresh += PAGE_SIZE;
+
+	unprotect_page(source, PAGE_ENTRY_I);
+	report_prefix_pop();
+	report_prefix_pop();
+}
+
+int main(void)
+{
+	report_prefix_push("mvpg");
+
+	init_page(source);
+	fresh = alloc_pages_flags(MEM_ORDER, FLAG_DONTZERO | FLAG_FRESH);
+	assert(fresh);
+
+	test_exceptions();
+	test_success();
+	test_small_loop("nommu");
+
+	setup_vm();
+
+	test_small_loop("mmu");
+	test_mmu_prot();
+
+	report_prefix_pop();
+	return report_summary();
+}
diff --git a/s390x/unittests.cfg b/s390x/unittests.cfg
index 2298be6c..9f81a608 100644
--- a/s390x/unittests.cfg
+++ b/s390x/unittests.cfg
@@ -99,3 +99,7 @@ file = uv-guest.elf
 
 [sie]
 file = sie.elf
+
+[mvpg]
+file = mvpg.elf
+timeout = 10
-- 
2.29.2


  parent reply	other threads:[~2021-03-08 14:34 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-03-08 14:31 [kvm-unit-tests GIT PULL 00/16] s390x update Janosch Frank
2021-03-08 14:31 ` [kvm-unit-tests GIT PULL 01/16] lib/s390x/sclp: Clarify that the CPUEntry array could be at a different spot Janosch Frank
2021-03-08 14:31 ` [kvm-unit-tests GIT PULL 02/16] s390x: pv: implement routine to share/unshare memory Janosch Frank
2021-03-08 14:31 ` [kvm-unit-tests GIT PULL 03/16] s390x: define UV compatible I/O allocation Janosch Frank
2021-03-08 14:31 ` [kvm-unit-tests GIT PULL 04/16] s390x: css: pv: css test adaptation for PV Janosch Frank
2021-03-08 14:31 ` [kvm-unit-tests GIT PULL 05/16] Fix the length in the stsi check for the VM name Janosch Frank
2021-03-08 14:31 ` [kvm-unit-tests GIT PULL 06/16] s390x: Remove sthyi partition number check Janosch Frank
2021-03-08 14:31 ` [kvm-unit-tests GIT PULL 07/16] s390x: Fix fpc store address in RESTORE_REGS_STACK Janosch Frank
2021-03-08 14:31 ` [kvm-unit-tests GIT PULL 08/16] s390x: Fully commit to stack save area for exceptions Janosch Frank
2021-03-08 14:31 ` [kvm-unit-tests GIT PULL 09/16] s390x: Introduce and use CALL_INT_HANDLER macro Janosch Frank
2021-03-08 14:31 ` [kvm-unit-tests GIT PULL 10/16] s390x: Provide preliminary backtrace support Janosch Frank
2021-03-08 14:31 ` [kvm-unit-tests GIT PULL 11/16] s390x: Print more information on program exceptions Janosch Frank
2021-03-08 14:31 ` [kvm-unit-tests GIT PULL 12/16] s390x: Move diag308_load_reset to stack saving Janosch Frank
2021-03-08 14:31 ` [kvm-unit-tests GIT PULL 13/16] s390x: Remove SAVE/RESTORE_STACK and lowcore fpc and fprs save areas Janosch Frank
2021-03-08 14:31 ` [kvm-unit-tests GIT PULL 14/16] s390x: introduce leave_pstate to leave userspace Janosch Frank
2021-03-08 14:31 ` Janosch Frank [this message]
2021-03-08 14:31 ` [kvm-unit-tests GIT PULL 16/16] s390x: mvpg: skip some tests when using TCG Janosch Frank
2021-03-08 14:36 ` [kvm-unit-tests GIT PULL 00/16] s390x update Paolo Bonzini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210308143147.64755-16-frankja@linux.ibm.com \
    --to=frankja@linux.ibm.com \
    --cc=borntraeger@de.ibm.com \
    --cc=cohuck@redhat.com \
    --cc=david@redhat.com \
    --cc=imbrenda@linux.ibm.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-s390@vger.kernel.org \
    --cc=pbonzini@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox