[kvm-unit-tests,PULL,5/5] s390x: test if the DXC is correctly stored
diff mbox series

Message ID 20180830163022.12350-6-david@redhat.com
State New
Headers show
Series
  • [kvm-unit-tests,PULL,1/5] s390x: user ctl_set/clear_bit for low address protection
Related show

Commit Message

David Hildenbrand Aug. 30, 2018, 4:30 p.m. UTC
This was not properly handled in TCG for all DATA exceptions. Let's
use a simple example.

CRT produced a trap via a DATA exception with DXC 0xff, when in this
case both registers are equal (which is the case because we are using
the same register).

Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
---
 lib/s390x/asm/float.h | 51 +++++++++++++++++++++++++++++++++++++++++++
 s390x/emulator.c      | 34 +++++++++++++++++++++++++++++
 2 files changed, 85 insertions(+)
 create mode 100644 lib/s390x/asm/float.h

Patch
diff mbox series

diff --git a/lib/s390x/asm/float.h b/lib/s390x/asm/float.h
new file mode 100644
index 0000000..adab986
--- /dev/null
+++ b/lib/s390x/asm/float.h
@@ -0,0 +1,51 @@ 
+/*
+ * Copyright (c) 2018 Red Hat Inc
+ *
+ * Authors:
+ *  David Hildenbrand <david@redhat.com>
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License version 2.
+ */
+#ifndef _ASM_S390X_FLOAT_H_
+#define _ASM_S390X_FLOAT_H_
+
+static inline void set_fpc(uint32_t fpc)
+{
+	asm volatile("	lfpc	%0\n" : : "Q"(fpc) );
+}
+
+static inline uint32_t get_fpc(void)
+{
+	uint32_t fpc;
+
+	asm volatile("	stfpc	%0\n" : "=Q"(fpc));
+
+	return fpc;
+}
+
+static inline uint8_t get_fpc_dxc()
+{
+	return get_fpc() >> 8;
+}
+
+static inline void set_fpc_dxc(uint8_t dxc)
+{
+	uint32_t fpc = get_fpc();
+
+	fpc = (fpc & ~0xff00) | ((uint32_t)dxc) << 8;
+
+	set_fpc(fpc);
+}
+
+static inline void afp_enable(void)
+{
+	ctl_set_bit(0, 63 - 45);
+}
+
+static inline void afp_disable(void)
+{
+	ctl_clear_bit(0, 63 - 45);
+}
+
+#endif
diff --git a/s390x/emulator.c b/s390x/emulator.c
index a8b4212..d01ecd3 100644
--- a/s390x/emulator.c
+++ b/s390x/emulator.c
@@ -13,6 +13,9 @@ 
 #include <libcflat.h>
 #include <asm/cpacf.h>
 #include <asm/interrupt.h>
+#include <asm/float.h>
+
+struct lowcore *lc = NULL;
 
 static inline void __test_spm_ipm(uint8_t cc, uint8_t key)
 {
@@ -257,6 +260,36 @@  static void test_prno(void)
 	__test_basic_cpacf_opcode(CPACF_PRNO);
 }
 
+static void test_dxc(void)
+{
+	/* DXC (0xff) is to be stored in LC and FPC on a trap (CGRT) with AFP */
+	lc->dxc_vxc = 0x12345678;
+	set_fpc_dxc(0);
+
+	expect_pgm_int();
+	asm volatile("	.insn	rrf,0xb9600000,%0,%0,8,0\n"
+		     : : "r"(0) : "memory");
+	check_pgm_int_code(PGM_INT_CODE_DATA);
+
+	report("dxc in LC", lc->dxc_vxc == 0xff);
+	report("dxc in FPC", get_fpc_dxc() == 0xff);
+
+	/* DXC (0xff) is to be stored in LC only on a trap (CGRT) without AFP */
+	lc->dxc_vxc = 0x12345678;
+	set_fpc_dxc(0);
+
+	expect_pgm_int();
+	/* temporarily disable AFP */
+	afp_disable();
+	asm volatile("	.insn	rrf,0xb9600000,%0,%0,8,0\n"
+		     : : "r"(0) : "memory");
+	afp_enable();
+	check_pgm_int_code(PGM_INT_CODE_DATA);
+
+	report("dxc in LC", lc->dxc_vxc == 0xff);
+	report("dxc not in FPC", get_fpc_dxc() == 0);
+}
+
 static struct {
 	const char *name;
 	void (*func)(void);
@@ -273,6 +306,7 @@  static struct {
 	{ "pcc", test_pcc },
 	{ "kmctr", test_kmctr },
 	{ "prno", test_prno },
+	{ "dxc", test_dxc },
 	{ NULL, NULL }
 };