Skip to contentSkip to conversation

s390x: vmalloc support

PATCH Applied David Hildenbrand 4 participants 23 messages Feb 13, 2018 – Feb 14, 2018 KVM

lore
Share & tools
lore
#0 lore raw

v3 cover s390x: vmalloc support

This series implements
- detection of installed physical memory
- setup of the physical allocator
- setup of the MMU / page tables / DAT
- setup of the virtual allocator

The CPU now runs with DAT enabled. I added a small test to make sure malloc() indeed works and uses virtual adresses. Also, the sieve test is added.

While at it, fix the TEST BLOCK test on newer compilers.

Tested with upsteam QEMU TCG and KVM. However, to pass under TCG a fix is necessary ("[PATCH v1] s390x/tcg: fix disabling/enabling DAT").

v2 -> v3:
- split up configure_dat() to make use of two functions extract_psw_mask() and load_psw_mask(), it is now much cleaner and we might need these functions in the future.
- Minor cleanups / comment fixes

David Hildenbrand (11):
s390x: fix TEST BLOCK tests
s390x: use highest addresses for PGM_ADDRESSING errors
s390x: set initital stack pointer to stackptr, not stacktop
s390x: add missing sclp definitions from QEMU
s390x: rename sclp_setup() to sclp_ascii_setup()
s390x: detect installed memory
s390x: initialize the physical allocator
s390x: add vmalloc support
s390x: enable DAT in PGM interrupt handler
s390x: add test for (v)malloc
s390x: add sieve test

 lib/s390x/asm/arch_def.h  |  58 ++++++++++++
 lib/s390x/asm/interrupt.h |   1 +
 lib/s390x/asm/page.h      |  24 +++++
 lib/s390x/asm/pgtable.h   | 224 ++++++++++++++++++++++++++++++++++++++++++++++
 lib/s390x/interrupt.c     |  11 +++
 lib/s390x/io.c            |   3 +-
 lib/s390x/mmu.c           | 108 ++++++++++++++++++++++
 lib/s390x/sclp-ascii.c    |   6 +-
 lib/s390x/sclp.c          |  72 +++++++++++++++
 lib/s390x/sclp.h          | 112 ++++++++++++++++++++++-
 s390x/Makefile            |   7 ++
 s390x/cstart64.S          |   2 +-
 s390x/intercept.c         |  14 +--
 s390x/selftest.c          |  31 ++++++-
 s390x/sieve.c             |  59 ++++++++++++
 s390x/unittests.cfg       |   6 ++
 16 files changed, 723 insertions(+), 15 deletions(-)
 create mode 100644 lib/s390x/asm/pgtable.h
 create mode 100644 lib/s390x/mmu.c
 create mode 100644 lib/s390x/sclp.c
 create mode 100644 s390x/sieve.c
Signature · 1 line
2.14.3
#1 lore raw

PATCH v3 1/11 s390x: fix TEST BLOCK tests

While new compilers like

	s390x-linux-gnu-gcc (GCC) 7.2.1 20170915 (Red Hat Cross 7.2.1-1)
Complain, that R1 is missing, old compilers like
	gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-16)

will complain that R1 is not valid.

Let's just specify the instruction explicitly.

---
 s390x/intercept.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
s390x/intercept.c +3 -3
index 59e5fca..99dde0d 100644
@@ -139,7 +139,7 @@ static void test_testblock(void)
 
 	asm volatile (
 		" lghi	%%r0,0\n"
-		" tb	%1\n"
+		" .insn	rre,0xb22c0000,0,%1\n"
 		" ipm	%0\n"
 		" srl	%0,28\n"
 		: "=d" (cc)
@@ -150,12 +150,12 @@ static void test_testblock(void)
 
 	expect_pgm_int();
 	low_prot_enable();
-	asm volatile (" tb %0 " : : "r"(4096));
+	asm volatile (" .insn	rre,0xb22c0000,0,%0\n" : : "r"(4096));
 	low_prot_disable();
 	check_pgm_int_code(PGM_INT_CODE_PROTECTION);
 
 	expect_pgm_int();
-	asm volatile (" tb %0 " : : "r"(-4096));
+	asm volatile (" .insn	rre,0xb22c0000,0,%0\n" : : "r"(-4096));
 	check_pgm_int_code(PGM_INT_CODE_ADDRESSING);
 }
 
Signature · 1 line
2.14.3
#2 lore raw

PATCH v3 2/11 s390x: use highest addresses for PGM_ADDRESSING errors

In reply to David Hildenbrand

Without the L, we get 32 bit addresses, resulting in different memory addresses. This is necessary for enabling the MMU.

---
 s390x/intercept.c | 10 +++++-----
 s390x/selftest.c  |  2 +-
 2 files changed, 6 insertions(+), 6 deletions(-)
s390x/intercept.c +5 -5
index 99dde0d..404b4c6 100644
@@ -46,7 +46,7 @@ static void test_stpx(void)
 	check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
 
 	expect_pgm_int();
-	asm volatile(" stpx 0(%0) " : : "r"(-8));
+	asm volatile(" stpx 0(%0) " : : "r"(-8L));
 	check_pgm_int_code(PGM_INT_CODE_ADDRESSING);
 }
 
@@ -78,7 +78,7 @@ static void test_spx(void)
 	check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
 
 	expect_pgm_int();
-	asm volatile(" spx 0(%0) " : : "r"(-8));
+	asm volatile(" spx 0(%0) " : : "r"(-8L));
 	check_pgm_int_code(PGM_INT_CODE_ADDRESSING);
 }
 
@@ -101,7 +101,7 @@ static void test_stap(void)
 	check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
 
 	expect_pgm_int();
-	asm volatile ("stap 0(%0)\n" : : "r"(-8));
+	asm volatile ("stap 0(%0)\n" : : "r"(-8L));
 	check_pgm_int_code(PGM_INT_CODE_ADDRESSING);
 }
 
@@ -126,7 +126,7 @@ static void test_stidp(void)
 	check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
 
 	expect_pgm_int();
-	asm volatile ("stidp 0(%0)\n" : : "r"(-8));
+	asm volatile ("stidp 0(%0)\n" : : "r"(-8L));
 	check_pgm_int_code(PGM_INT_CODE_ADDRESSING);
 }
 
