This is the mail archive of the
systemtap@sourceware.org
mailing list for the systemtap project.
[RFC][PATCH] Add s390x support in Systemtap
- From: David Wilder <dwilder at us dot ibm dot com>
- To: systemtap at sources dot redhat dot com
- Date: Tue, 19 Sep 2006 14:52:18 -0700
- Subject: [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