This is the mail archive of the systemtap@sourceware.org mailing list for the systemtap project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC][PATCH] Add s390x support in Systemtap


Here is the patch adding s390x (64-bit) support into Systemtap.
At this time I am not fully adding s390 (31-bit) native support because I am not sure anyone cares about the 31-bit any more.


I still have a few test failures I am working on. Here is the current test summery:

Date: 200609191805
User: root
Kernel: Linux 2.6.17-prep #4 SMP Wed Sep 6 19:04:03 CEST 2006 s390x s390x s390x GNU/Linux
Testsuite summary of failed tests
FAIL: probefunc:kernel.inline("context_switch") compilation
FAIL: absentstats (0 0)
FAIL: buildok/eighteen.stp
FAIL: buildok/twenty.stp
FAIL: buildok/twentythree.stp
FAIL: buildok/two.stp
FAIL: profile (timeout)
FAIL: profile
FAIL: queue_demo (timeout)
FAIL: queue_demo
FAIL: sysopen (0)
FAIL: transport normal - relayfs (0)
FAIL: /root/stap_testing_200609191805/src/testsuite/systemtap.stress/current.stp compilation
=== systemtap Summary ===


# of expected passes            212
# of unexpected failures        13
# of expected failures          103
# of unknown successes          1
# of known failures             4
# of untested testcases         1
runtest completed at Tue Sep 19 21:53:46 2006

--
David Wilder
IBM Linux Technology Center
Beaverton, Oregon, USA dwilder@us.ibm.com
(503)578-3789