@@ -155,7 +155,7 @@ static void test_testblock(void)
 	check_pgm_int_code(PGM_INT_CODE_PROTECTION);
 
 	expect_pgm_int();
-	asm volatile (" .insn	rre,0xb22c0000,0,%0\n" : : "r"(-4096));
+	asm volatile (" .insn	rre,0xb22c0000,0,%0\n" : : "r"(-4096L));
 	check_pgm_int_code(PGM_INT_CODE_ADDRESSING);
 }
 
s390x/selftest.c +1 -1
index 1c8d16a..905713f 100644
@@ -33,7 +33,7 @@ static void test_pgm_int(void)
 	check_pgm_int_code(PGM_INT_CODE_OPERATION);
 
 	expect_pgm_int();
-	asm volatile("	stg %0,0(%0)\n" : : "r"(-1));
+	asm volatile("	stg %0,0(%0)\n" : : "r"(-1L));
 	check_pgm_int_code(PGM_INT_CODE_ADDRESSING);
 }
 
Signature · 1 line
2.14.3
#3 lore raw

PATCH v3 3/11 s390x: set initital stack pointer to stackptr, not stacktop

In reply to David Hildenbrand

... was wrong from the beginning and remained unnoticed until we started playing with dynamic memory allocation.

---
 s390x/cstart64.S | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
s390x/cstart64.S +1 -1
index 4d0c877..9a26ed3 100644
@@ -18,7 +18,7 @@
 	.globl start
 start:
 	/* setup stack */
-	larl	%r15, stacktop
+	larl	%r15, stackptr
 	/* setup initial PSW mask + control registers*/
 	larl	%r1, initital_psw
 	lpswe	0(%r1)
Signature · 1 line
2.14.3
#4 lore raw

PATCH v3 4/11 s390x: add missing sclp definitions from QEMU

In reply to David Hildenbrand

Copy all missing definitions from QEMU (include/hw/s390x/sclp.h). We cannot simply replace the file, as some ASCII definitions are missing in the QEMU file (defined somewhere else in QEMU).

Convert QEMU_PACKED accordingly and copy the copyright statement.

---
 lib/s390x/sclp.h | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 106 insertions(+), 1 deletion(-)
lib/s390x/sclp.h +106 -1
index 3f4c138..a1d0a5e 100644
@@ -1,8 +1,13 @@
 /*
- * SCLP ASCII access driver
+ * SCLP definitions
  *
+ * Based on the file pc-bios/s390-ccw/sclp.h from QEMU
  * Copyright (c) 2013 Alexander Graf <[email protected]>
  *
+ * and based on the file include/hw/s390x/sclp.h from QEMU
+ * Copyright IBM, Corp. 2012
+ * Author: Christian Borntraeger <[email protected]>
+ *
  * This work is licensed under the terms of the GNU GPL, version 2 or (at
  * your option) any later version. See the COPYING file in the top-level
  * directory.
@@ -11,21 +16,51 @@
 #ifndef SCLP_H
 #define SCLP_H
 
+#define SCLP_CMD_CODE_MASK                      0xffff00ff
+
 /* SCLP command codes */
 #define SCLP_CMDW_READ_SCP_INFO                 0x00020001
 #define SCLP_CMDW_READ_SCP_INFO_FORCED          0x00120001
+#define SCLP_READ_STORAGE_ELEMENT_INFO          0x00040001
+#define SCLP_ATTACH_STORAGE_ELEMENT             0x00080001
+#define SCLP_ASSIGN_STORAGE                     0x000D0001
 #define SCLP_CMD_READ_EVENT_DATA                0x00770005
 #define SCLP_CMD_WRITE_EVENT_DATA               0x00760005
 #define SCLP_CMD_READ_EVENT_DATA                0x00770005
 #define SCLP_CMD_WRITE_EVENT_DATA               0x00760005
 #define SCLP_CMD_WRITE_EVENT_MASK               0x00780005
 
+/* SCLP Memory hotplug codes */
+#define SCLP_FC_ASSIGN_ATTACH_READ_STOR         0xE00000000000ULL
+#define SCLP_STARTING_SUBINCREMENT_ID           0x10001
+#define SCLP_INCREMENT_UNIT                     0x10000
+#define MAX_AVAIL_SLOTS                         32
+#define MAX_STORAGE_INCREMENTS                  1020
+
+/* CPU hotplug SCLP codes */
+#define SCLP_HAS_CPU_INFO                       0x0C00000000000000ULL
+#define SCLP_CMDW_READ_CPU_INFO                 0x00010001
+#define SCLP_CMDW_CONFIGURE_CPU                 0x00110001
+#define SCLP_CMDW_DECONFIGURE_CPU               0x00100001
+
+/* SCLP PCI codes */
+#define SCLP_HAS_IOA_RECONFIG                   0x0000000040000000ULL
+#define SCLP_CMDW_CONFIGURE_IOA                 0x001a0001
+#define SCLP_CMDW_DECONFIGURE_IOA               0x001b0001
+#define SCLP_RECONFIG_PCI_ATYPE                 2
+
 /* SCLP response codes */
 #define SCLP_RC_NORMAL_READ_COMPLETION          0x0010
 #define SCLP_RC_NORMAL_COMPLETION               0x0020
+#define SCLP_RC_SCCB_BOUNDARY_VIOLATION         0x0100
+#define SCLP_RC_NO_ACTION_REQUIRED              0x0120
 #define SCLP_RC_INVALID_SCLP_COMMAND            0x01f0
 #define SCLP_RC_CONTAINED_EQUIPMENT_CHECK       0x0340
 #define SCLP_RC_INSUFFICIENT_SCCB_LENGTH        0x0300
+#define SCLP_RC_STANDBY_READ_COMPLETION         0x0410
+#define SCLP_RC_ADAPTER_IN_RESERVED_STATE       0x05f0
+#define SCLP_RC_ADAPTER_TYPE_NOT_RECOGNIZED     0x06f0
+#define SCLP_RC_ADAPTER_ID_NOT_RECOGNIZED       0x09f0
 #define SCLP_RC_INVALID_FUNCTION                0x40f0
 #define SCLP_RC_NO_EVENT_BUFFERS_STORED         0x60f0
 #define SCLP_RC_INVALID_SELECTION_MASK          0x70f0
@@ -50,13 +85,83 @@ typedef struct SCCBHeader {
 } __attribute__((packed)) SCCBHeader;
 
 #define SCCB_DATA_LEN (SCCB_SIZE - sizeof(SCCBHeader))
+#define SCCB_CPU_FEATURE_LEN 6
+
+/* CPU information */
+typedef struct CPUEntry {
+    uint8_t address;
+    uint8_t reserved0;
+    uint8_t features[SCCB_CPU_FEATURE_LEN];
+    uint8_t reserved2[6];
+    uint8_t type;
+    uint8_t reserved1;
+} __attribute__((packed)) CPUEntry;
 
 typedef struct ReadInfo {
     SCCBHeader h;
     uint16_t rnmax;
     uint8_t rnsize;
+    uint8_t  _reserved1[16 - 11];       /* 11-15 */
+    uint16_t entries_cpu;               /* 16-17 */
+    uint16_t offset_cpu;                /* 18-19 */
+    uint8_t  _reserved2[24 - 20];       /* 20-23 */
+    uint8_t  loadparm[8];               /* 24-31 */
+    uint8_t  _reserved3[48 - 32];       /* 32-47 */
+    uint64_t facilities;                /* 48-55 */
+    uint8_t  _reserved0[76 - 56];       /* 56-75 */
+    uint32_t ibc_val;
+    uint8_t  conf_char[99 - 80];        /* 80-98 */
+    uint8_t mha_pow;
+    uint32_t rnsize2;
+    uint64_t rnmax2;
+    uint8_t  _reserved6[116 - 112];     /* 112-115 */
+    uint8_t  conf_char_ext[120 - 116];   /* 116-119 */
+    uint16_t highest_cpu;
+    uint8_t  _reserved5[124 - 122];     /* 122-123 */
+    uint32_t hmfai;
+    struct CPUEntry entries[0];
 } __attribute__((packed)) ReadInfo;
 
+typedef struct ReadCpuInfo {
+    SCCBHeader h;
+    uint16_t nr_configured;         /* 8-9 */
+    uint16_t offset_configured;     /* 10-11 */
+    uint16_t nr_standby;            /* 12-13 */
+    uint16_t offset_standby;        /* 14-15 */
+    uint8_t reserved0[24-16];       /* 16-23 */
+    struct CPUEntry entries[0];
+} __attribute__((packed)) ReadCpuInfo;
+
+typedef struct ReadStorageElementInfo {
+    SCCBHeader h;
+    uint16_t max_id;
+    uint16_t assigned;
+    uint16_t standby;
+    uint8_t _reserved0[16 - 14]; /* 14-15 */
+    uint32_t entries[0];
+} __attribute__((packed)) ReadStorageElementInfo;
+
+typedef struct AttachStorageElement {
+    SCCBHeader h;
+    uint8_t _reserved0[10 - 8];  /* 8-9 */
+    uint16_t assigned;
+    uint8_t _reserved1[16 - 12]; /* 12-15 */
+    uint32_t entries[0];
+} __attribute__((packed)) AttachStorageElement;
+
+typedef struct AssignStorage {
+    SCCBHeader h;
+    uint16_t rn;
+} __attribute__((packed)) AssignStorage;
+
+typedef struct IoaCfgSccb {
+    SCCBHeader header;
+    uint8_t atype;
+    uint8_t reserved1;
+    uint16_t reserved2;
+    uint32_t aid;
+} __attribute__((packed)) IoaCfgSccb;
+
 typedef struct SCCB {
     SCCBHeader h;
     char data[SCCB_DATA_LEN];
Signature · 1 line
2.14.3
#5 lore raw

PATCH v3 5/11 s390x: rename sclp_setup() to sclp_ascii_setup()

In reply to David Hildenbrand

We'll be introducing some other sclp related files including setup functions soon. Also allow to call sclp_service_call() from these (including reusing the buffer).

---
 lib/s390x/io.c         | 2 +-
 lib/s390x/sclp-ascii.c | 6 +++---
 lib/s390x/sclp.h       | 4 +++-
 3 files changed, 7 insertions(+), 5 deletions(-)
lib/s390x/io.c +1 -1
index 12f9d26..3121a78 100644
@@ -42,7 +42,7 @@ void setup()
 {
 	setup_args_progname(ipl_args);
 	setup_facilities();
-	sclp_setup();
+	sclp_ascii_setup();
 }
 
 void exit(int code)
lib/s390x/sclp-ascii.c +3 -3
index dfb9e68..893ca17 100644
@@ -13,10 +13,10 @@
 #include <asm/page.h>
 #include "sclp.h"
 
-static char _sccb[PAGE_SIZE] __attribute__((__aligned__(4096)));
+char _sccb[PAGE_SIZE] __attribute__((__aligned__(4096)));
 
 /* Perform service call. Return 0 on success, non-zero otherwise. */
-static int sclp_service_call(unsigned int command, void *sccb)
+int sclp_service_call(unsigned int command, void *sccb)
 {
         int cc;
 
@@ -47,7 +47,7 @@ static void sclp_set_write_mask(void)
     sclp_service_call(SCLP_CMD_WRITE_EVENT_MASK, sccb);
 }
 
-void sclp_setup(void)
+void sclp_ascii_setup(void)
 {
     sclp_set_write_mask();
 }
lib/s390x/sclp.h +3 -1
index a1d0a5e..d113cf8 100644
@@ -207,7 +207,9 @@ typedef struct ReadEventData {
     uint32_t mask;
 } __attribute__((packed)) ReadEventData;
 
-void sclp_setup(void);
+void sclp_ascii_setup(void);
 void sclp_print(const char *str);
+extern char _sccb[];
+int sclp_service_call(unsigned int command, void *sccb);
 
 #endif /* SCLP_H */
Signature · 1 line
2.14.3
#6 lore raw

PATCH v3 6/11 s390x: detect installed memory

In reply to David Hildenbrand

Unfortunately, there is no easy way to simply read out the amount of installed memory. We have to probe (via TEST PROTECTION) for installed memory in a given range.

---
 lib/s390x/asm/arch_def.h  | 12 ++++++++++
 lib/s390x/asm/interrupt.h |  1 +
 lib/s390x/interrupt.c     | 11 +++++++++
 lib/s390x/io.c            |  1 +
 lib/s390x/sclp.c          | 58 +++++++++++++++++++++++++++++++++++++++++++++++
 lib/s390x/sclp.h          |  1 +
 s390x/Makefile            |  1 +
 7 files changed, 85 insertions(+)
 create mode 100644 lib/s390x/sclp.c
lib/s390x/asm/arch_def.h +12 -0
index 72e5c60..ee4c96f 100644
@@ -151,4 +151,16 @@ struct cpuid {
 	uint64_t reserved : 15;
 };
 
+static inline int tprot(unsigned long addr)
+{
+	int cc;
+
+	asm volatile(
+		"	tprot	0(%1),0\n"
+		"	ipm	%0\n"
+		"	srl	%0,28\n"
+		: "=d" (cc) : "a" (addr) : "cc");
+	return cc;
+}
+
 #endif
lib/s390x/asm/interrupt.h +1 -0
index 41be039..3ccc8e3 100644
@@ -13,6 +13,7 @@
 
 void handle_pgm_int(void);
 void expect_pgm_int(void);
+uint16_t clear_pgm_int(void);
 void check_pgm_int_code(uint16_t code);
 
 /* Activate low-address protection */
lib/s390x/interrupt.c +11 -0
index 8d861a2..67d581b 100644
@@ -23,6 +23,17 @@ void expect_pgm_int(void)
 	mb();
 }
 
