[PATCH kvm-unit-tests v1 4/4] s390x: test if the DXC is correctly stored

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

Signed-off-by: David Hildenbrand <david@xxxxxxxxxx>
---
 lib/s390x/asm/float.h | 51 +++++++++++++++++++++++++++++++++++++++++++
 s390x/emulator.c      | 35 +++++++++++++++++++++++++++++
 2 files changed, 86 insertions(+)
 create mode 100644 lib/s390x/asm/float.h

diff --git a/lib/s390x/asm/float.h b/lib/s390x/asm/float.h
new file mode 100644
index 0000000..e994e15
--- /dev/null
+++ b/lib/s390x/asm/float.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2018 Red Hat Inc
+ *
+ * Authors:
+ *  David Hildenbrand <david@xxxxxxxxxx>
+ *
+ * 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" : : "m"(fpc) );
+}
+
+static inline uint32_t get_fpc(void)
+{
+	uint32_t fpc;
+
+	asm volatile("	stfpc	%0\n" : "=m"(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..f49c414 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,37 @@ 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 (CRT) 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 (CRT) 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 +307,7 @@ static struct {
 	{ "pcc", test_pcc },
 	{ "kmctr", test_kmctr },
 	{ "prno", test_prno },
+	{ "dxc", test_dxc },
 	{ NULL, NULL }
 };
 
-- 
2.17.1




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux