diff mbox

[kvm-unit-tests,v1,1/6] s390x: initial infrastructure

Message ID 20170512105830.10604-2-david@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

David Hildenbrand May 12, 2017, 10:58 a.m. UTC
This adds the very basic infrastructure for s390x. As we compile for
z900, also QEMU tcg can be used.

To cross compile:

$./configure --arch=s390x --cross-prefix=/usr/bin/s390x-linux-gnu-
$ make

Please note that for now, nothing will be compiled, as there is no test
to compile. A basic self test will be added in the following patches.

smp and stack unwinding is not supported yet. sclp console output will
be added in the following patches.

Parts based on a prototype by Thomas Huth.

Signed-off-by: David Hildenbrand <david@redhat.com>
---
 configure                |  2 +-
 lib/s390x/asm/barrier.h  | 16 ++++++++++++++
 lib/s390x/asm/io.h       | 17 +++++++++++++++
 lib/s390x/asm/page.h     | 16 ++++++++++++++
 lib/s390x/asm/spinlock.h | 16 ++++++++++++++
 lib/s390x/asm/stack.h    | 21 ++++++++++++++++++
 lib/s390x/io.c           | 48 +++++++++++++++++++++++++++++++++++++++++
 lib/s390x/stack.c        | 28 ++++++++++++++++++++++++
 s390x/Makefile           | 32 +++++++++++++++++++++++++++
 s390x/cstart64.S         | 39 +++++++++++++++++++++++++++++++++
 s390x/flat.lds           | 42 ++++++++++++++++++++++++++++++++++++
 s390x/run                | 56 ++++++++++++++++++++++++++++++++++++++++++++++++
 s390x/unittests.cfg      | 19 ++++++++++++++++
 13 files changed, 351 insertions(+), 1 deletion(-)
 create mode 100644 lib/s390x/asm/barrier.h
 create mode 100644 lib/s390x/asm/io.h
 create mode 100644 lib/s390x/asm/page.h
 create mode 100644 lib/s390x/asm/spinlock.h
 create mode 100644 lib/s390x/asm/stack.h
 create mode 100644 lib/s390x/io.c
 create mode 100644 lib/s390x/stack.c
 create mode 100644 s390x/Makefile
 create mode 100644 s390x/cstart64.S
 create mode 100644 s390x/flat.lds
 create mode 100755 s390x/run
 create mode 100644 s390x/unittests.cfg

Comments

Christian Borntraeger May 15, 2017, 9:19 a.m. UTC | #1
Nice to see somebody doing this for s390x.


On 05/12/2017 12:58 PM, David Hildenbrand wrote:
[...]

> diff --git a/s390x/Makefile b/s390x/Makefile
> new file mode 100644
> index 0000000..f9468bb
> --- /dev/null
> +++ b/s390x/Makefile
> @@ -0,0 +1,32 @@
> +all: test_cases
> +
> +test_cases: $(tests)
> +
> +CFLAGS += -std=gnu99
> +CFLAGS += -ffreestanding
> +CFLAGS += -Wextra
> +CFLAGS += -I lib
> +CFLAGS += -O2
> +CFLAGS += -msoft-float


If you enable the AFP register control bit in your startup code, you can probably
avoid the soft-float thing.
David Hildenbrand May 16, 2017, 7:54 a.m. UTC | #2
On 15.05.2017 11:19, Christian Borntraeger wrote:
> Nice to see somebody doing this for s390x.
> 
> 
> On 05/12/2017 12:58 PM, David Hildenbrand wrote:
> [...]
> 
>> diff --git a/s390x/Makefile b/s390x/Makefile
>> new file mode 100644
>> index 0000000..f9468bb
>> --- /dev/null
>> +++ b/s390x/Makefile
>> @@ -0,0 +1,32 @@
>> +all: test_cases
>> +
>> +test_cases: $(tests)
>> +
>> +CFLAGS += -std=gnu99
>> +CFLAGS += -ffreestanding
>> +CFLAGS += -Wextra
>> +CFLAGS += -I lib
>> +CFLAGS += -O2
>> +CFLAGS += -msoft-float
> 
> 
> If you enable the AFP register control bit in your startup code, you can probably
> avoid the soft-float thing.
> 