+uint16_t clear_pgm_int(void)
+{
+	uint16_t code;
+
+	mb();
+	code = lc->pgm_int_code;
+	lc->pgm_int_code = 0;
+	pgm_int_expected = false;
+	return code;
+}
+
 void check_pgm_int_code(uint16_t code)
 {
 	mb();
lib/s390x/io.c +1 -0
index 3121a78..eb4d171 100644
@@ -43,6 +43,7 @@ void setup()
 	setup_args_progname(ipl_args);
 	setup_facilities();
 	sclp_ascii_setup();
+	sclp_memory_setup();
 }
 
 void exit(int code)
lib/s390x/sclp.c new file +58 -0

58 lines not on this page · raw message

lib/s390x/sclp.h +1 -0
index d113cf8..21d482b 100644
@@ -211,5 +211,6 @@ void sclp_ascii_setup(void);
 void sclp_print(const char *str);
 extern char _sccb[];
 int sclp_service_call(unsigned int command, void *sccb);
+void sclp_memory_setup(void);
 
 #endif /* SCLP_H */
s390x/Makefile +1 -0
index f585faf..ce63dd1 100644
@@ -24,6 +24,7 @@ cflatobjs += lib/util.o
 cflatobjs += lib/alloc_phys.o
 cflatobjs += lib/s390x/io.o
 cflatobjs += lib/s390x/stack.o
+cflatobjs += lib/s390x/sclp.o
 cflatobjs += lib/s390x/sclp-ascii.o
 cflatobjs += lib/s390x/interrupt.o
 
Signature · 1 line
2.14.3
#7 lore raw

PATCH v3 7/11 s390x: initialize the physical allocator

In reply to David Hildenbrand

We now have the range of free memory, let's initialize the physical allocator. It is now possible to use use malloc and memalign, based on the early-ops. alloc_pages() cannot be used yet (as it has to be initialized via free_pages() - e.g. via setup_vm() - first)

---
 lib/s390x/sclp.c | 12 ++++++++++++
 s390x/Makefile   |  3 +++
 2 files changed, 15 insertions(+)
lib/s390x/sclp.c +12 -0
index 199405c..c7471b1 100644
@@ -15,11 +15,21 @@
 #include <asm/arch_def.h>
 #include <asm/interrupt.h>
 #include "sclp.h"
+#include <alloc_phys.h>
+
+extern unsigned long stacktop;
 
 static uint64_t storage_increment_size;
 static uint64_t max_ram_size;
 static uint64_t ram_size;
 
+static void mem_init(phys_addr_t mem_end)
+{
+	phys_addr_t freemem_start = (phys_addr_t)&stacktop & PAGE_MASK;
+
+	phys_alloc_init(freemem_start, mem_end - freemem_start);
+}
+
 void sclp_memory_setup(void)
 {
 	ReadInfo *ri = (void *)_sccb;
@@ -55,4 +65,6 @@ void sclp_memory_setup(void)
 			break;
 		ram_size += storage_increment_size;
 	}
+
+	mem_init(ram_size);
 }
s390x/Makefile +3 -0
index ce63dd1..4198fdc 100644
@@ -21,6 +21,9 @@ asm-offsets = lib/$(ARCH)/asm-offsets.h
 include $(SRCDIR)/scripts/asm-offsets.mak
 
 cflatobjs += lib/util.o
+cflatobjs += lib/alloc.o
+cflatobjs += lib/alloc_phys.o
+cflatobjs += lib/alloc_page.o
 cflatobjs += lib/alloc_phys.o
 cflatobjs += lib/s390x/io.o
 cflatobjs += lib/s390x/stack.o
Signature · 1 line
2.14.3
#8 lore raw

Re: [PATCH kvm-unit-tests v3 07/11] s390x: initialize the physical allocator

Quoted 20 lines · David Hildenbrand

We now have the range of free memory, let's initialize the physical allocator. It is now possible to use use malloc and memalign, based on the early-ops. alloc_pages() cannot be used yet (as it has to be initialized via free_pages() - e.g. via setup_vm() - first)

---
 lib/s390x/sclp.c | 12 ++++++++++++
 s390x/Makefile   |  3 +++
 2 files changed, 15 insertions(+)
lib/s390x/sclp.c +1 -0
index 199405c..c7471b1 100644
@@ -15,11 +15,21 @@
 #include <asm/arch_def.h>
 #include <asm/interrupt.h>
 #include "sclp.h"
+#include <alloc_phys.h>

lib/s390x/sclp.c line 28

Quoted 10 lines
lib/s390x/sclp.c +5 -0
+
+extern unsigned long stacktop;
 
 static uint64_t storage_increment_size;
 static uint64_t max_ram_size;
 static uint64_t ram_size;
 
