kvm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [kvm-unit-tests PATCH v2 0/2] s390x: program interrupt handler
@ 2017-05-31 12:39 David Hildenbrand
  2017-05-31 12:39 ` [kvm-unit-tests PATCH v2 1/2] s390x: generate asm offsets for the lowcore David Hildenbrand
  2017-05-31 12:39 ` [kvm-unit-tests PATCH v2 2/2] s390x: pgm interrupt handler and a way to test them David Hildenbrand
  0 siblings, 2 replies; 9+ messages in thread
From: David Hildenbrand @ 2017-05-31 12:39 UTC (permalink / raw)
  To: kvm
  Cc: Paolo Bonzini, Radim Krčmář, Thomas Huth, david,
	Christian Borntraeger

Add a program interrupt handler and two simple program interrupt tests.

The check for the ADRESSING exception will fail on
- TCG without "target/s390x: addressing exceptions are suppressing"
- Old KVM versions without 492d8642eaef ("KVM: s390: Forward PSW to next
  instruction for addressing exceptions")

v1 -> v2: (s390x: generate asm offsets for the lowcore)
- Added missing field (mcck extended save area)
- Dropped alignment attribute for naturally aligned struct

v1 -> v2: (pgm interrupt handler and a way to test them)
- Renamed everything from irq->int/interrupt to keep it consistent
- Use global lowcore variable struct lowcore *lc;
- Safe+restore fpr and fpc in interrupt handler
- Setup pgm int handler using mvc instruction
- Renamed received_pgm_irq to check_pgm_int_code() and moved "report"
  into "check_pgm_int_code()"
- Minor style + comment fixes

David Hildenbrand (2):
  s390x: generate asm offsets for the lowcore
  s390x: pgm interrupt handler and a way to test them

 lib/s390x/asm-offsets.c     |  74 ++++++++++++++++++++++
 lib/s390x/asm/arch_def.h    | 146 ++++++++++++++++++++++++++++++++++++++++++++
 lib/s390x/asm/asm-offsets.h |  10 +++
 lib/s390x/asm/interrupt.h   |  18 ++++++
 lib/s390x/interrupt.c       |  82 +++++++++++++++++++++++++
 s390x/Makefile              |  10 ++-
 s390x/cstart64.S            |  55 +++++++++++++++++
 s390x/selftest.c            |  13 ++++
 8 files changed, 407 insertions(+), 1 deletion(-)
 create mode 100644 lib/s390x/asm-offsets.c
 create mode 100644 lib/s390x/asm/arch_def.h
 create mode 100644 lib/s390x/asm/asm-offsets.h
 create mode 100644 lib/s390x/asm/interrupt.h
 create mode 100644 lib/s390x/interrupt.c

-- 
2.9.3

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

* [kvm-unit-tests PATCH v2 1/2] s390x: generate asm offsets for the lowcore
  2017-05-31 12:39 [kvm-unit-tests PATCH v2 0/2] s390x: program interrupt handler David Hildenbrand
@ 2017-05-31 12:39 ` David Hildenbrand
  2017-05-31 12:39 ` [kvm-unit-tests PATCH v2 2/2] s390x: pgm interrupt handler and a way to test them David Hildenbrand
  1 sibling, 0 replies; 9+ messages in thread
From: David Hildenbrand @ 2017-05-31 12:39 UTC (permalink / raw)
  To: kvm
  Cc: Paolo Bonzini, Radim Krčmář, Thomas Huth, david,
	Christian Borntraeger

Add the s390x psw and lowcore structs and generate asm offsets for lowcore
fields. Add all lowcore fields defined in the current PoP (z13).

Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
---
 lib/s390x/asm-offsets.c     | 71 ++++++++++++++++++++++++++++++++++++
 lib/s390x/asm/arch_def.h    | 87 +++++++++++++++++++++++++++++++++++++++++++++
 lib/s390x/asm/asm-offsets.h | 10 ++++++
 s390x/Makefile              |  8 ++++-
 4 files changed, 175 insertions(+), 1 deletion(-)
 create mode 100644 lib/s390x/asm-offsets.c
 create mode 100644 lib/s390x/asm/arch_def.h
 create mode 100644 lib/s390x/asm/asm-offsets.h

diff --git a/lib/s390x/asm-offsets.c b/lib/s390x/asm-offsets.c
new file mode 100644
index 0000000..1e8d5ce
--- /dev/null
+++ b/lib/s390x/asm-offsets.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2017 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.
+ */
+#include <libcflat.h>
+#include <kbuild.h>
+#include <asm/arch_def.h>
+
+int main(void)
+{
+	OFFSET(GEN_LC_EXT_INT_PARAM, lowcore, ext_int_param);
+	OFFSET(GEN_LC_CPU_ADDR, lowcore, cpu_addr);
+	OFFSET(GEN_LC_EXT_INT_CODE, lowcore, ext_int_code);
+	OFFSET(GEN_LC_SVC_INT_ID, lowcore, svc_int_id);
+	OFFSET(GEN_LC_SVC_INT_CODE, lowcore, svc_int_code);
+	OFFSET(GEN_LC_PGM_INT_ID, lowcore, pgm_int_id);
+	OFFSET(GEN_LC_PGM_INT_CODE, lowcore, pgm_int_code);
+	OFFSET(GEN_LC_DXC_VXC, lowcore, dxc_vxc);
+	OFFSET(GEN_LC_MON_CLASS_NB, lowcore, mon_class_nb);
+	OFFSET(GEN_LC_PER_CODE, lowcore, per_code);
+	OFFSET(GEN_LC_PER_ATMID, lowcore, per_atmid);
+	OFFSET(GEN_LC_PER_ADDR, lowcore, per_addr);
+	OFFSET(GEN_LC_EXC_ACC_ID, lowcore, exc_acc_id);
+	OFFSET(GEN_LC_PER_ACC_ID, lowcore, per_acc_id);
+	OFFSET(GEN_LC_OP_ACC_ID, lowcore, op_acc_id);
+	OFFSET(GEN_LC_ARCH_MODE_ID, lowcore, arch_mode_id);
+	OFFSET(GEN_LC_TRANS_EXC_ID, lowcore, trans_exc_id);
+	OFFSET(GEN_LC_MON_CODE, lowcore, mon_code);
+	OFFSET(GEN_LC_SUBSYS_ID_WORD, lowcore, subsys_id_word);
+	OFFSET(GEN_LC_IO_INT_PARAM, lowcore, io_int_param);
+	OFFSET(GEN_LC_IO_INT_WORD, lowcore, io_int_word);
+	OFFSET(GEN_LC_STFL, lowcore, stfl);
+	OFFSET(GEN_LC_MCCK_INT_CODE, lowcore, mcck_int_code);
+	OFFSET(GEN_LC_EXT_DAMAGE_CODE, lowcore, ext_damage_code);
+	OFFSET(GEN_LC_FAILING_STORAGE_ADDR, lowcore, failing_storage_addr);
+	OFFSET(GEN_LC_EMON_CA_ORIGIN, lowcore, emon_ca_origin);
+	OFFSET(GEN_LC_EMON_CA_SIZE, lowcore, emon_ca_size);
+	OFFSET(GEN_LC_EMON_EXC_COUNT, lowcore, emon_exc_count);
+	OFFSET(GEN_LC_BREAKING_EVENT_ADDR, lowcore, breaking_event_addr);
+	OFFSET(GEN_LC_RESTART_OLD_PSW, lowcore, restart_old_psw);
+	OFFSET(GEN_LC_EXT_OLD_PSW, lowcore, ext_old_psw);
+	OFFSET(GEN_LC_SVC_OLD_PSW, lowcore, svc_old_psw);
+	OFFSET(GEN_LC_PGM_OLD_PSW, lowcore, pgm_old_psw);
+	OFFSET(GEN_LC_MCCK_OLD_PSW, lowcore, mcck_old_psw);
+	OFFSET(GEN_LC_IO_OLD_PSW, lowcore, io_old_psw);
+	OFFSET(GEN_LC_RESTART_NEW_PSW, lowcore, restart_new_psw);
+	OFFSET(GEN_LC_EXT_NEW_PSW, lowcore, ext_new_psw);
+	OFFSET(GEN_LC_SVC_NEW_PSW, lowcore, svc_new_psw);
+	OFFSET(GEN_LC_PGM_NEW_PSW, lowcore, pgm_new_psw);
+	OFFSET(GEN_LC_MCCK_NEW_PSW, lowcore, mcck_new_psw);
+	OFFSET(GEN_LC_IO_NEW_PSW, lowcore, io_new_psw);
+	OFFSET(GEN_LC_MCCK_EXT_SA_ADDR, lowcore, mcck_ext_sa_addr);
+	OFFSET(GEN_LC_FPRS_SA, lowcore, fprs_sa);
+	OFFSET(GEN_LC_GRS_SA, lowcore, grs_sa);
+	OFFSET(GEN_LC_PSW_SA, lowcore, psw_sa);
+	OFFSET(GEN_LC_PREFIX_SA, lowcore, prefix_sa);
+	OFFSET(GEN_LC_FPC_SA, lowcore, fpc_sa);
+	OFFSET(GEN_LC_TOD_PR_SA, lowcore, tod_pr_sa);
+	OFFSET(GEN_LC_CPUTM_SA, lowcore, cputm_sa);
+	OFFSET(GEN_LC_CC_SA, lowcore, cc_sa);
+	OFFSET(GEN_LC_ARS_SA, lowcore, ars_sa);
+	OFFSET(GEN_LC_CRS_SA, lowcore, crs_sa);
+	OFFSET(GEN_LC_PGM_INT_TDB, lowcore, pgm_int_tdb);
+
+	return 0;
+}
diff --git a/lib/s390x/asm/arch_def.h b/lib/s390x/asm/arch_def.h
new file mode 100644
index 0000000..efa7f12
--- /dev/null
+++ b/lib/s390x/asm/arch_def.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2017 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_ARCH_DEF_H_
+#define _ASM_S390X_ARCH_DEF_H_
+
+struct psw {
+	uint64_t	mask;
+	uint64_t	addr;
+};
+
+struct lowcore {
+	uint8_t		pad_0x0000[0x0080 - 0x0000];	/* 0x0000 */
+	uint32_t	ext_int_param;			/* 0x0080 */
+	uint16_t	cpu_addr;			/* 0x0084 */
+	uint16_t	ext_int_code;			/* 0x0086 */
+	uint16_t	svc_int_id;			/* 0x0088 */
+	uint16_t	svc_int_code;			/* 0x008a */
+	uint16_t	pgm_int_id;			/* 0x008c */
+	uint16_t	pgm_int_code;			/* 0x008e */
+	uint32_t	dxc_vxc;			/* 0x0090 */
+	uint16_t	mon_class_nb;			/* 0x0094 */
+	uint8_t		per_code;			/* 0x0096 */
+	uint8_t		per_atmid;			/* 0x0097 */
+	uint64_t	per_addr;			/* 0x0098 */
+	uint8_t		exc_acc_id;			/* 0x00a0 */
+	uint8_t		per_acc_id;			/* 0x00a1 */
+	uint8_t		op_acc_id;			/* 0x00a2 */
+	uint8_t		arch_mode_id;			/* 0x00a3 */
+	uint8_t		pad_0x00a4[0x00a8 - 0x00a4];	/* 0x00a4 */
+	uint64_t	trans_exc_id;			/* 0x00a8 */
+	uint64_t	mon_code;			/* 0x00b0 */
+	uint32_t	subsys_id_word;			/* 0x00b8 */
+	uint32_t	io_int_param;			/* 0x00bc */
+	uint32_t	io_int_word;			/* 0x00c0 */
+	uint8_t		pad_0x00c4[0x00c8 - 0x00c4];	/* 0x00c4 */
+	uint32_t	stfl;				/* 0x00c8 */
+	uint8_t		pad_0x00cc[0x00e8 - 0x00cc];	/* 0x00cc */
+	uint64_t	mcck_int_code;			/* 0x00e8 */
+	uint8_t		pad_0x00f0[0x00f4 - 0x00f0];	/* 0x00f0 */
+	uint32_t	ext_damage_code;		/* 0x00f4 */
+	uint64_t	failing_storage_addr;		/* 0x00f8 */
+	uint64_t	emon_ca_origin;			/* 0x0100 */
+	uint32_t	emon_ca_size;			/* 0x0108 */
+	uint32_t	emon_exc_count;			/* 0x010c */
+	uint64_t	breaking_event_addr;		/* 0x0110 */
+	uint8_t		pad_0x0118[0x0120 - 0x0118];	/* 0x0118 */
+	struct psw	restart_old_psw;		/* 0x0120 */
+	struct psw	ext_old_psw;			/* 0x0130 */
+	struct psw	svc_old_psw;			/* 0x0140 */
+	struct psw	pgm_old_psw;			/* 0x0150 */
+	struct psw	mcck_old_psw;			/* 0x0160 */
+	struct psw	io_old_psw;			/* 0x0170 */
+	uint8_t		pad_0x0180[0x01a0 - 0x0180];	/* 0x0180 */
+	struct psw	restart_new_psw;		/* 0x01a0 */
+	struct psw	ext_new_psw;			/* 0x01b0 */
+	struct psw	svc_new_psw;			/* 0x01c0 */
+	struct psw	pgm_new_psw;			/* 0x01d0 */
+	struct psw	mcck_new_psw;			/* 0x01e0 */
+	struct psw	io_new_psw;			/* 0x01f0 */
+	uint8_t		pad_0x0200[0x11b0 - 0x0200];	/* 0x0200 */
+	uint64_t	mcck_ext_sa_addr;		/* 0x11b0 */
+	uint8_t		pad_0x11b8[0x1200 - 0x11b8];	/* 0x11b8 */
+	uint64_t	fprs_sa[16];			/* 0x1200 */
+	uint64_t	grs_sa[16];			/* 0x1280 */
+	struct psw	psw_sa;				/* 0x1300 */
+	uint8_t		pad_0x1310[0x1318 - 0x1310];	/* 0x1310 */
+	uint32_t	prefix_sa;			/* 0x1318 */
+	uint32_t	fpc_sa;				/* 0x131c */
+	uint8_t		pad_0x1320[0x1324 - 0x1320];	/* 0x1320 */
+	uint32_t	tod_pr_sa;			/* 0x1324 */
+	uint64_t	cputm_sa;			/* 0x1328 */
+	uint64_t	cc_sa;				/* 0x1330 */
+	uint8_t		pad_0x1338[0x1340 - 0x1338];	/* 0x1338 */
+	uint32_t	ars_sa[16];			/* 0x1340 */
+	uint64_t	crs_sa[16];			/* 0x1380 */
+	uint8_t		pad_0x1400[0x1800 - 0x1400];	/* 0x1400 */
+	uint8_t		pgm_int_tdb[0x1900 - 0x1800];	/* 0x1800 */
+} __attribute__ ((__packed__));
+
+#endif
diff --git a/lib/s390x/asm/asm-offsets.h b/lib/s390x/asm/asm-offsets.h
new file mode 100644
index 0000000..a6d7af8
--- /dev/null
+++ b/lib/s390x/asm/asm-offsets.h
@@ -0,0 +1,10 @@
+/*
+ * Copyright (c) 2017 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.
+ */
+#include <generated/asm-offsets.h>
diff --git a/s390x/Makefile b/s390x/Makefile
index e80add0..4e4b94a 100644
--- a/s390x/Makefile
+++ b/s390x/Makefile
@@ -15,6 +15,9 @@ LDFLAGS += -nostdlib
 # We want to keep intermediate files
 .PRECIOUS: %.o
 
+asm-offsets = lib/$(ARCH)/asm-offsets.h
+include $(SRCDIR)/scripts/asm-offsets.mak
+
 cflatobjs += lib/util.o
 cflatobjs += lib/alloc.o
 cflatobjs += lib/s390x/io.o
@@ -33,5 +36,8 @@ FLATLIBS = $(libcflat)
 		$(filter %.o, $^) $(FLATLIBS) $(@:.elf=.aux.o)
 	$(RM) $(@:.elf=.aux.o)
 
-arch_clean:
+arch_clean: asm_offsets_clean
 	$(RM) $(TEST_DIR)/*.{o,elf} $(TEST_DIR)/.*.d lib/s390x/.*.d
+
+generated-files = $(asm-offsets)
+$(test_cases:.elf=.o) $(cstart.o) $(cflatobjs): $(generated-files)
-- 
2.9.3

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

* [kvm-unit-tests PATCH v2 2/2] s390x: pgm interrupt handler and a way to test them
  2017-05-31 12:39 [kvm-unit-tests PATCH v2 0/2] s390x: program interrupt handler David Hildenbrand
  2017-05-31 12:39 ` [kvm-unit-tests PATCH v2 1/2] s390x: generate asm offsets for the lowcore David Hildenbrand
@ 2017-05-31 12:39 ` David Hildenbrand
  2017-05-31 12:51   ` Paolo Bonzini
  2017-05-31 13:22   ` Thomas Huth
  1 sibling, 2 replies; 9+ messages in thread
From: David Hildenbrand @ 2017-05-31 12:39 UTC (permalink / raw)
  To: kvm
  Cc: Paolo Bonzini, Radim Krčmář, Thomas Huth, david,
	Christian Borntraeger

The program interrupt handler will detect unexpected program interrupts and
allow to expect + verify program interrupts for testing purposes.

We need "-fno-delete-null-pointer-checks", otherwise trying to access the
lowcore at address 0 makes GCC generate very weird code.

Add two tests to test for simple operation and addressing exceptions.

Signed-off-by: David Hildenbrand <david@redhat.com>
---
 lib/s390x/asm-offsets.c   |  3 ++
 lib/s390x/asm/arch_def.h  | 61 ++++++++++++++++++++++++++++++++++-
 lib/s390x/asm/interrupt.h | 18 +++++++++++
 lib/s390x/interrupt.c     | 82 +++++++++++++++++++++++++++++++++++++++++++++++
 s390x/Makefile            |  2 ++
 s390x/cstart64.S          | 55 +++++++++++++++++++++++++++++++
 s390x/selftest.c          | 13 ++++++++
 7 files changed, 233 insertions(+), 1 deletion(-)
 create mode 100644 lib/s390x/asm/interrupt.h
 create mode 100644 lib/s390x/interrupt.c

diff --git a/lib/s390x/asm-offsets.c b/lib/s390x/asm-offsets.c
index 1e8d5ce..f1012c6 100644
--- a/lib/s390x/asm-offsets.c
+++ b/lib/s390x/asm-offsets.c
@@ -54,6 +54,9 @@ int main(void)
 	OFFSET(GEN_LC_PGM_NEW_PSW, lowcore, pgm_new_psw);
 	OFFSET(GEN_LC_MCCK_NEW_PSW, lowcore, mcck_new_psw);
 	OFFSET(GEN_LC_IO_NEW_PSW, lowcore, io_new_psw);
+	OFFSET(GEN_LC_SW_INT_GRS, lowcore, sw_int_grs);
+	OFFSET(GEN_LC_SW_INT_FPRS, lowcore, sw_int_fprs);
+	OFFSET(GEN_LC_SW_INT_FPC, lowcore, sw_int_fpc);
 	OFFSET(GEN_LC_MCCK_EXT_SA_ADDR, lowcore, mcck_ext_sa_addr);
 	OFFSET(GEN_LC_FPRS_SA, lowcore, fprs_sa);
 	OFFSET(GEN_LC_GRS_SA, lowcore, grs_sa);
diff --git a/lib/s390x/asm/arch_def.h b/lib/s390x/asm/arch_def.h
index efa7f12..07d467e 100644
--- a/lib/s390x/asm/arch_def.h
+++ b/lib/s390x/asm/arch_def.h
@@ -64,7 +64,11 @@ struct lowcore {
 	struct psw	pgm_new_psw;			/* 0x01d0 */
 	struct psw	mcck_new_psw;			/* 0x01e0 */
 	struct psw	io_new_psw;			/* 0x01f0 */
-	uint8_t		pad_0x0200[0x11b0 - 0x0200];	/* 0x0200 */
+	/* sw definition: save area for registers in interrupt handlers */
+	uint64_t	sw_int_grs[16];			/* 0x0200 */
+	uint64_t	sw_int_fprs[16];		/* 0x0280 */
+	uint32_t	sw_int_fpc;			/* 0x0300 */
+	uint8_t		pad_0x0304[0x11b0 - 0x0304];	/* 0x0304 */
 	uint64_t	mcck_ext_sa_addr;		/* 0x11b0 */
 	uint8_t		pad_0x11b8[0x1200 - 0x11b8];	/* 0x11b8 */
 	uint64_t	fprs_sa[16];			/* 0x1200 */
@@ -84,4 +88,59 @@ struct lowcore {
 	uint8_t		pgm_int_tdb[0x1900 - 0x1800];	/* 0x1800 */
 } __attribute__ ((__packed__));
 
+#define PGM_INT_CODE_OPERATION			0x01
+#define PGM_INT_CODE_PRIVILEGED_OPERATION	0x02
+#define PGM_INT_CODE_EXECUTE			0x03
+#define PGM_INT_CODE_PROTECTION			0x04
+#define PGM_INT_CODE_ADDRESSING			0x05
+#define PGM_INT_CODE_SPECIFICATION		0x06
+#define PGM_INT_CODE_DATA			0x07
+#define PGM_INT_CODE_FIXED_POINT_OVERFLOW	0x08
+#define PGM_INT_CODE_FIXED_POINT_DIVIDE		0x09
+#define PGM_INT_CODE_DECIMAL_OVERFLOW		0x0a
+#define PGM_INT_CODE_DECIMAL_DIVIDE		0x0b
+#define PGM_INT_CODE_HFP_EXPONENT_OVERFLOW	0x0c
+#define PGM_INT_CODE_HFP_EXPONENT_UNDERFLOW	0x0d
+#define PGM_INT_CODE_HFP_SIGNIFICANCE		0x0e
+#define PGM_INT_CODE_HFP_DIVIDE			0x0f
+#define PGM_INT_CODE_SEGMENT_TRANSLATION	0x10
+#define PGM_INT_CODE_PAGE_TRANSLATION		0x11
+#define PGM_INT_CODE_TRANSLATION_SPEC		0x12
+#define PGM_INT_CODE_SPECIAL_OPERATION		0x13
+#define PGM_INT_CODE_OPERAND			0x15
+#define PGM_INT_CODE_TRACE_TABLE		0x16
+#define PGM_INT_CODE_VECTOR_PROCESSING		0x1b
+#define PGM_INT_CODE_SPACE_SWITCH_EVENT		0x1c
+#define PGM_INT_CODE_HFP_SQUARE_ROOT		0x1d
+#define PGM_INT_CODE_PC_TRANSLATION_SPEC	0x1f
+#define PGM_INT_CODE_AFX_TRANSLATION		0x20
+#define PGM_INT_CODE_ASX_TRANSLATION		0x21
+#define PGM_INT_CODE_LX_TRANSLATION		0x22
+#define PGM_INT_CODE_EX_TRANSLATION		0x23
+#define PGM_INT_CODE_PRIMARY_AUTHORITY		0x24
+#define PGM_INT_CODE_SECONDARY_AUTHORITY	0x25
+#define PGM_INT_CODE_LFX_TRANSLATION		0x26
+#define PGM_INT_CODE_LSX_TRANSLATION		0x27
+#define PGM_INT_CODE_ALET_SPECIFICATION		0x28
+#define PGM_INT_CODE_ALEN_TRANSLATION		0x29
+#define PGM_INT_CODE_ALE_SEQUENCE		0x2a
+#define PGM_INT_CODE_ASTE_VALIDITY		0x2b
+#define PGM_INT_CODE_ASTE_SEQUENCE		0x2c
+#define PGM_INT_CODE_EXTENDED_AUTHORITY		0x2d
+#define PGM_INT_CODE_LSTE_SEQUENCE		0x2e
+#define PGM_INT_CODE_ASTE_INSTANCE		0x2f
+#define PGM_INT_CODE_STACK_FULL			0x30
+#define PGM_INT_CODE_STACK_EMPTY		0x31
+#define PGM_INT_CODE_STACK_SPECIFICATION	0x32
+#define PGM_INT_CODE_STACK_TYPE			0x33
+#define PGM_INT_CODE_STACK_OPERATION		0x34
+#define PGM_INT_CODE_ASCE_TYPE			0x38
+#define PGM_INT_CODE_REGION_FIRST_TRANS		0x39
+#define PGM_INT_CODE_REGION_SECOND_TRANS	0x3a
+#define PGM_INT_CODE_REGION_THIRD_TRANS		0x3b
+#define PGM_INT_CODE_MONITOR_EVENT		0x40
+#define PGM_INT_CODE_PER			0x80
+#define PGM_INT_CODE_CRYPTO_OPERATION		0x119
+#define PGM_INT_CODE_TX_ABORTED_EVENT		0x200
+
 #endif
diff --git a/lib/s390x/asm/interrupt.h b/lib/s390x/asm/interrupt.h
new file mode 100644
index 0000000..383d312
--- /dev/null
+++ b/lib/s390x/asm/interrupt.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2017 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 _ASMS390X_IRQ_H_
+#define _ASMS390X_IRQ_H_
+#include <asm/arch_def.h>
+
+void handle_pgm_int(void);
+void expect_pgm_int(void);
+void check_pgm_int_code(uint16_t code);
+
+#endif
diff --git a/lib/s390x/interrupt.c b/lib/s390x/interrupt.c
new file mode 100644
index 0000000..8d861a2
--- /dev/null
+++ b/lib/s390x/interrupt.c
@@ -0,0 +1,82 @@
+/*
+ * s390x interrupt handling
+ *
+ * Copyright (c) 2017 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.
+ */
+#include <libcflat.h>
+#include <asm/interrupt.h>
+#include <asm/barrier.h>
+
+static bool pgm_int_expected;
+static struct lowcore *lc;
+
+void expect_pgm_int(void)
+{
+	pgm_int_expected = true;
+	lc->pgm_int_code = 0;
+	mb();
+}
+
+void check_pgm_int_code(uint16_t code)
+{
+	mb();
+	report("Program interrupt: expected(%d) == received(%d)",
+	       code == lc->pgm_int_code, code, lc->pgm_int_code);
+}
+
+static void fixup_pgm_int(void)
+{
+	switch (lc->pgm_int_code) {
+	case PGM_INT_CODE_SEGMENT_TRANSLATION:
+	case PGM_INT_CODE_PAGE_TRANSLATION:
+	case PGM_INT_CODE_TRACE_TABLE:
+	case PGM_INT_CODE_AFX_TRANSLATION:
+	case PGM_INT_CODE_ASX_TRANSLATION:
+	case PGM_INT_CODE_LX_TRANSLATION:
+	case PGM_INT_CODE_EX_TRANSLATION:
+	case PGM_INT_CODE_PRIMARY_AUTHORITY:
+	case PGM_INT_CODE_SECONDARY_AUTHORITY:
+	case PGM_INT_CODE_LFX_TRANSLATION:
+	case PGM_INT_CODE_LSX_TRANSLATION:
+	case PGM_INT_CODE_ALEN_TRANSLATION:
+	case PGM_INT_CODE_ALE_SEQUENCE:
+	case PGM_INT_CODE_ASTE_VALIDITY:
+	case PGM_INT_CODE_ASTE_SEQUENCE:
+	case PGM_INT_CODE_EXTENDED_AUTHORITY:
+	case PGM_INT_CODE_LSTE_SEQUENCE:
+	case PGM_INT_CODE_ASTE_INSTANCE:
+	case PGM_INT_CODE_STACK_FULL:
+	case PGM_INT_CODE_STACK_EMPTY:
+	case PGM_INT_CODE_STACK_SPECIFICATION:
+	case PGM_INT_CODE_STACK_TYPE:
+	case PGM_INT_CODE_STACK_OPERATION:
+	case PGM_INT_CODE_ASCE_TYPE:
+	case PGM_INT_CODE_REGION_FIRST_TRANS:
+	case PGM_INT_CODE_REGION_SECOND_TRANS:
+	case PGM_INT_CODE_REGION_THIRD_TRANS:
+	case PGM_INT_CODE_PER:
+	case PGM_INT_CODE_CRYPTO_OPERATION:
+		/* The interrupt was nullified, the old PSW points at the
+		 * responsible instruction. Forward the PSW so we don't loop.
+		 */
+		lc->pgm_old_psw.addr += lc->pgm_int_id;
+	}
+	/* suppressed/terminated/completed point already at the next address */
+}
+
+void handle_pgm_int(void)
+{
+	if (!pgm_int_expected)
+		report_abort("Unexpected program interrupt: %d at %#lx, ilen %d\n",
+			     lc->pgm_int_code, lc->pgm_old_psw.addr,
+			     lc->pgm_int_id);
+
+	pgm_int_expected = false;
+	fixup_pgm_int();
+}
diff --git a/s390x/Makefile b/s390x/Makefile
index 4e4b94a..b48f8ab 100644
--- a/s390x/Makefile
+++ b/s390x/Makefile
@@ -10,6 +10,7 @@ CFLAGS += -Wextra
 CFLAGS += -I $(SRCDIR)/lib
 CFLAGS += -O2
 CFLAGS += -march=z900
+CFLAGS += -fno-delete-null-pointer-checks
 LDFLAGS += -nostdlib
 
 # We want to keep intermediate files
@@ -23,6 +24,7 @@ cflatobjs += lib/alloc.o
 cflatobjs += lib/s390x/io.o
 cflatobjs += lib/s390x/stack.o
 cflatobjs += lib/s390x/sclp-ascii.o
+cflatobjs += lib/s390x/interrupt.o
 
 OBJDIRS += lib/s390x
 
diff --git a/s390x/cstart64.S b/s390x/cstart64.S
index 28cd59d..4d0c877 100644
--- a/s390x/cstart64.S
+++ b/s390x/cstart64.S
@@ -10,6 +10,8 @@
  * 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.
  */
+#include <asm/asm-offsets.h>
+
 .section .init
 
 /* entry point - for KVM + TCG we directly start in 64 bit mode */
@@ -21,6 +23,10 @@ start:
 	larl	%r1, initital_psw
 	lpswe	0(%r1)
 init_psw_cont:
+	/* setup pgm interrupt handler */
+	larl	%r1, pgm_int_psw
+	mvc	GEN_LC_PGM_NEW_PSW(16), 0(%r1)
+	/* setup cr0, enabling e.g. AFP-register control */
 	larl	%r1, initital_cr0
 	lctlg	%c0, %c0, 0(%r1)
 	/* call setup() */
@@ -36,9 +42,58 @@ init_psw_cont:
 	/* call exit() */
 	j exit
 
+pgm_int:
+	/* save grs 0-15 */
+	stmg	%r0, %r15, GEN_LC_SW_INT_GRS
+	/* save fprs 0-15 + fpc */
+	larl	%r1, GEN_LC_SW_INT_FPRS
+	std	%f0, 0(%r1)
+	std	%f1, 8(%r1)
+	std	%f2, 16(%r1)
+	std	%f3, 24(%r1)
+	std	%f4, 32(%r1)
+	std	%f5, 40(%r1)
+	std	%f6, 48(%r1)
+	std	%f7, 56(%r1)
+	std	%f8, 64(%r1)
+	std	%f9, 72(%r1)
+	std	%f10, 80(%r1)
+	std	%f11, 88(%r1)
+	std	%f12, 96(%r1)
+	std	%f13, 104(%r1)
+	std	%f14, 112(%r1)
+	std	%f15, 120(%r1)
+	stfpc	GEN_LC_SW_INT_FPC
+	/* call our c handler */
+	brasl	%r14, handle_pgm_int
+	/* restore fprs 0-15 + fpc */
+	larl	%r1, GEN_LC_SW_INT_FPRS
+	ld	%f0, 0(%r1)
+	ld	%f1, 8(%r1)
+	ld	%f2, 16(%r1)
+	ld	%f3, 24(%r1)
+	ld	%f4, 32(%r1)
+	ld	%f5, 40(%r1)
+	ld	%f6, 48(%r1)
+	ld	%f7, 56(%r1)
+	ld	%f8, 64(%r1)
+	ld	%f9, 72(%r1)
+	ld	%f10, 80(%r1)
+	ld	%f11, 88(%r1)
+	ld	%f12, 96(%r1)
+	ld	%f13, 104(%r1)
+	ld	%f14, 112(%r1)
+	ld	%f15, 120(%r1)
+	lfpc	GEN_LC_SW_INT_FPC
+	/* restore grs 0-15 */
+	lmg	%r0, %r15, GEN_LC_SW_INT_GRS
+	lpswe	GEN_LC_PGM_OLD_PSW
+
 	.align	8
 initital_psw:
 	.quad	0x0000000180000000, init_psw_cont
+pgm_int_psw:
+	.quad	0x0000000180000000, pgm_int
 initital_cr0:
 	/* enable AFP-register control, so FP regs (+BFP instr) can be used */
 	.quad	0x0000000000040000
diff --git a/s390x/selftest.c b/s390x/selftest.c
index 4558e47..ca94158 100644
--- a/s390x/selftest.c
+++ b/s390x/selftest.c
@@ -10,6 +10,7 @@
  */
 #include <libcflat.h>
 #include <util.h>
+#include <asm/interrupt.h>
 
 static void test_fp(void)
 {
@@ -25,6 +26,17 @@ static void test_fp(void)
 	report("3.0/2.0 == 1.5", c == 1.5);
 }
 
+static void test_pgm_int(void)
+{
+	expect_pgm_int();
+	asm volatile("	.insn e,0x0001"); /* used for SW breakpoints in QEMU */
+	check_pgm_int_code(PGM_INT_CODE_OPERATION);
+
+	expect_pgm_int();
+	*((unsigned int*)-1) = 1;
+	check_pgm_int_code(PGM_INT_CODE_ADDRESSING);
+}
+
 int main(int argc, char**argv)
 {
 	report_prefix_push("selftest");
@@ -36,6 +48,7 @@ int main(int argc, char**argv)
 	report("argv[2] == 123", !strcmp(argv[2], "123"));
 
 	test_fp();
+	test_pgm_int();
 
 	return report_summary();
 }
-- 
2.9.3

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

* Re: [kvm-unit-tests PATCH v2 2/2] s390x: pgm interrupt handler and a way to test them
  2017-05-31 12:39 ` [kvm-unit-tests PATCH v2 2/2] s390x: pgm interrupt handler and a way to test them David Hildenbrand
@ 2017-05-31 12:51   ` Paolo Bonzini
  2017-05-31 13:25     ` Thomas Huth
  2017-05-31 13:26     ` David Hildenbrand
  2017-05-31 13:22   ` Thomas Huth
  1 sibling, 2 replies; 9+ messages in thread
From: Paolo Bonzini @ 2017-05-31 12:51 UTC (permalink / raw)
  To: David Hildenbrand, kvm
  Cc: Radim Krčmář, Thomas Huth, Christian Borntraeger



On 31/05/2017 14:39, David Hildenbrand wrote:
> +	expect_pgm_int();
> +	*((unsigned int*)-1) = 1;
> +	check_pgm_int_code(PGM_INT_CODE_ADDRESSING);

QEMU gets

ABORT: selftest: Unexpected program interrupt: 5 at 0x12b4c, ilen 4

It seems that QEMU doesn't point the PSW at the next instruction:

	IN: main
	0x0000000000012b44:  lghi       %r1,-1
	0x0000000000012b48:  lhi        %r3,1
	0x0000000000012b4c:  st %r3,0(%r1)
	0x0000000000012b50:  lghi       %r2,5
	0x0000000000012b54:  brasl      %r14,0x128e8
	0x0000000000012b4c:  st %r3,0(%r1)
	0x0000000000012b50:  lghi       %r2,5
	0x0000000000012b54:  brasl      %r14,0x128e8     # this is expect_pgm_int

	Trace 0x7f5ff6c7f520 [0: 0000000000012b44] main
	Trace 0x7f5ff6c7bc20 [0: 000000000001004e] 
	Trace 0x7f5ff6c7c960 [0: 0000000000012918] handle_pgm_int
	Trace 0x7f5ff6c7d280 [0: 00000000000100a4] 

and now it gets another program interrupt:

	IN: main
	0x0000000000012b4c:  st %r3,0(%r1)
	0x0000000000012b50:  lghi       %r2,5
	0x0000000000012b54:  brasl      %r14,0x128e8

	Trace 0x7f5ff6c7f600 [0: 0000000000012b4c] main
	Trace 0x7f5ff6c7bc20 [0: 000000000001004e] 
	Trace 0x7f5ff6c7c960 [0: 0000000000012918] handle_pgm_int

Thanks,

Paolo

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

* Re: [kvm-unit-tests PATCH v2 2/2] s390x: pgm interrupt handler and a way to test them
  2017-05-31 12:39 ` [kvm-unit-tests PATCH v2 2/2] s390x: pgm interrupt handler and a way to test them David Hildenbrand
  2017-05-31 12:51   ` Paolo Bonzini
@ 2017-05-31 13:22   ` Thomas Huth
  2017-05-31 13:30     ` David Hildenbrand
  1 sibling, 1 reply; 9+ messages in thread
From: Thomas Huth @ 2017-05-31 13:22 UTC (permalink / raw)
  To: David Hildenbrand, kvm
  Cc: Paolo Bonzini, Radim Krčmář, Christian Borntraeger

On 31.05.2017 14:39, David Hildenbrand wrote:
> The program interrupt handler will detect unexpected program interrupts and
> allow to expect + verify program interrupts for testing purposes.
> 
> We need "-fno-delete-null-pointer-checks", otherwise trying to access the
> lowcore at address 0 makes GCC generate very weird code.
> 
> Add two tests to test for simple operation and addressing exceptions.
> 
> Signed-off-by: David Hildenbrand <david@redhat.com>
> ---
[...]
> diff --git a/lib/s390x/interrupt.c b/lib/s390x/interrupt.c
> new file mode 100644
> index 0000000..8d861a2
> --- /dev/null
> +++ b/lib/s390x/interrupt.c
> @@ -0,0 +1,82 @@
> +/*
> + * s390x interrupt handling
> + *
> + * Copyright (c) 2017 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.
> + */
> +#include <libcflat.h>
> +#include <asm/interrupt.h>
> +#include <asm/barrier.h>
> +
> +static bool pgm_int_expected;
> +static struct lowcore *lc;

Cosmetic suggestion:
Maybe make it "static struct lowcore const *lc = 0" to be more explicit?

Apart from that, patch looks fine to me now, so with or without that change:

Reviewed-by: Thomas Huth <thuth@redhat.com>

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

* Re: [kvm-unit-tests PATCH v2 2/2] s390x: pgm interrupt handler and a way to test them
  2017-05-31 12:51   ` Paolo Bonzini
@ 2017-05-31 13:25     ` Thomas Huth
  2017-05-31 14:23       ` Paolo Bonzini
  2017-05-31 13:26     ` David Hildenbrand
  1 sibling, 1 reply; 9+ messages in thread
From: Thomas Huth @ 2017-05-31 13:25 UTC (permalink / raw)
  To: Paolo Bonzini, David Hildenbrand, kvm
  Cc: Radim Krčmář, Christian Borntraeger

On 31.05.2017 14:51, Paolo Bonzini wrote:
> 
> 
> On 31/05/2017 14:39, David Hildenbrand wrote:
>> +	expect_pgm_int();
>> +	*((unsigned int*)-1) = 1;
>> +	check_pgm_int_code(PGM_INT_CODE_ADDRESSING);
> 
> QEMU gets
> 
> ABORT: selftest: Unexpected program interrupt: 5 at 0x12b4c, ilen 4
> 
> It seems that QEMU doesn't point the PSW at the next instruction

David mentioned it in the cover letter ... you likely need this patch
here first:

http://patchwork.ozlabs.org/patch/768173/

 Thomas

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

* Re: [kvm-unit-tests PATCH v2 2/2] s390x: pgm interrupt handler and a way to test them
  2017-05-31 12:51   ` Paolo Bonzini
  2017-05-31 13:25     ` Thomas Huth
@ 2017-05-31 13:26     ` David Hildenbrand
  1 sibling, 0 replies; 9+ messages in thread
From: David Hildenbrand @ 2017-05-31 13:26 UTC (permalink / raw)
  To: Paolo Bonzini, kvm
  Cc: Radim Krčmář, Thomas Huth, Christian Borntraeger

On 31.05.2017 14:51, Paolo Bonzini wrote:
> 
> 
> On 31/05/2017 14:39, David Hildenbrand wrote:
>> +	expect_pgm_int();
>> +	*((unsigned int*)-1) = 1;
>> +	check_pgm_int_code(PGM_INT_CODE_ADDRESSING);
> 
> QEMU gets
> 
> ABORT: selftest: Unexpected program interrupt: 5 at 0x12b4c, ilen 4
> 
> It seems that QEMU doesn't point the PSW at the next instruction:
> 
> 	IN: main
> 	0x0000000000012b44:  lghi       %r1,-1
> 	0x0000000000012b48:  lhi        %r3,1
> 	0x0000000000012b4c:  st %r3,0(%r1)
> 	0x0000000000012b50:  lghi       %r2,5
> 	0x0000000000012b54:  brasl      %r14,0x128e8
> 	0x0000000000012b4c:  st %r3,0(%r1)
> 	0x0000000000012b50:  lghi       %r2,5
> 	0x0000000000012b54:  brasl      %r14,0x128e8     # this is expect_pgm_int
> 
> 	Trace 0x7f5ff6c7f520 [0: 0000000000012b44] main
> 	Trace 0x7f5ff6c7bc20 [0: 000000000001004e] 
> 	Trace 0x7f5ff6c7c960 [0: 0000000000012918] handle_pgm_int
> 	Trace 0x7f5ff6c7d280 [0: 00000000000100a4] 
> 
> and now it gets another program interrupt:

Exactly, the emulator doesn't properly forward the PSW.

> 
> 	IN: main
> 	0x0000000000012b4c:  st %r3,0(%r1)
> 	0x0000000000012b50:  lghi       %r2,5
> 	0x0000000000012b54:  brasl      %r14,0x128e8
> 
> 	Trace 0x7f5ff6c7f600 [0: 0000000000012b4c] main
> 	Trace 0x7f5ff6c7bc20 [0: 000000000001004e] 
> 	Trace 0x7f5ff6c7c960 [0: 0000000000012918] handle_pgm_int
> 
> Thanks,
> 
> Paolo
> 

Yes, known problem as described in the cover letter. Happens with
current TCG and old KVM. Patch for TCG is on the list.

Thanks for testing!

-- 

Thanks,

David

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

* Re: [kvm-unit-tests PATCH v2 2/2] s390x: pgm interrupt handler and a way to test them
  2017-05-31 13:22   ` Thomas Huth
@ 2017-05-31 13:30     ` David Hildenbrand
  0 siblings, 0 replies; 9+ messages in thread
From: David Hildenbrand @ 2017-05-31 13:30 UTC (permalink / raw)
  To: Thomas Huth, kvm
  Cc: Paolo Bonzini, Radim Krčmář, Christian Borntraeger

On 31.05.2017 15:22, Thomas Huth wrote:
> On 31.05.2017 14:39, David Hildenbrand wrote:
>> The program interrupt handler will detect unexpected program interrupts and
>> allow to expect + verify program interrupts for testing purposes.
>>
>> We need "-fno-delete-null-pointer-checks", otherwise trying to access the
>> lowcore at address 0 makes GCC generate very weird code.
>>
>> Add two tests to test for simple operation and addressing exceptions.
>>
>> Signed-off-by: David Hildenbrand <david@redhat.com>
>> ---
> [...]
>> diff --git a/lib/s390x/interrupt.c b/lib/s390x/interrupt.c
>> new file mode 100644
>> index 0000000..8d861a2
>> --- /dev/null
>> +++ b/lib/s390x/interrupt.c
>> @@ -0,0 +1,82 @@
>> +/*
>> + * s390x interrupt handling
>> + *
>> + * Copyright (c) 2017 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.
>> + */
>> +#include <libcflat.h>
>> +#include <asm/interrupt.h>
>> +#include <asm/barrier.h>
>> +
>> +static bool pgm_int_expected;
>> +static struct lowcore *lc;
> 
> Cosmetic suggestion:
> Maybe make it "static struct lowcore const *lc = 0" to be more explicit?

You most probably mean
static struct lowcore *const lc = 0;

(otherwise it won't compile)

makes sense. If I have to resend, I'll add it.

> 
> Apart from that, patch looks fine to me now, so with or without that change:
> 
> Reviewed-by: Thomas Huth <thuth@redhat.com>
> 

Thanks!

-- 

Thanks,

David

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

* Re: [kvm-unit-tests PATCH v2 2/2] s390x: pgm interrupt handler and a way to test them
  2017-05-31 13:25     ` Thomas Huth
@ 2017-05-31 14:23       ` Paolo Bonzini
  0 siblings, 0 replies; 9+ messages in thread
From: Paolo Bonzini @ 2017-05-31 14:23 UTC (permalink / raw)
  To: Thomas Huth, David Hildenbrand, kvm
  Cc: Radim Krčmář, Christian Borntraeger



On 31/05/2017 15:25, Thomas Huth wrote:
> On 31.05.2017 14:51, Paolo Bonzini wrote:
>>
>>
>> On 31/05/2017 14:39, David Hildenbrand wrote:
>>> +	expect_pgm_int();
>>> +	*((unsigned int*)-1) = 1;
>>> +	check_pgm_int_code(PGM_INT_CODE_ADDRESSING);
>>
>> QEMU gets
>>
>> ABORT: selftest: Unexpected program interrupt: 5 at 0x12b4c, ilen 4
>>
>> It seems that QEMU doesn't point the PSW at the next instruction
> 
> David mentioned it in the cover letter ... you likely need this patch
> here first:
> 
> http://patchwork.ozlabs.org/patch/768173/
> 
>  Thomas
> 

That helps indeed. :)

Paolo

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

end of thread, other threads:[~2017-05-31 14:23 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-05-31 12:39 [kvm-unit-tests PATCH v2 0/2] s390x: program interrupt handler David Hildenbrand
2017-05-31 12:39 ` [kvm-unit-tests PATCH v2 1/2] s390x: generate asm offsets for the lowcore David Hildenbrand
2017-05-31 12:39 ` [kvm-unit-tests PATCH v2 2/2] s390x: pgm interrupt handler and a way to test them David Hildenbrand
2017-05-31 12:51   ` Paolo Bonzini
2017-05-31 13:25     ` Thomas Huth
2017-05-31 14:23       ` Paolo Bonzini
2017-05-31 13:26     ` David Hildenbrand
2017-05-31 13:22   ` Thomas Huth
2017-05-31 13:30     ` David Hildenbrand

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