diff --git a/src/runtime/arith.c b/src/runtime/arith.c
index fea7421..97121ae 100644
--- a/src/runtime/arith.c
+++ b/src/runtime/arith.c
@@ -25,6 +25,13 @@ long long _div64 (long long u, long long
 long long _mod64 (long long u, long long v);
 #endif
 
+/* 31 bit s390 suupport is not yet included, it may never be.
+#ifdef __s390__
+long long _div64 (long long u, long long v);
+long long _mod64 (long long u, long long v);
+#endif
+*/
+
 /** Divide x by y.  In case of division-by-zero,
  * set context error string, and return 0
  */
diff --git a/src/runtime/copy.c b/src/runtime/copy.c
index f4d906b..4d71686 100644
--- a/src/runtime/copy.c
+++ b/src/runtime/copy.c
@@ -88,6 +88,11 @@ do {									   \
 #elif defined (__powerpc64__) || defined (__ia64__)
 #define __stp_strncpy_from_user(dst,src,count,res) \
 	do { res = __strncpy_from_user(dst, src, count); } while(0)
+
+#elif defined (__s390__) || defined (__s390x__)
+#define __stp_strncpy_from_user(dst,src,count,res) \
+	do { res = strncpy_from_user(dst, src, count); } while(0)
+
 #endif
 
 /** Copy a NULL-terminated string from userspace.
diff --git a/src/runtime/current.c b/src/runtime/current.c
index 5dbc06e..809f253 100644
--- a/src/runtime/current.c
+++ b/src/runtime/current.c
@@ -44,6 +44,8 @@ unsigned long _stp_ret_addr (struct pt_r
 	return REG_LINK(regs);
 #elif defined (__ia64__)
 	return regs->b0;
+#elif defined (__s390__) || defined (__s390x__)
+	return regs->gprs[14];
 #else
 	#error Unimplemented architecture
 #endif
@@ -208,6 +210,37 @@ void _stp_sprint_regs(String str, struct
 	_stp_string_cat(str, "\n");
 }
 
+#elif defined (__s390x__) || defined (__s390__)
+
+#ifdef __s390x__
+#define GPRSIZE "%016lX "
+#else	/* s390 */
+#define GPRSIZE "%08lX "
+#endif
+
+void _stp_sprint_regs(String str, struct pt_regs * regs)
+{
+	char *mode;
+	int i;
+
+	mode = (regs->psw.mask & PSW_MASK_PSTATE) ? "User" : "Krnl";
+	_stp_sprintf(str,"%s PSW : ["GPRSIZE"] ["GPRSIZE"]",
+		mode, (void *) regs->psw.mask,
+		(void *) regs->psw.addr);
+
+#ifdef CONFIG_SMP
+	_stp_sprintf(str, " CPU: %d", smp_processor_id());
+#endif /* CONFIG_SMP */
+
+	for (i = 0; i < 16; i++) {
+		if ((i % 4) == 0) {
+			_stp_sprintf(str, "\n GPRS%02d: ", i);
+		}
+		_stp_sprintf(str, GPRSIZE, regs->gprs[i]);
+	}
+	_stp_string_cat(str, "\n");
+}
+
 #endif
 
 /** Print the registers.
diff --git a/src/runtime/loc2c-runtime.h b/src/runtime/loc2c-runtime.h
index c88ad97..493f019 100644
--- a/src/runtime/loc2c-runtime.h
+++ b/src/runtime/loc2c-runtime.h
@@ -112,6 +112,12 @@
 #define fetch_register(regno) ((intptr_t) c->regs->gpr[regno])
 #define store_register(regno) (c->regs->gpr[regno] = (value))
 
+#elif defined (__s390__) || defined (__s390x__)
+#undef fetch_register
+#undef store_register
+#define fetch_register(regno) ((intptr_t) c->regs->gprs[regno])
+#define store_register(regno) (c->regs->gprs[regno] = (value))
+
 #endif
 
 #if defined __i386__ || defined __x86_64__
@@ -254,8 +260,160 @@
       goto deref_fault;							      \
   })
 
+#elif defined (__s390__) || defined (__s390x__)
+
+#if defined __s390__
+#define __stp_get_asm(x, addr, err, size)			\
+({								\
+	asm volatile(						\
+		"0: mvc  0(%2,%4),0(%3)\n"			\
+		"1:\n"						\
+		".section .fixup,\"ax\"\n"			\
+		"2: lhi    %0,%5\n"				\
+		"   bras    1,3f\n"				\
+		"   .long  1b\n"				\
+		"3: l      1,0(1)\n"				\
+		"   br     1\n"					\
+		".previous\n"					\
+		".section __ex_table,\"a\"\n"			\
+		"   .align 4\n"					\
+		"   .long  0b,2b\n"				\
+		".previous"					\
+		: "+&d" (err), "=m" (x)				\
+		: "i" (size),"a"(addr),				\
+		"a" (&(x)),"K" (-EFAULT)			\
+		: "cc", "1" );					\
+})
+
+#define __stp_put_asm(x, addr, err, size)			\
+({								\
+	asm volatile(						\
+		"0: mvc  0(%1,%2),0(%3)\n"			\
+		"1:\n"						\
+		".section .fixup,\"ax\"\n"			\
+		"2: lhi    %0,%5\n"				\
+		"   bras    1,3f\n"				\
+		"   .long  1b\n"				\
+		"3: l      1,0(1)\n"				\
+		"   br     1\n"					\
+		".previous\n"					\
+		".section __ex_table,\"a\"\n"			\
+		"   .align 4\n"					\
+		"   .long  0b,2b\n"				\
+		".previous"					\
+		: "+&d" (err)					\
+		: "i" (size), "a" (addr),			\
+		"a" (&(x)),"K" (-EFAULT)			\
+		: "cc", "1");					\
+})
+
+#else /* s390x */
+
+#define __stp_get_asm(x, addr, err, size)			\
+({								\
+	asm volatile(						\
+		"0: mvc  0(%2,%4),0(%3)\n"			\
+		"1:\n"						\
+		".section .fixup,\"ax\"\n"			\
+		"2: lghi    %0,%5\n"				\
+		"   jg     1b\n"				\
+		".previous\n"					\
+		".section __ex_table,\"a\"\n"			\
+		"   .align 8\n"					\
+		"   .quad  0b,2b\n"				\
+		".previous"					\
+		: "+&d" (err), "=m" (x)				\
+		: "i" (size),"a"(addr),				\
+		"a" (&(x)),"K" (-EFAULT)			\
+		: "cc");					\
+})
+
+#define __stp_put_asm(x, addr, err, size)			\
+({								\
+	asm volatile(						\
+		"0: mvc  0(%1,%2),0(%3)\n"			\
+		"1:\n"						\
+		".section .fixup,\"ax\"\n"			\
+		"2: lghi    %0,%4\n"				\
+		"   jg     1b\n"				\
+		".previous\n"					\
+		".section __ex_table,\"a\"\n"			\
+		"   .align 8\n"					\
+		"   .quad  0b,2b\n"				\
+		".previous"					\
+		: "+&d" (err)					\
+		: "i" (size),"a"(addr),				\
+		"a"(&(x)),"K"(-EFAULT)				\
+		: "cc");					\
+})
 #endif
 
+#define deref(size, addr)					\
+({								\
+	u8 _b; u16 _w; u32 _l; u64 _q;				\
+	int _bad = 0;						\
+	intptr_t _v = 0;					\
+	switch (size) {						\
+	case 1: {						\
+		__stp_get_asm(_b, addr, _bad, 1);		\
+		_v = _b;					\
+		break;						\
+		};						\
+	case 2: {						\
+		__stp_get_asm(_w, addr, _bad, 2);		\
+		_v = _w;					\
+		break;						\
+		};						\
+	case 4: {						\
+		__stp_get_asm(_l, addr, _bad, 4);		\
+		_v = _l;					\
+		break;						\
+		};						\
+	case 8: {						\
+		__stp_get_asm(_q, addr, _bad, 8);		\
+		_v = _q;					\
+		break;						\
+		};						\
+	default:						\
+		_bad = -EFAULT;					\
+	}							\
+	if (_bad)						\
+		goto deref_fault;				\
+	_v;							\
+})
+
+#define deref_store(size, addr, value)				\
+({								\
+	int _bad = 0;						\
+	switch (size) {						\
+	case 1:{						\
+		u8 _x = value;					\
+		__stp_put_asm(_x, addr, _bad,1);		\
+		break;						\
+		};						\
+	case 2:{ 						\
+		u16 _x = value;					\
+		__stp_put_asm(_x, addr, _bad,2);		\
+		break;						\
+		};						\
+	case 4:{						\
+		u32 _x = value;					\
+		__stp_put_asm(_x, addr, _bad,4);		\
+		break;						\
+		};						\
+	case 8:	{						\
+		u64 _x = value;					\
+		__stp_put_asm(_x, addr, _bad,8);		\
+		break;						\
+		};						\
+	default:						\
+		break;						\
+	}							\
+	if (_bad)						\
+		goto deref_fault;				\
+})
+#endif /* (s390) || (s390x) */
+
 #define deref_string(dst, addr, maxbytes)				      \
   ({									      \
     uintptr_t _addr;							      \
diff --git a/src/runtime/regs.h b/src/runtime/regs.h
index 0e759d1..48487c4 100644
--- a/src/runtime/regs.h
+++ b/src/runtime/regs.h
@@ -32,6 +32,15 @@
 #define REG_SP(regs) regs->gpr[1]
 #define REG_LINK(regs) regs->link
 
+#elif defined (__s390__) || defined (__s390x__)
+#ifndef __s390x__
+#define PSW_ADDR_AMODE	0x80000000UL
+#else /* __s390x__ */
+#define PSW_ADDR_AMODE	0x0000000000000000UL
+#endif /* __s390x__ */
+#define REG_IP(regs)	((regs)->psw.addr) | PSW_ADDR_AMODE
+#define REG_SP(regs)	(regs)->gprs[15]
+
 #else
 #error "Unimplemented architecture"
 #endif
diff --git a/src/runtime/stack.c b/src/runtime/stack.c
index 73ac19c..bd6e6a6 100644
--- a/src/runtime/stack.c
+++ b/src/runtime/stack.c
@@ -217,6 +217,80 @@ static void __stp_stack_sprint (String s
 	} while (str->len < STP_STRING_SIZE);
 }
 
+#elif defined (__s390__) || defined (__s390x__)
+
+static unsigned long
+__stp_show_stack (String str, unsigned long sp, unsigned long low,
+		  unsigned long high, int verbose)
+{
+
+	struct stack_frame *sf;
+	struct pt_regs *regs;
+	unsigned long ip;
+
+	 while (1) {
+		sp = sp & PSW_ADDR_INSN;
+		/* fixme: verify  this is a kernel stack */
+		if (sp < low || sp > high - sizeof(*sf))
+			return sp;
+		sf = (struct stack_frame *) sp;
+		ip = sf->gprs[8] & PSW_ADDR_INSN;
+		if (verbose) {
+			_stp_sprintf(str, "[%016lx] [%016lx] ", sp, ip);
+			_stp_symbol_sprint(str, ip);
+			_stp_string_cat(str, "\n");
+		}else{
+			_stp_sprintf(str,"%lx ", ip);
+		}
+		/* Follow the back_chain */
+		while (1) {
+			low = sp;
+			sp = sf->back_chain & PSW_ADDR_INSN;
+			if (!sp)
+				break;
+			if (sp <= low || sp > high - sizeof(*sf))
+				return sp;
+			sf = (struct stack_frame *) sp;
+			ip = sf->gprs[8] & PSW_ADDR_INSN;
+			if (verbose) {
+                        	_stp_sprintf(str, "[%016lx] [%016lx] ", sp, ip);
+                        	_stp_symbol_sprint(str, ip);
+				_stp_string_cat(str, "\n");
+                	}else{
+				_stp_sprintf(str,"%lx ", ip);
+			}
+                }
+                /* Zero backchain detected, check for interrupt frame. */
+		sp = (unsigned long) (sf + 1);
+		if (sp <= low || sp > high - sizeof(*regs))
+			return sp;
+		regs = (struct pt_regs *) sp;
+		if (verbose) {
+			_stp_sprintf(str, "[%016lx] [%016lx] ", sp, ip);
+			_stp_symbol_sprint(str, ip);
+			_stp_string_cat(str, "\n");
+		}else{
+			_stp_sprintf(str,"%lx ", ip);
+		}
+		low = sp;
+		sp = regs->gprs[15];
+	}
+}
+
+static void __stp_stack_sprint (String str, unsigned long *_sp,
+				int verbose, int levels)
+{
+		unsigned long sp = (unsigned long)*_sp;
+
+		sp = __stp_show_stack(str, sp,
+			S390_lowcore.async_stack - ASYNC_SIZE,
+			S390_lowcore.async_stack,verbose);
+
+		__stp_show_stack(str, sp,
+			S390_lowcore.thread_info,
+			S390_lowcore.thread_info + THREAD_SIZE,verbose);
+}
+
 #else
 #error "Unsupported architecture"
 #endif

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]