+static void mem_init(phys_addr_t mem_end)
+{
+	phys_addr_t freemem_start = (phys_addr_t)&stacktop & PAGE_MASK;

Should be ok since stacktop should be aligned. Otherwise this should maybe better be (stacktop + PAGE_SIZE - 1) & PAGE_MASK ?

Thomas

#9 lore raw

Re: [PATCH kvm-unit-tests v3 07/11] s390x: initialize the physical allocator

Quoted 28 lines · Thomas Huth
Quoted 27 lines · David Hildenbrand

We now have the range of free memory, let's initialize the physical allocator. It is now possible to use use malloc and memalign, based on the early-ops. alloc_pages() cannot be used yet (as it has to be initialized via free_pages() - e.g. via setup_vm() - first)

---
 lib/s390x/sclp.c | 12 ++++++++++++
 s390x/Makefile   |  3 +++
 2 files changed, 15 insertions(+)
lib/s390x/sclp.c +3 -0
index 199405c..c7471b1 100644
@@ -15,11 +15,21 @@
 #include <asm/arch_def.h>
 #include <asm/interrupt.h>
 #include "sclp.h"
+#include <alloc_phys.h>
+
+extern unsigned long stacktop;
 
 static uint64_t storage_increment_size;
 static uint64_t max_ram_size;
 static uint64_t ram_size;
 
Quoted 7 lines

lib/s390x/sclp.c line 28

Quoted 3 lines
lib/s390x/sclp.c +3 -0
+static void mem_init(phys_addr_t mem_end)
+{
+	phys_addr_t freemem_start = (phys_addr_t)&stacktop & PAGE_MASK;

Should be ok since stacktop should be aligned. Otherwise this should maybe better be (stacktop + PAGE_SIZE - 1) & PAGE_MASK ?

Either that or drop the "& PAGE_MASK". But guess this doesn't really make a difference right now. Thanks!

Quoted 2 lines

Thomas

Signature · 3 lines
Thanks,

David / dhildenb
#10 lore raw

PATCH v3 8/11 s390x: add vmalloc support

In reply to David Hildenbrand

To use virtual addresses, we have to
- build page tables with identity mapping
- setup the primary ASCE in cr1
- enable DAT in the PSW

Not using the Linux definitions/implementation as they contain too much software defined stuff / things we don't need.

Written from scratch. Tried to stick to the general Linux naming schemes.

As we currently don't invalidate anything except page table entries, it is sufficient to only use ipte for now.

---
 lib/s390x/asm/arch_def.h |  46 ++++++++++
 lib/s390x/asm/page.h     |  24 +++++
 lib/s390x/asm/pgtable.h  | 224 +++++++++++++++++++++++++++++++++++++++++++++++
 lib/s390x/mmu.c          | 104 ++++++++++++++++++++++
 lib/s390x/sclp.c         |   2 +
 s390x/Makefile           |   2 +
 6 files changed, 402 insertions(+)
 create mode 100644 lib/s390x/asm/pgtable.h
 create mode 100644 lib/s390x/mmu.c
lib/s390x/asm/arch_def.h +46 -0
index ee4c96f..620dca4 100644
@@ -15,6 +15,8 @@ struct psw {
 	uint64_t	addr;
 };
 
+#define PSW_MASK_DAT			0x0400000000000000UL
+
 struct lowcore {
 	uint8_t		pad_0x0000[0x0080 - 0x0000];	/* 0x0000 */
 	uint32_t	ext_int_param;			/* 0x0080 */
@@ -163,4 +165,48 @@ static inline int tprot(unsigned long addr)
 	return cc;
 }
 
+static inline void lctlg(int cr, uint64_t value)
+{
+	asm volatile(
+		"	lctlg	%1,%1,%0\n"
+		: : "Q" (value), "i" (cr));
+}
+
+static inline uint64_t stctg(int cr)
+{
+	uint64_t value;
+
+	asm volatile(
+		"	stctg	%1,%1,%0\n"
+		: "=Q" (value) : "i" (cr) : "memory");
+	return value;
+}
+
+static inline uint64_t extract_psw_mask(void)
+{
+	uint32_t mask_upper = 0, mask_lower = 0;
+
+	asm volatile(
+		"	epsw	%0,%1\n"
+		: "+r" (mask_upper), "+r" (mask_lower) : : );
+
+	return (uint64_t) mask_upper << 32 | mask_lower;
+}
+
+static inline void load_psw_mask(uint64_t mask)
+{
+	struct psw psw = {
+		.mask = mask,
+		.addr = 0,
+	};
+	uint64_t tmp = 0;
+
+	asm volatile(
+		"	larl	%0,0f\n"
+		"	stg	%0,8(%1)\n"
+		"	lpswe	0(%1)\n"
+		"0:\n"
+		: "+r" (tmp) :  "a" (&psw) : "memory", "cc" );
+}
+
 #endif
lib/s390x/asm/page.h +24 -0
index 141a456..bc19154 100644
@@ -13,4 +13,28 @@
 
 #include <asm-generic/page.h>
 
+typedef uint64_t pgdval_t;		/* Region-1 table entry */
+typedef uint64_t p4dval_t;		/* Region-2 table entry*/
+typedef uint64_t pudval_t;		/* Region-3 table entry */
+typedef uint64_t pmdval_t;		/* Segment table entry */
+typedef uint64_t pteval_t;		/* Page table entry */
+
+typedef struct { pgdval_t pgd; } pgd_t;
+typedef struct { p4dval_t p4d; } p4d_t;
+typedef struct { pudval_t pud; } pud_t;
+typedef struct { pmdval_t pmd; } pmd_t;
+typedef struct { pteval_t pte; } pte_t;
+
+#define pgd_val(x)	((x).pgd)
+#define p4d_val(x)	((x).p4d)
+#define pud_val(x)	((x).pud)
+#define pmd_val(x)	((x).pmd)
+#define pte_val(x)	((x).pte)
+
+#define __pgd(x)	((pgd_t) { (x) } )
+#define __p4d(x)	((p4d_t) { (x) } )
+#define __pud(x)	((pud_t) { (x) } )
+#define __pmd(x)	((pmd_t) { (x) } )
+#define __pte(x)	((pte_t) { (x) } )
+
 #endif
lib/s390x/asm/pgtable.h new file +224 -0

224 lines not on this page · raw message

lib/s390x/mmu.c new file +104 -0

104 lines not on this page · raw message

lib/s390x/sclp.c +2 -0
index c7471b1..005ae52 100644
@@ -28,6 +28,8 @@ static void mem_init(phys_addr_t mem_end)
 	phys_addr_t freemem_start = (phys_addr_t)&stacktop & PAGE_MASK;
 
 	phys_alloc_init(freemem_start, mem_end - freemem_start);
+
+	setup_vm();
 }
 
 void sclp_memory_setup(void)
s390x/Makefile +2 -0
index 4198fdc..d9bef37 100644
@@ -24,12 +24,14 @@ cflatobjs += lib/util.o
 cflatobjs += lib/alloc.o
 cflatobjs += lib/alloc_phys.o
 cflatobjs += lib/alloc_page.o
+cflatobjs += lib/vmalloc.o
 cflatobjs += lib/alloc_phys.o
 cflatobjs += lib/s390x/io.o
 cflatobjs += lib/s390x/stack.o
 cflatobjs += lib/s390x/sclp.o
 cflatobjs += lib/s390x/sclp-ascii.o
 cflatobjs += lib/s390x/interrupt.o
+cflatobjs += lib/s390x/mmu.o
 
 OBJDIRS += lib/s390x
 
Signature · 1 line
2.14.3
#11 lore raw

PATCH v3 9/11 s390x: enable DAT in PGM interrupt handler

In reply to David Hildenbrand

Configure it in setup_vm().

---
 lib/s390x/mmu.c | 4 ++++
 1 file changed, 4 insertions(+)
lib/s390x/mmu.c +4 -0
index f0ec7c3..288f835 100644
@@ -30,6 +30,7 @@ void configure_dat(int enable)
 
 static void mmu_enable(pgd_t *pgtable)
 {
+	struct lowcore *lc = NULL;
 	const uint64_t asce = __pa(pgtable) | ASCE_DT_REGION1 |
 			      REGION_TABLE_LENGTH;
 
@@ -39,6 +40,9 @@ static void mmu_enable(pgd_t *pgtable)
 
 	/* enable dat (primary == 0 set as default) */
 	configure_dat(1);
+
+	/* we can now also use DAT unconditionally in our PGM handler */
+	lc->pgm_new_psw.mask |= PSW_MASK_DAT;
 }
 
 static pteval_t *get_pte(pgd_t *pgtable, uintptr_t vaddr)
Signature · 1 line
2.14.3
#12 lore raw

PATCH v3 10/11 s390x: add test for (v)malloc

In reply to David Hildenbrand

Let's test if basic allocation works and we get virtual addresses.

---
 s390x/selftest.c | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)