Looks like we can drop that completely.

a) no floating point operations are used either way.

b) adding a very basic division results in

static void test_fp(void)
{
	double a, b;

	b = 6.5;
	a = 2.0;

	b = b / a;

	report("test fp", b == 3.25);
}

(compiled with -O0)

s390x/selftest.o: In function `test_fp':
/home/dhildenb/git/kvm-unit-tests/s390x/selftest.c:21: undefined
reference to `__divdf3'
/home/dhildenb/git/kvm-unit-tests/s390x/selftest.c:23: undefined
reference to `__eqdf2'

So we would need a soft float lib (as we're using -nostdlib)

c) dropping -msoft-float

A DDB (DIVIDE long BFP) is generated. That seems to work under TCG
without any exception. I assume the check for AFP-register control is
missing. I assume, that test would not pass under KVM.


For now I will simply drop -msoft-float.

Thanks!
Christian Borntraeger May 16, 2017, 7:58 a.m. UTC | #3
On 05/16/2017 09:54 AM, David Hildenbrand wrote:
> On 15.05.2017 11:19, Christian Borntraeger wrote:
>> Nice to see somebody doing this for s390x.
>>
>>
>> On 05/12/2017 12:58 PM, David Hildenbrand wrote:
>> [...]
>>
>>> diff --git a/s390x/Makefile b/s390x/Makefile
>>> new file mode 100644
>>> index 0000000..f9468bb
>>> --- /dev/null
>>> +++ b/s390x/Makefile
>>> @@ -0,0 +1,32 @@
>>> +all: test_cases
>>> +
>>> +test_cases: $(tests)
>>> +
>>> +CFLAGS += -std=gnu99
>>> +CFLAGS += -ffreestanding
>>> +CFLAGS += -Wextra
>>> +CFLAGS += -I lib
>>> +CFLAGS += -O2
>>> +CFLAGS += -msoft-float
>>
>>
>> If you enable the AFP register control bit in your startup code, you can probably
>> avoid the soft-float thing.
>>
> 
> Looks like we can drop that completely.
> 
> a) no floating point operations are used either way.
> 
> b) adding a very basic division results in
> 
> static void test_fp(void)
> {
> 	double a, b;
> 
> 	b = 6.5;
> 	a = 2.0;
> 
> 	b = b / a;
> 
> 	report("test fp", b == 3.25);
> }
> 
> (compiled with -O0)
> 
> s390x/selftest.o: In function `test_fp':
> /home/dhildenb/git/kvm-unit-tests/s390x/selftest.c:21: undefined
> reference to `__divdf3'
> /home/dhildenb/git/kvm-unit-tests/s390x/selftest.c:23: undefined
> reference to `__eqdf2'
> 
> So we would need a soft float lib (as we're using -nostdlib)
> 
> c) dropping -msoft-float
> 
> A DDB (DIVIDE long BFP) is generated. That seems to work under TCG
> without any exception. I assume the check for AFP-register control is
> missing. I assume, that test would not pass under KVM.
> 
> 
> For now I will simply drop -msoft-float.