s390x/selftest.c +29 -0
index 905713f..18a40e1 100644
@@ -10,7 +10,10 @@
  */
 #include <libcflat.h>
 #include <util.h>
+#include <alloc.h>
 #include <asm/interrupt.h>
+#include <asm/barrier.h>
+#include <asm/pgtable.h>
 
 static void test_fp(void)
 {
@@ -37,6 +40,31 @@ static void test_pgm_int(void)
 	check_pgm_int_code(PGM_INT_CODE_ADDRESSING);
 }
 
+static void test_malloc(void)
+{
+	int *tmp = malloc(sizeof(int));
+	int *tmp2 = malloc(sizeof(int));
+
+	*tmp = 123456789;
+	*tmp2 = 123456789;
+	mb();
+
+	report("malloc: got vaddr", (uintptr_t)tmp & 0xf000000000000000ul);
+	report("malloc: access works", *tmp == 123456789);
+	report("malloc: got 2nd vaddr", (uintptr_t)tmp2 & 0xf000000000000000ul);
+	report("malloc: access works", (*tmp2 == 123456789));
+	report("malloc: addresses differ", tmp != tmp2);
+
+	expect_pgm_int();
+	configure_dat(0);
+	*tmp = 987654321;
+	configure_dat(1);
+	check_pgm_int_code(PGM_INT_CODE_ADDRESSING);
+
+	free(tmp);
+	free(tmp2);
+}
+
 int main(int argc, char**argv)
 {
 	report_prefix_push("selftest");
@@ -49,6 +77,7 @@ int main(int argc, char**argv)
 
 	test_fp();
 	test_pgm_int();
+	test_malloc();
 
 	return report_summary();
 }
Signature · 1 line
2.14.3
#13 lore raw

PATCH v3 11/11 s390x: add sieve test

In reply to David Hildenbrand

Copied from x86/sieve.c. Modifications:
- proper code formatting.
- as setup_vm() is already called, temporarily disable DAT.

The test takes fairly long, especially because we only have 128MB of ram and allocate 3 times in a row ~100mb of virtual memory.

---
 s390x/Makefile      |  1 +
 s390x/sieve.c       | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 s390x/unittests.cfg |  6 ++++++
 3 files changed, 66 insertions(+)
 create mode 100644 s390x/sieve.c
s390x/Makefile +1 -0
index d9bef37..2d3336c 100644
@@ -1,6 +1,7 @@
 tests = $(TEST_DIR)/selftest.elf
 tests += $(TEST_DIR)/intercept.elf
 tests += $(TEST_DIR)/emulator.elf
+tests += $(TEST_DIR)/sieve.elf
 
 all: directories test_cases
 
s390x/sieve.c new file +59 -0

59 lines not on this page · raw message

s390x/unittests.cfg +6 -0
index 1343a19..4a1e469 100644
@@ -28,3 +28,9 @@ file = intercept.elf
 
 [emulator]
 file = emulator.elf
+
+[sieve]
+file = sieve.elf
+groups = selftest
+# can take fairly long even on KVM guests
+timeout = 600
Signature · 1 line
2.14.3
#14 lore raw

Re: [PATCH kvm-unit-tests v3 11/11] s390x: add sieve test

Quoted 6 lines · David Hildenbrand

Copied from x86/sieve.c. Modifications:
- proper code formatting.
- as setup_vm() is already called, temporarily disable DAT.

The test takes fairly long, especially because we only have 128MB of ram and allocate 3 times in a row ~100mb of virtual memory.

Does it make sense to change the memory size in the unittests.cfg file? e.g. via extra_params?

Quoted 101 lines
---
 s390x/Makefile      |  1 +
 s390x/sieve.c       | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 s390x/unittests.cfg |  6 ++++++
 3 files changed, 66 insertions(+)
 create mode 100644 s390x/sieve.c
s390x/Makefile +1 -0
index d9bef37..2d3336c 100644
@@ -1,6 +1,7 @@
 tests = $(TEST_DIR)/selftest.elf
 tests += $(TEST_DIR)/intercept.elf
 tests += $(TEST_DIR)/emulator.elf
+tests += $(TEST_DIR)/sieve.elf
 
 all: directories test_cases
 
s390x/sieve.c new file +59 -0
new file mode 100644
index 0000000..28d4d1e
@@ -0,0 +1,59 @@
+/*
+ * Copied from x86/sieve.c
+ */
+
+#include <libcflat.h>
+#include <alloc.h>
+#include <asm/pgtable.h>
+
+int sieve(char* data, int size)
+{
+	int i, j, r = 0;
+
+	for (i = 0; i < size; ++i)
+		data[i] = 1;
+
+	data[0] = data[1] = 0;
+
+	for (i = 2; i < size; ++i)
+		if (data[i]) {
+			++r;
+			for (j = i * 2; j < size; j += i)
+				data[j] = 0;
+		}
+	return r;
+}
+
+void test_sieve(const char *msg, char *data, int size)
+{
+	int r;
+
+	printf("%s:", msg);
+	r = sieve(data, size);
+	printf("%d out of %d\n", r, size);
+}
+
+#define STATIC_SIZE 1000000
+#define VSIZE 100000000
+char static_data[STATIC_SIZE];
+
+int main()
+{
+	void *v;
+	int i;
+
+	printf("starting sieve\n");
+
+	configure_dat(0);
+	test_sieve("static", static_data, STATIC_SIZE);
+	configure_dat(1);
+
+	test_sieve("mapped", static_data, STATIC_SIZE);
+	for (i = 0; i < 3; ++i) {
+		v = malloc(VSIZE);
+		test_sieve("virtual", v, VSIZE);
+		free(v);
+	}
+
+	return 0;
+}
s390x/unittests.cfg +6 -0
index 1343a19..4a1e469 100644
@@ -28,3 +28,9 @@ file = intercept.elf
 
 [emulator]
 file = emulator.elf
+
+[sieve]
+file = sieve.elf
+groups = selftest
+# can take fairly long even on KVM guests
+timeout = 600
maintainer
#15 lore raw

Re: [PATCH kvm-unit-tests v3 11/11] s390x: add sieve test

Quoted 4 lines · Christian Borntraeger
Quoted 2 lines

The test takes fairly long, especially because we only have 128MB of ram and allocate 3 times in a row ~100mb of virtual memory.

Does it make sense to change the memory size in the unittests.cfg file? e.g. via extra_params?

The test takes 5 seconds on x86 KVM and about a minute on TCG (lots of TLB misses). Maybe it's an s390-specific bug in the test?

Thanks,

Paolo

#16 lore raw

Re: [PATCH kvm-unit-tests v3 11/11] s390x: add sieve test

Quoted 8 lines · Paolo Bonzini
Quoted 4 lines · Christian Borntraeger
Quoted 2 lines

The test takes fairly long, especially because we only have 128MB of ram and allocate 3 times in a row ~100mb of virtual memory.

Does it make sense to change the memory size in the unittests.cfg file? e.g. via extra_params?

The test takes 5 seconds on x86 KVM and about a minute on TCG (lots of TLB misses). Maybe it's an s390-specific bug in the test?

Under TCG: 1m 6,823s

I have to idea how long it takes under LPAR. Right now, I only have a z/VM based system available, so we are already using nested virtualization (implemented by z/VM). I expect things to be slow :)

Will try to find a LPAR to test with ...

Quoted 5 lines

Thanks,

Paolo

Signature · 3 lines
Thanks,

David / dhildenb
#17 lore raw

Re: [PATCH kvm-unit-tests v3 11/11] s390x: add sieve test

Quoted 10 lines · David Hildenbrand
Quoted 8 lines · Paolo Bonzini
Quoted 4 lines · Christian Borntraeger
Quoted 2 lines

The test takes fairly long, especially because we only have 128MB of ram and allocate 3 times in a row ~100mb of virtual memory.

Does it make sense to change the memory size in the unittests.cfg file? e.g. via extra_params?

The test takes 5 seconds on x86 KVM and about a minute on TCG (lots of TLB misses). Maybe it's an s390-specific bug in the test?

Quoted 8 lines

Under TCG: 1m 6,823s

I have to idea how long it takes under LPAR. Right now, I only have a z/VM based system available, so we are already using nested virtualization (implemented by z/VM). I expect things to be slow :)

Will try to find a LPAR to test with ...

LPAR: 0m 6.552s
z/VM: > 6m

So I don't think its a BUG. It's really nested virtualization kicking in.

Signature · 3 lines
Thanks,

David / dhildenb
maintainer
#18 lore raw

Re: [PATCH kvm-unit-tests v3 11/11] s390x: add sieve test

Quoted 17 lines · David Hildenbrand
Quoted 16 lines · David Hildenbrand
Quoted 8 lines · Paolo Bonzini
Quoted 4 lines · Christian Borntraeger
Quoted 2 lines

The test takes fairly long, especially because we only have 128MB of ram and allocate 3 times in a row ~100mb of virtual memory.

Does it make sense to change the memory size in the unittests.cfg file? e.g. via extra_params?

The test takes 5 seconds on x86 KVM and about a minute on TCG (lots of TLB misses). Maybe it's an s390-specific bug in the test?

Under TCG: 1m 6,823s

I have to idea how long it takes under LPAR. Right now, I only have a z/VM based system available, so we are already using nested virtualization (implemented by z/VM). I expect things to be slow :)

Quoted 7 lines
Quoted 2 lines

Will try to find a LPAR to test with ...

LPAR: 0m 6.552s
z/VM: > 6m

So I don't think its a BUG. It's really nested virtualization kicking in.

Whoa. How does KVM-on-KVM-on-LPAR fare?

I'll change the comment to

# can take fairly long when KVM is nested inside z/VM

Thanks,

Paolo

#19 lore raw

Re: [PATCH kvm-unit-tests v3 11/11] s390x: add sieve test

Quoted 21 lines · Paolo Bonzini
Quoted 20 lines · David Hildenbrand
Quoted 18 lines · David Hildenbrand
Quoted 8 lines · Paolo Bonzini
Quoted 4 lines · Christian Borntraeger
Quoted 2 lines

The test takes fairly long, especially because we only have 128MB of ram and allocate 3 times in a row ~100mb of virtual memory.

Does it make sense to change the memory size in the unittests.cfg file? e.g. via extra_params?

The test takes 5 seconds on x86 KVM and about a minute on TCG (lots of TLB misses). Maybe it's an s390-specific bug in the test?

Under TCG: 1m 6,823s