This will allow gcc to spill/fill into floating point registers, which are
not all available without afp-register control. It will probably work because
the gr->fpr move will not be used for -march=z900, but I suggest to not rely
on that.
David Hildenbrand May 16, 2017, 8:21 a.m. UTC | #4
On 16.05.2017 09:58, Christian Borntraeger wrote:
> On 05/16/2017 09:54 AM, David Hildenbrand wrote:
>> On 15.05.2017 11:19, Christian Borntraeger wrote:
>>> Nice to see somebody doing this for s390x.
>>>
>>>
>>> On 05/12/2017 12:58 PM, David Hildenbrand wrote:
>>> [...]
>>>
>>>> diff --git a/s390x/Makefile b/s390x/Makefile
>>>> new file mode 100644
>>>> index 0000000..f9468bb
>>>> --- /dev/null
>>>> +++ b/s390x/Makefile
>>>> @@ -0,0 +1,32 @@
>>>> +all: test_cases
>>>> +
>>>> +test_cases: $(tests)
>>>> +
>>>> +CFLAGS += -std=gnu99
>>>> +CFLAGS += -ffreestanding
>>>> +CFLAGS += -Wextra
>>>> +CFLAGS += -I lib
>>>> +CFLAGS += -O2
>>>> +CFLAGS += -msoft-float
>>>
>>>
>>> If you enable the AFP register control bit in your startup code, you can probably
>>> avoid the soft-float thing.
>>>
>>
>> Looks like we can drop that completely.
>>
>> a) no floating point operations are used either way.
>>
>> b) adding a very basic division results in
>>
>> static void test_fp(void)
>> {
>> 	double a, b;
>>
>> 	b = 6.5;
>> 	a = 2.0;
>>
>> 	b = b / a;
>>
>> 	report("test fp", b == 3.25);
>> }
>>
>> (compiled with -O0)
>>
>> s390x/selftest.o: In function `test_fp':
>> /home/dhildenb/git/kvm-unit-tests/s390x/selftest.c:21: undefined
>> reference to `__divdf3'
>> /home/dhildenb/git/kvm-unit-tests/s390x/selftest.c:23: undefined
>> reference to `__eqdf2'
>>
>> So we would need a soft float lib (as we're using -nostdlib)
>>
>> c) dropping -msoft-float
>>
>> A DDB (DIVIDE long BFP) is generated. That seems to work under TCG
>> without any exception. I assume the check for AFP-register control is
>> missing. I assume, that test would not pass under KVM.
>>
>>
>> For now I will simply drop -msoft-float.
> 
> This will allow gcc to spill/fill into floating point registers, which are
> not all available without afp-register control. It will probably work because
> the gr->fpr move will not be used for -march=z900, but I suggest to not rely
> on that.
> 

Good point, so enabling AFP sounds right. And that should be valid on
any z/Architecture system (base feature set).

Thanks!
diff mbox

Patch

diff --git a/configure b/configure
index d152414..3690041 100755
--- a/configure
+++ b/configure
@@ -7,7 +7,7 @@  objcopy=objcopy
 objdump=objdump
 ar=ar
 addr2line=addr2line
-arch=`uname -m | sed -e 's/i.86/i386/;s/arm.*/arm/;s/ppc64.*/ppc64/'`
+arch=`uname -m | sed -e 's/i.86/i386/;s/arm.*/arm/;s/ppc64.*/ppc64/;s/s390x.*/s390x/'`
 host=$arch
 cross_prefix=
 endian=""
diff --git a/lib/s390x/asm/barrier.h b/lib/s390x/asm/barrier.h
new file mode 100644
index 0000000..5e77984
--- /dev/null
+++ b/lib/s390x/asm/barrier.h
@@ -0,0 +1,16 @@ 
+/*
+ * Copyright (c) 2017 Red Hat Inc
+ *
+ * Authors:
+ *  Thomas Huth <thuth@redhat.com>
+ *  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 <asm-generic/barrier.h>
+
+#ifndef _ASM_S390X_BARRIER_H_
+#define _ASM_S390X_BARRIER_H_
+
+#endif
diff --git a/lib/s390x/asm/io.h b/lib/s390x/asm/io.h
new file mode 100644
index 0000000..feb4115
--- /dev/null
+++ b/lib/s390x/asm/io.h
@@ -0,0 +1,17 @@ 
+/*
+ * Copyright (c) 2017 Red Hat Inc
+ *
+ * Authors:
+ *  Thomas Huth <thuth@redhat.com>
+ *  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_IO_H_
+#define _ASMS390X_IO_H_
+
+#define __iomem
+
+#include <asm-generic/io.h>
+#endif
diff --git a/lib/s390x/asm/page.h b/lib/s390x/asm/page.h
new file mode 100644
index 0000000..c67b251
--- /dev/null
+++ b/lib/s390x/asm/page.h
@@ -0,0 +1,16 @@ 
+/*
+ * Copyright (c) 2017 Red Hat Inc
+ *
+ * Authors:
+ *  Thomas Huth <thuth@redhat.com>
+ *  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 <asm-generic/page.h>
+
+#ifndef _ASMS390X_PAGE_H_
+#define _ASMS390X_PAGE_H_
+
+#endif
diff --git a/lib/s390x/asm/spinlock.h b/lib/s390x/asm/spinlock.h
new file mode 100644
index 0000000..9d40a94
--- /dev/null
+++ b/lib/s390x/asm/spinlock.h
@@ -0,0 +1,16 @@ 
+/*
+ * Copyright (c) 2017 Red Hat Inc
+ *
+ * Authors:
+ *  Thomas Huth <thuth@redhat.com>
+ *  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 <asm-generic/spinlock.h>
+
+#ifndef __ASMS390X_SPINLOCK_H
+#define __ASMS390X_SPINLOCK_H
+
+#endif
diff --git a/lib/s390x/asm/stack.h b/lib/s390x/asm/stack.h
new file mode 100644
index 0000000..e36d975
--- /dev/null
+++ b/lib/s390x/asm/stack.h
@@ -0,0 +1,21 @@ 
+/*
+ * Copyright (c) 2017 Red Hat Inc
+ *
+ * Authors:
+ *  Thomas Huth <thuth@redhat.com>
+ *  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_STACK_H_
+#define _ASMS390X_STACK_H_
+
+#ifndef _STACK_H_
+#error Do not directly include <asm/stack.h>. Just use <stack.h>.
+#endif
+
+#define HAVE_ARCH_BACKTRACE_FRAME
+#define HAVE_ARCH_BACKTRACE
+
+#endif
diff --git a/lib/s390x/io.c b/lib/s390x/io.c
new file mode 100644
index 0000000..a652124
--- /dev/null
+++ b/lib/s390x/io.c
@@ -0,0 +1,48 @@ 
+/*
+ * s390x io implementation
+ *
+ * Copyright (c) 2017 Red Hat Inc
+ *
+ * Authors:
+ *  Thomas Huth <thuth@redhat.com>
+ *  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/spinlock.h>
+
+extern void setup_args_progname(const char *args);
+extern char ipl_args[];
+
+static struct spinlock lock;
+
+void puts(const char *s)
+{
+	spin_lock(&lock);
+	/* FIXME */
+	(void)s;
+	spin_unlock(&lock);
+}
+
+static void sigp_stop()
+{
+	register unsigned long status asm ("1") = 0;
+	register unsigned long cpu asm ("2") = 0;
+
+	asm volatile(
+		"	sigp %0,%1,0(%2)\n"
+		: "+d" (status)  : "d" (cpu), "d" (5) : "cc");
+}
+
+void setup()
+{
+	setup_args_progname(ipl_args);
+}
+
+void exit(int code)
+{
+	printf("\nEXIT: STATUS=%d\n", ((code) << 1) | 1);
+	sigp_stop();
+}
diff --git a/lib/s390x/stack.c b/lib/s390x/stack.c
new file mode 100644
index 0000000..cd34b20
--- /dev/null
+++ b/lib/s390x/stack.c
@@ -0,0 +1,28 @@ 
+/*
+ * s390x stack implementation
+ *
+ * Copyright (c) 2017 Red Hat Inc
+ *
+ * Authors:
+ *  Thomas Huth <thuth@redhat.com>
+ *  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 <stack.h>
+
+int backtrace_frame(const void *frame, const void **return_addrs, int max_depth)
+{
+	printf("TODO: Implement backtrace_frame(%p, %p, %d) function!\n",
+	       frame, return_addrs, max_depth);
+	return 0;
+}
+
+int backtrace(const void **return_addrs, int max_depth)
+{
+	printf("TODO: Implement backtrace(%p, %d) function!\n",
+	       return_addrs, max_depth);
+	return 0;
+}
diff --git a/s390x/Makefile b/s390x/Makefile
new file mode 100644
index 0000000..f9468bb
--- /dev/null
+++ b/s390x/Makefile
@@ -0,0 +1,32 @@ 
+all: test_cases
+
+test_cases: $(tests)
+
+CFLAGS += -std=gnu99
+CFLAGS += -ffreestanding
+CFLAGS += -Wextra
+CFLAGS += -I lib
+CFLAGS += -O2
+CFLAGS += -msoft-float
+CFLAGS += -march=z900
+LDFLAGS += -nostdlib
+
+# We want to keep intermediate files
+.PRECIOUS: %.o
+
+cflatobjs += lib/util.o
+cflatobjs += lib/alloc.o
+cflatobjs += lib/s390x/io.o
+cflatobjs += lib/s390x/stack.o
+
+cstart.o = $(TEST_DIR)/cstart64.o
+
+FLATLIBS = $(libcflat)
+%.elf: %.o $(FLATLIBS) s390x/flat.lds $(cstart.o)
+	$(CC) $(CFLAGS) -c -o $(@:.elf=.aux.o) lib/auxinfo.c -DPROGNAME=\"$@\"
+	$(CC) $(LDFLAGS) -o $@ -T s390x/flat.lds -Ttext=0x10000 \
+		$(filter %.o, $^) $(FLATLIBS) $(@:.elf=.aux.o)
+	$(RM) $(@:.elf=.aux.o)
+
+arch_clean:
+	$(RM) $(TEST_DIR)/*.{o,elf} $(TEST_DIR)/.*.d lib/s390x/.*.d
diff --git a/s390x/cstart64.S b/s390x/cstart64.S
new file mode 100644
index 0000000..b5741c2
--- /dev/null
+++ b/s390x/cstart64.S
@@ -0,0 +1,39 @@ 
+/*
+ * s390x startup code
+ *
+ * Copyright (c) 2017 Red Hat Inc
+ *
+ * Authors:
+ *  Thomas Huth <thuth@redhat.com>
+ *  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.
+ */
+.section .init
+
+/* entry point - for KVM + TCG we directly start in 64 bit mode */
+	.globl start
+start:
+	/* setup stack */
+	larl	%r15, stacktop
+	/* setup initial PSW mask */
+	larl	%r1, initital_psw
+	lpswe	0(%r1)
+init_psw_cont:
+	/* call setup() */
+	brasl	%r14, setup
+	/* forward test parameter */
+	larl	%r2, __argc
+	llgf	%r2, 0(%r2)
+	larl	%r3, __argv
+	/* call to main() */
+	brasl	%r14, main
+	/* forward exit code */
+	lgr	%r3, %r2
+	/* call exit() */
+	j exit
+
+	.align	8
+initital_psw:
+	.quad	0x0000000180000000, init_psw_cont
diff --git a/s390x/flat.lds b/s390x/flat.lds
new file mode 100644
index 0000000..b6e2172
--- /dev/null
+++ b/s390x/flat.lds
@@ -0,0 +1,42 @@ 
+SECTIONS
+{
+	.text : {
+		*(.init)
+		. = 0x480;
+		ipl_args = .;
+		. = 0x600;
+		*(.text)
+		*(.text.*)
+	}
+	. = ALIGN(64K);
+	etext = .;
+	.opd : { *(.opd) }
+	. = ALIGN(16);
+	.dynamic : {
+		dynamic_start = .;
+		*(.dynamic)
+	}
+	.dynsym : {
+		dynsym_start = .;
+		*(.dynsym)
+	}
+	.rela.dyn : { *(.rela*) }
+	. = ALIGN(16);
+	.data : {
+		*(.data)
+		*(.data.rel*)
+	}
+	. = ALIGN(16);
+	.rodata : { *(.rodata) *(.rodata.*) }
+	. = ALIGN(16);
+	.bss : { *(.bss) }
+	. = ALIGN(64K);
+	edata = .;
+	. += 64K;
+	. = ALIGN(64K);
+	/*
+	 * stackptr set with initial stack frame preallocated
+	 */
+	stackptr = . - 160;
+	stacktop = .;
+}
diff --git a/s390x/run b/s390x/run
new file mode 100755
index 0000000..cf333de
--- /dev/null
+++ b/s390x/run
@@ -0,0 +1,56 @@ 
+#!/usr/bin/env bash
+
+if [ -z "$STANDALONE" ]; then
+	if [ ! -f config.mak ]; then
+		echo "run ./configure && make first. See ./configure -h"
+		exit 2
+	fi
+	source config.mak
+	source scripts/arch-run.bash
+fi
+
+if [ -c /dev/kvm ]; then
+	if [ "$HOST" = "s390x" ] && [ "$ARCH" = "s390x" ]; then
+		kvm_available=yes
+	fi
+fi
+
+if [ "$ACCEL" = "kvm" ] && [ "$kvm_available" != "yes" ]; then
+	echo "KVM is needed, but not available on this host"
+	exit 2
+fi
+
+if [ -z "$ACCEL" ]; then
+	if [ "$kvm_available" = "yes" ]; then
+		ACCEL="kvm"
+	else
+		ACCEL="tcg"
+	fi
+fi
+
+qemu=$(search_qemu_binary)
+
+M='-machine s390-ccw-virtio'
+M+=",accel=$ACCEL"
+command="$qemu -nodefaults -nographic $M"
+command+=" -chardev stdio,id=con0 -device sclpconsole,chardev=con0"
+[ -f "$ENV" ] && command+=" -initrd $ENV"
+command+=" -kernel"
+command="$(timeout_cmd) $command"
+echo $command "$@"
+
+# We return the exit code via stdout, not via the QEMU return code
+lines=$(run_qemu $command "$@")
+ret=$?
+echo "$lines"
+if [ $ret -eq 1 ]; then
+	testret=$(grep '^EXIT: ' <<<"$lines" | sed 's/.*STATUS=\([0-9][0-9]*\).*/\1/')
+	if [ "$testret" ]; then
+		if [ $testret -eq 1 ]; then
+			ret=0
+		else
+			ret=$testret
+		fi
+	fi
+fi
+exit $ret
diff --git a/s390x/unittests.cfg b/s390x/unittests.cfg
new file mode 100644
index 0000000..b1e0b1e
--- /dev/null
+++ b/s390x/unittests.cfg
@@ -0,0 +1,19 @@ 
+##############################################################################
+# unittest configuration
+#
+# [unittest_name]
+# file = <name>.elf		# Name of the elf file to be used.
+# extra_params = -append <params...>	# Additional parameters used.
+# groups = <group_name1> <group_name2> ... # Used to identify test cases
+#					   # with run_tests -g ...
+#					   # Specify group_name=nodefault
+#					   # to have test not run by default
+# accel = kvm|tcg		# Optionally specify if test must run with
+#				# kvm or tcg. If not specified, then kvm will
+#				# be used when available.
+# timeout = <duration>		# Optionally specify a timeout.
+# check = <path>=<value> # check a file for a particular value before running
+#			 # a test. The check line can contain multiple files
+#			 # to check separated by a space but each check
+#			 # parameter needs to be of the form <path>=<value>
+##############################################################################