I have to idea how long it takes under LPAR. Right now, I only have a z/VM based system available, so we are already using nested virtualization (implemented by z/VM). I expect things to be slow :)

Will try to find a LPAR to test with ...

Quoted 6 lines
Quoted 4 lines

LPAR: 0m 6.552s
z/VM: > 6m

So I don't think its a BUG. It's really nested virtualization kicking in.

Whoa. How does KVM-on-KVM-on-LPAR fare?

We do a lot of IPTE calls, which flush the TLB on all CPUs.

But I think this could also be because the z/VM machine I am running on is simply overloaded. But of course also because our nested virt implementation in KVM is better ;)

Just tried nested under KVM (KVM-on-KVM-on-LPAR):

real 0m 9.411s

Quoted 9 lines

I'll change the comment to

# can take fairly long when KVM is nested inside z/VM

Thanks,

Paolo

Signature · 3 lines
Thanks,

David / dhildenb
#20 lore raw

Re: [PATCH kvm-unit-tests v3 11/11] s390x: add sieve test

Quoted 27 lines · David Hildenbrand
Quoted 26 lines · Paolo Bonzini
Quoted 24 lines · David Hildenbrand
Quoted 10 lines · David Hildenbrand
Quoted 8 lines · Paolo Bonzini
Quoted 4 lines · Christian Borntraeger
Quoted 2 lines

The test takes fairly long, especially because we only have 128MB of ram and allocate 3 times in a row ~100mb of virtual memory.

Does it make sense to change the memory size in the unittests.cfg file? e.g. via extra_params?

The test takes 5 seconds on x86 KVM and about a minute on TCG (lots of TLB misses). Maybe it's an s390-specific bug in the test?

Quoted 8 lines

Under TCG: 1m 6,823s

I have to idea how long it takes under LPAR. Right now, I only have a z/VM based system available, so we are already using nested virtualization (implemented by z/VM). I expect things to be slow :)

Will try to find a LPAR to test with ...

LPAR: 0m 6.552s
z/VM: > 6m

So I don't think its a BUG. It's really nested virtualization kicking in.

Quoted 7 lines
Quoted 1 line

Whoa. How does KVM-on-KVM-on-LPAR fare?

We do a lot of IPTE calls, which flush the TLB on all CPUs.

But I think this could also be because the z/VM machine I am running on is simply overloaded. But of course also because our nested virt implementation in KVM is better ;)

Just double checked, as we are not reusing virtual addresses, we are not issuing any IPTE instructions right now. So also no TLB flushes. This makes it very strange why z/VM performs (for me reproducible) that bad.

Quoted 16 lines

Just tried nested under KVM (KVM-on-KVM-on-LPAR):

real 0m 9.411s

Quoted 9 lines

I'll change the comment to

# can take fairly long when KVM is nested inside z/VM

Thanks,

Paolo

Signature · 3 lines
Thanks,

David / dhildenb
#21 lore raw

Re: [PATCH kvm-unit-tests v3 11/11] s390x: add sieve test

In reply to Christian Borntraeger
Quoted 11 lines · Christian Borntraeger
Quoted 6 lines · David Hildenbrand

Copied from x86/sieve.c. Modifications:
- proper code formatting.
- as setup_vm() is already called, temporarily disable DAT.

The test takes fairly long, especially because we only have 128MB of ram and allocate 3 times in a row ~100mb of virtual memory.

Does it make sense to change the memory size in the unittests.cfg file? e.g. via extra_params?

As the long runtime only seems to be a problem when running nested under z/VM, I don't think this should be a problem.

Signature · 3 lines
Thanks,

David / dhildenb
maintainer Applied
#22 lore raw
In reply to David Hildenbrand
Quoted 12 lines · David Hildenbrand

This series implements
- detection of installed physical memory
- setup of the physical allocator
- setup of the MMU / page tables / DAT
- setup of the virtual allocator

The CPU now runs with DAT enabled. I added a small test to make sure malloc() indeed works and uses virtual adresses. Also, the sieve test is added.

While at it, fix the TEST BLOCK test on newer compilers.

Quoted 8 lines

Tested with upsteam QEMU TCG and KVM. However, to pass under TCG a fix is necessary ("[PATCH v1] s390x/tcg: fix disabling/enabling DAT").

v2 -> v3:
- split up configure_dat() to make use of two functions extract_psw_mask() and load_psw_mask(), it is now much cleaner and we might need these functions in the future.
- Minor cleanups / comment fixes

Applied, thanks. Happy that the arm/x86 code generalized decently to s390!

Paolo

Quoted 37 lines

David Hildenbrand (11):
s390x: fix TEST BLOCK tests
s390x: use highest addresses for PGM_ADDRESSING errors
s390x: set initital stack pointer to stackptr, not stacktop
s390x: add missing sclp definitions from QEMU
s390x: rename sclp_setup() to sclp_ascii_setup()
s390x: detect installed memory
s390x: initialize the physical allocator
s390x: add vmalloc support
s390x: enable DAT in PGM interrupt handler
s390x: add test for (v)malloc
s390x: add sieve test

 lib/s390x/asm/arch_def.h  |  58 ++++++++++++
 lib/s390x/asm/interrupt.h |   1 +
 lib/s390x/asm/page.h      |  24 +++++
 lib/s390x/asm/pgtable.h   | 224 ++++++++++++++++++++++++++++++++++++++++++++++
 lib/s390x/interrupt.c     |  11 +++
 lib/s390x/io.c            |   3 +-
 lib/s390x/mmu.c           | 108 ++++++++++++++++++++++
 lib/s390x/sclp-ascii.c    |   6 +-
 lib/s390x/sclp.c          |  72 +++++++++++++++
 lib/s390x/sclp.h          | 112 ++++++++++++++++++++++-
 s390x/Makefile            |   7 ++
 s390x/cstart64.S          |   2 +-
 s390x/intercept.c         |  14 +--
 s390x/selftest.c          |  31 ++++++-
 s390x/sieve.c             |  59 ++++++++++++
 s390x/unittests.cfg       |   6 ++
 16 files changed, 723 insertions(+), 15 deletions(-)
 create mode 100644 lib/s390x/asm/pgtable.h
 create mode 100644 lib/s390x/mmu.c
 create mode 100644 lib/s390x/sclp.c
 create mode 100644 s390x/sieve.c