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 04/13] mips: runtime and tapset code from cisco


Signed-off-by: Crestez Dan Leonard <cdleonard@gmail.com>
---
 runtime/linux/arith.c         |  25 +++-
 runtime/regs.c                | 117 ++++++++++++++++++
 runtime/stack-mips.c          |   7 ++
 runtime/stack.c               |   2 +
 runtime/syscall.h             |  49 ++++++++
 tapset/errno.stp              |   2 +
 tapset/linux/aux_syscalls.stp |   5 +-
 tapset/linux/scheduler.stp    |   2 +-
 tapset/linux/syscalls2.stp    |   8 ++
 tapset/mips/aux_syscalls.stp  |  44 +++++++
 tapset/mips/registers.stp     | 276 ++++++++++++++++++++++++++++++++++++++++++
 11 files changed, 533 insertions(+), 4 deletions(-)
 create mode 100644 runtime/stack-mips.c
 create mode 100644 tapset/mips/aux_syscalls.stp
 create mode 100644 tapset/mips/registers.stp

diff --git a/runtime/linux/arith.c b/runtime/linux/arith.c
index b64984a..9f65711 100644
--- a/runtime/linux/arith.c
+++ b/runtime/linux/arith.c
@@ -21,7 +21,8 @@
 /* Other 32-bit cpus will need to modify this file. */
 
 #if defined (__i386__) || defined(__arm__) || \
-	(defined(__powerpc__) && !defined(__powerpc64__))
+	(defined(__powerpc__) && !defined(__powerpc64__)) || \
+        (defined(__mips__) && !defined(__mips64))
 static long long _div64 (long long u, long long v);
 static long long _mod64 (long long u, long long v);
 #endif
@@ -116,7 +117,8 @@ static int _stp_random_pm (unsigned n)
 
 
 #if defined (__i386__) || defined (__arm__) || \
-	(defined(__powerpc__) && !defined(__powerpc64__))
+	(defined(__powerpc__) && !defined(__powerpc64__)) || \
+        (defined(__mips__) && !defined(__mips64))
 
 /* 64-bit division functions extracted from libgcc */
 typedef long long DWtype;
@@ -248,6 +250,25 @@ typedef union
 	   : "r" ((USItype) (a)),					\
 	     "r" ((USItype) (b)) __CLOBBER_CC );}
 
+#elif defined (__mips__)
+
+#define umul_ppmm(w1, w0, u, v)                                        \
+  __asm__ ("multu %2,%3"                                               \
+          : "=l" ((USItype) (w0)),                                     \
+            "=h" ((USItype) (w1))                                      \
+          : "d" ((USItype) (u)),                                       \
+            "d" ((USItype) (v)))
+
+#if !defined (sub_ddmmss)
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  do {                                                                 \
+    UWtype __x;                                                        \
+    __x = (al) - (bl);                                                 \
+    (sh) = (ah) - (bh) - (__x > (al));                                 \
+    (sl) = __x;                                                        \
+  } while (0)
+#endif
+
 #endif
 
 #define __udiv_qrnnd_c(q, r, n1, n0, d) \
diff --git a/runtime/regs.c b/runtime/regs.c
index ade3ad9..8a3f365 100644
--- a/runtime/regs.c
+++ b/runtime/regs.c
@@ -3,6 +3,7 @@
  * Copyright (C) 2005, 2007 Red Hat Inc.
  * Copyright (C) 2005 Intel Corporation.
  * Copyright (C) 2007 Quentin Barnes.
+ * Copyright (C) 2009 Sony Corporation.
  *
  * This file is part of systemtap, and is free software.  You can
  * redistribute it and/or modify it under the terms of the GNU General
@@ -23,6 +24,122 @@
 
 #include "dyninst/regs.c"
 
+#elif defined (__mips__)
+/*
+ * Only o32 application has 32bit registers. N32 and N64 both
+ * should use 64bit registers regardless of pointer size
+ */
+static int _stp_probing_app_with_32bit_regs(struct pt_regs *regs)
+{
+	if (!regs)
+		return 0;
+	return (user_mode(regs) &&
+                test_tsk_thread_flag(current, TIF_32BIT_REGS));
+}
+
+void _stp_print_regs(struct pt_regs * regs)
+{
+#ifdef MIPS_PRINT_REGS_SHOW_SYMBOLS
+        /* it is too much stack to do symbol translation by default */
+    	char symbol_name[KSYM_SYMBOL_LEN];
+#endif /* MIPS_PRINT_REGS_SHOW_SYMBOLS */
+	const int field = 2 * sizeof(unsigned long);
+	unsigned int cause = regs->cp0_cause;
+	int i;
+
+	_stp_printf("Cpu %d\n", smp_processor_id());
+
+	/*
+	 * Saved main processor registers
+	 */
+	for (i = 0; i < 32;) {
+		if ((i % 4) == 0)
+			_stp_printf("$%2d   :", i);
+		if (i == 0)
+			_stp_printf(" %0*lx", field, 0UL);
+		else if (i == 26 || i == 27)
+			_stp_printf(" %*s", field, "");
+		else
+			_stp_printf(" %0*lx", field, regs->regs[i]);
+
+		i++;
+		if ((i % 4) == 0)
+			_stp_printf("\n");
+	}
+
+	_stp_printf("Hi    : %0*lx\n", field, regs->hi);
+	_stp_printf("Lo    : %0*lx\n", field, regs->lo);
+
+	/*
+	 * Saved cp0 registers
+	 */
+	_stp_printf("epc   : %0*lx ", field, regs->cp0_epc);
+#ifdef MIPS_PRINT_REGS_SHOW_SYMBOLSx
+        sprint_symbol(symbol_name, regs->cp0_epc);
+	_stp_printf("%s ", symbol_name);
+#endif /* MIPS_PRINT_REGS_SHOW_SYMBOLS */
+
+	_stp_printf("ra    : %0*lx ", field, regs->regs[31]);
+#ifdef MIPS_PRINT_REGS_SHOW_SYMBOLS
+        sprint_symbol(symbol_name, regs->regs[31]);
+	_stp_printf("%s", symbol_name);
+#endif /* MIPS_PRINT_REGS_SHOW_SYMBOLS */
+	_stp_printf("\n");
+
+	_stp_printf("Status: %08x    ", (uint32_t) regs->cp0_status);
+
+	if (current_cpu_data.isa_level == MIPS_CPU_ISA_I) {
+		if (regs->cp0_status & ST0_KUO)
+			_stp_printf("KUo ");
+		if (regs->cp0_status & ST0_IEO)
+			_stp_printf("IEo ");
+		if (regs->cp0_status & ST0_KUP)
+			_stp_printf("KUp ");
+		if (regs->cp0_status & ST0_IEP)
+			_stp_printf("IEp ");
+		if (regs->cp0_status & ST0_KUC)
+			_stp_printf("KUc ");
+		if (regs->cp0_status & ST0_IEC)
+			_stp_printf("IEc ");
+	} else {
+		if (regs->cp0_status & ST0_KX)
+			_stp_printf("KX ");
+		if (regs->cp0_status & ST0_SX)
+			_stp_printf("SX ");
+		if (regs->cp0_status & ST0_UX)
+			_stp_printf("UX ");
+		switch (regs->cp0_status & ST0_KSU) {
+		case KSU_USER:
+			_stp_printf("USER ");
+			break;
+		case KSU_SUPERVISOR:
+			_stp_printf("SUPERVISOR ");
+			break;
+		case KSU_KERNEL:
+			_stp_printf("KERNEL ");
+			break;
+		default:
+			_stp_printf("BAD_MODE ");
+			break;
+		}
+		if (regs->cp0_status & ST0_ERL)
+			_stp_printf("ERL ");
+		if (regs->cp0_status & ST0_EXL)
+			_stp_printf("EXL ");
+		if (regs->cp0_status & ST0_IE)
+			_stp_printf("IE ");
+	}
+
+	_stp_printf("\n");
+
+	_stp_printf("Cause : %08x\n", cause);
+
+	cause = (((cause) & CAUSEF_EXCCODE) >> CAUSEB_EXCCODE);
+	if (1 <= cause && cause <= 5)
+		_stp_printf("BadVA : %0*lx\n", field, regs->cp0_badvaddr);
+
+	_stp_printf("PrId  : %08x\n", read_c0_prid());
+}
 #endif
 
 
diff --git a/runtime/stack-mips.c b/runtime/stack-mips.c
new file mode 100644
index 0000000..e1eb995
--- /dev/null
+++ b/runtime/stack-mips.c
@@ -0,0 +1,7 @@
+static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels,
+			       struct task_struct *tsk,
+			       struct unwind_context *context,
+			       struct uretprobe_instance *ri, int uregs_valid)
+{
+  /* TODO: fix, it is just stub for now */
+}
diff --git a/runtime/stack.c b/runtime/stack.c
index 769f7bc..ba47f37 100644
--- a/runtime/stack.c
+++ b/runtime/stack.c
@@ -78,6 +78,8 @@ static int _stp_valid_pc_addr(unsigned long addr, struct task_struct *tsk)
 #include "stack-ia64.c"
 #elif defined (__arm__)
 #include "stack-arm.c"
+#elif defined (__mips__)
+#include "stack-mips.c"
 #elif defined (__s390__)
 #include "stack-s390.c"
 #else
diff --git a/runtime/syscall.h b/runtime/syscall.h
index 32af78c..447adb1 100644
--- a/runtime/syscall.h
+++ b/runtime/syscall.h
@@ -77,6 +77,55 @@
 #define MREMAP_SYSCALL_NO(tsk)		1156
 #endif
 
+#if defined(__mips__)
+/* n64 values: scall64-64.S */
+#define MMAP_SYSCALL_NO_MIPS_N64	5009
+#define MMAP2_SYSCALL_NO_MIPS_N64	((unsigned long)-1) /* does not exits */
+#define MPROTECT_SYSCALL_NO_MIPS_N64	5010
+#define MUNMAP_SYSCALL_NO_MIPS_N64	5011
+#define MREMAP_SYSCALL_NO_MIPS_N64	5024
+
+/* n32 values: scall64-n32.S */
+#define MMAP_SYSCALL_NO_MIPS_N32	6009
+#define MMAP2_SYSCALL_NO_MIPS_N32	((unsigned long)-1) /* does not exits */
+#define MPROTECT_SYSCALL_NO_MIPS_N32	6010
+#define MUNMAP_SYSCALL_NO_MIPS_N32	6011
+#define MREMAP_SYSCALL_NO_MIPS_N32	6024
+
+/* o32 values: scall32-o32.S */
+#define MMAP_SYSCALL_NO_MIPS_O32	4090
+#define MMAP2_SYSCALL_NO_MIPS_O32	4210
+#define MPROTECT_SYSCALL_NO_MIPS_O32	4125
+#define MUNMAP_SYSCALL_NO_MIPS_O32	4091
+#define MREMAP_SYSCALL_NO_MIPS_O32	4167
+
+#define MMAP_SYSCALL_NO(tsk) ((test_tsk_thread_flag((tsk), TIF_32BIT_ADDR)) ?	   \
+			      ((test_tsk_thread_flag((tsk), TIF_32BIT_REGS)) ?	   \
+			       (MMAP_SYSCALL_NO_MIPS_O32) :			   \
+			       (MMAP_SYSCALL_NO_MIPS_N32)) :			   \
+			      (MMAP_SYSCALL_NO_MIPS_N64))
+#define MMAP2_SYSCALL_NO(tsk) ((test_tsk_thread_flag((tsk), TIF_32BIT_ADDR)) ?	   \
+			      ((test_tsk_thread_flag((tsk), TIF_32BIT_REGS)) ?	   \
+			       (MMAP2_SYSCALL_NO_MIPS_O32) :			   \
+			       (MMAP2_SYSCALL_NO_MIPS_N32)) :			   \
+			      (MMAP2_SYSCALL_NO_MIPS_N64))
+#define MPROTECT_SYSCALL_NO(tsk) ((test_tsk_thread_flag((tsk), TIF_32BIT_ADDR)) ?  \
+			      ((test_tsk_thread_flag((tsk), TIF_32BIT_REGS)) ?	   \
+			       (MPROTECT_SYSCALL_NO_MIPS_O32) :			   \
+			       (MPROTECT_SYSCALL_NO_MIPS_N32)) :		   \
+			      (MPROTECT_SYSCALL_NO_MIPS_N64))
+#define MUNMAP_SYSCALL_NO(tsk) ((test_tsk_thread_flag((tsk), TIF_32BIT_ADDR)) ?	   \
+			      ((test_tsk_thread_flag((tsk), TIF_32BIT_REGS)) ?	   \
+			       (MUNMAP_SYSCALL_NO_MIPS_O32) :			   \
+			       (MUNMAP_SYSCALL_NO_MIPS_N32)) :			   \
+			      (MUNMAP_SYSCALL_NO_MIPS_N64))
+#define MREMAP_SYSCALL_NO(tsk) ((test_tsk_thread_flag((tsk), TIF_32BIT_ADDR)) ?	   \
+			      ((test_tsk_thread_flag((tsk), TIF_32BIT_REGS)) ?	   \
+			       (MREMAP_SYSCALL_NO_MIPS_O32) :			   \
+			       (MREMAP_SYSCALL_NO_MIPS_N32)) :			   \
+			      (MREMAP_SYSCALL_NO_MIPS_N64))
+#endif
+
 #if defined(__s390__) || defined(__s390x__)
 #define MMAP_SYSCALL_NO(tsk)		90
 #define MMAP2_SYSCALL_NO(tsk)		192
diff --git a/tapset/errno.stp b/tapset/errno.stp
index df1ccbd..7e1d2f4 100644
--- a/tapset/errno.stp
+++ b/tapset/errno.stp
@@ -390,6 +390,8 @@ static long _stp_returnval(struct pt_regs *regs) {
 		return regs->regs[0];
 #elif defined (__arm__)
 		return regs->ARM_r0;
+#elif defined (__mips__)
+		return regs->regs[2];
 #else
 		_stp_error("returnval() not defined for this architecture");
 		return 0;
diff --git a/tapset/linux/aux_syscalls.stp b/tapset/linux/aux_syscalls.stp
index 53e73f8..a5e7b56 100644
--- a/tapset/linux/aux_syscalls.stp
+++ b/tapset/linux/aux_syscalls.stp
@@ -2745,7 +2745,7 @@ static void _stp_sigaction_str(struct sigaction *act, char *ptr, int len)
       strlcat (ptr, ", ", len);
       _stp_lookup_or_str(_stp_sa_flags_list, act->sa_flags, ptr, len);
       strlcat (ptr, ", ", len);
-#if !defined (__ia64__)
+#if !defined (__ia64__) && !defined (__mips__)
       slen = strlen(ptr);
       _stp_snprintf(ptr + slen, len - slen,
 		    "0x%lx, [", (long)act->sa_restorer);
@@ -3085,6 +3085,9 @@ function __is_user_regs:long (regs:long)
 #elif defined(__arm__)
 	long cpsr = kread(&regs->ARM_cpsr);
 	STAP_RETVALUE = ((cpsr & 0xf) == 0);
+#elif defined(__mips__) /* TODO kamensky: need to test */
+	unsigned long cp0 = kread(&regs->cp0_status);
+	THIS->__retvalue = ((cp0 & 0x08) == 8);
 #elif defined(__s390__) || defined(__s390x__)
 	unsigned long mask = kread(&regs->psw.mask);
 	STAP_RETVALUE = ((mask & PSW_MASK_PSTATE) != 0);
diff --git a/tapset/linux/scheduler.stp b/tapset/linux/scheduler.stp
index 7596a46..d45116b 100644
--- a/tapset/linux/scheduler.stp
+++ b/tapset/linux/scheduler.stp
@@ -117,7 +117,7 @@ probe scheduler.balance = kernel.function("idle_balance") ?
  */
 
 probe scheduler.ctxswitch = kernel.trace("sched_switch") !,
-%( arch != "x86_64" && arch != "ia64" && arch != "arm" %?
+%( arch != "x86_64" && arch != "ia64" && arch != "arm" && arch != "mips" %?
 	kernel.function("__switch_to")
 %:
 	kernel.function("context_switch")
diff --git a/tapset/linux/syscalls2.stp b/tapset/linux/syscalls2.stp
index 08d4e36..7832dd4 100644
--- a/tapset/linux/syscalls2.stp
+++ b/tapset/linux/syscalls2.stp
@@ -1553,7 +1553,11 @@ probe syscall.rt_sigreturn.return =
 	kernel.function("sys32_rt_sigreturn").return ?
 {
 	name = "rt_sigreturn"
+%( arch == "mips" %?
+	retstr = "void"
+%:
 	retstr = return_str(1, $return)
+%)
 }
 
 # rt_sigsuspend ______________________________________________
@@ -3143,7 +3147,11 @@ probe syscall.sigreturn.return = kernel.function("sys_sigreturn").return ?,
                                  kernel.function("sys32_sigreturn").return ?
 {
 	name = "sigreturn"
+%( arch == "mips" %?
+	retstr = "void"
+%:
 	retstr = return_str(1, $return)
+%)
 }
 
 # sigsuspend _________________________________________________
diff --git a/tapset/mips/aux_syscalls.stp b/tapset/mips/aux_syscalls.stp
new file mode 100644
index 0000000..5de5485
--- /dev/null
+++ b/tapset/mips/aux_syscalls.stp
@@ -0,0 +1,44 @@
+# arch-specific requests of ptrace ___________________________
+#
+function _arch_ptrace_argstr(request, pid, addr, data)
+{
+	if (request == %{ PTRACE_GETREGS %})
+		// TODO: Retrieve *data in .return
+		return sprintf ("PTRACE_GETREGS, %d, data=%p", pid, data)
+	if (request == %{ PTRACE_SETREGS %})
+		// TODO: Retrieve *data here
+		return sprintf ("PTRACE_SETREGS, %d, data=%p", pid, data)
+	if (request == %{ PTRACE_GETFPREGS %})
+		// TODO: Retrieve *data in .return
+		return sprintf ("PTRACE_GETFPREGS, %d, data=%p", pid, data)
+	if (request == %{ PTRACE_SETFPREGS %})
+		// TODO: Retrieve *data here
+		return sprintf ("PTRACE_SETFPREGS, %d, data=%p", pid, data)
+	if (request == %{ PTRACE_PEEKTEXT_3264 %})
+		// TODO: Retrieve *data in .return
+		return sprintf ("PTRACE_PEEKTEXT_3264, %d, *addr=%p, data=%p", pid, user_long(addr), data)
+	if (request == %{ PTRACE_PEEKDATA_3264 %})
+		// TODO: Retrieve *data in .return
+		return sprintf ("PTRACE_PEEKDATA_3264, %d, *addr=%p, data=%p", pid, user_long(addr), data)
+	if (request == %{ PTRACE_POKETEXT_3264 %})
+		return sprintf ("PTRACE_POKETEXT_3264, %d, *addr=%p, data=%p", pid, user_long(addr), data)
+	if (request == %{ PTRACE_POKEDATA_3264 %})
+		return sprintf ("PTRACE_POKEDATA_3264, %d, *addr=%p, data=%p", pid, user_long(addr), data)
+	if (request == %{ PTRACE_GET_THREAD_AREA %})
+		// TODO: Retrieve *data in .return
+		return sprintf ("PTRACE_GET_THREAD_AREA, %d, index=%d, data=%p", pid, addr, data)
+	if (request == %{ PTRACE_GET_THREAD_AREA_3264 %})
+		// TODO: Retrieve *data in .return
+		return sprintf ("PTRACE_GET_THREAD_AREA_3264, %d, index=%d, data=%p", pid, addr, data)
+	if (request == %{ PTRACE_GET_WATCH_REGS %})
+		// TODO: Retrieve *data in .return
+		return sprintf ("PTRACE_GET_WATCH_REGS, %d, data=%p", pid, data)
+	if (request == %{ PTRACE_SET_WATCH_REGS %})
+		// TODO: Retrieve *data here
+		return sprintf ("PTRACE_SET_WATCH_REGS, %d, data=%p", pid, data)
+}
+
+function _ptrace_return_arch_prctl_addr:long(request:long, addr:long, data:long)
+{
+	return 0
+}
diff --git a/tapset/mips/registers.stp b/tapset/mips/registers.stp
new file mode 100644
index 0000000..be50f76
--- /dev/null
+++ b/tapset/mips/registers.stp
@@ -0,0 +1,276 @@
+/* Dwarfless register access for mips */
+
+global _reg_offsets, _stp_regs_registered
+
+function _stp_register_regs() {
+%( CONFIG_64BIT == "y" %?
+        /* n32/n64 registers naming scheme */
+	/* Same order as struct pt_regs */
+	_reg_offsets["zero"] = 0
+	_reg_offsets["at"] = 8
+	_reg_offsets["v0"] = 16
+	_reg_offsets["v1"] = 24
+	_reg_offsets["a0"] = 32
+	_reg_offsets["a1"] = 40
+	_reg_offsets["a2"] = 48
+	_reg_offsets["a3"] = 56
+	_reg_offsets["a4"] = 64
+	_reg_offsets["a5"] = 72
+	_reg_offsets["a6"] = 80
+	_reg_offsets["a7"] = 88
+	_reg_offsets["t0"] = 96
+	_reg_offsets["t1"] = 104
+	_reg_offsets["t2"] = 112
+	_reg_offsets["t3"] = 120
+	_reg_offsets["s0"] = 128
+	_reg_offsets["s1"] = 136
+	_reg_offsets["s2"] = 144
+	_reg_offsets["s3"] = 152
+	_reg_offsets["s4"] = 160
+	_reg_offsets["s5"] = 168
+	_reg_offsets["s6"] = 176
+	_reg_offsets["s7"] = 184
+	_reg_offsets["t8"] = 192
+	_reg_offsets["t9"] = 200
+	_reg_offsets["k0"] = 208
+	_reg_offsets["k1"] = 216
+	_reg_offsets["gp"] = 224
+	_reg_offsets["sp"] = 232
+	_reg_offsets["s8"] = 240       _reg_offsets["fp"] = 240
+	_reg_offsets["ra"] = 248
+
+	_reg_offsets["status"] = 256
+	_reg_offsets["hi"] = 264
+	_reg_offsets["lo"] = 272
+
+        /*
+         * no CONFIG_CPU_HAS_SMARTMIPS support for now, if it is
+         * enabled below values will be wrong
+         */
+
+	_reg_offsets["badvaddr"] = 280
+	_reg_offsets["cause"] = 288
+	_reg_offsets["epc"] = 296
+
+        /* no cp0_tcstatus register for now */
+        /* no mpl and mtp registers for now */
+%:
+        /* o32 registers naming scheme */
+	/* Same order as struct pt_regs */
+	_reg_offsets["zero"] = 24
+	_reg_offsets["at"] = 28
+	_reg_offsets["v0"] = 32
+	_reg_offsets["v1"] = 36
+	_reg_offsets["a0"] = 40
+	_reg_offsets["a1"] = 44
+	_reg_offsets["a2"] = 48
+	_reg_offsets["a3"] = 52
+	_reg_offsets["t0"] = 56
+	_reg_offsets["t1"] = 60
+	_reg_offsets["t2"] = 64
+	_reg_offsets["t3"] = 68
+	_reg_offsets["t4"] = 72
+	_reg_offsets["t5"] = 76
+	_reg_offsets["t6"] = 80
+	_reg_offsets["t7"] = 84
+	_reg_offsets["s0"] = 88
+	_reg_offsets["s1"] = 92
+	_reg_offsets["s2"] = 96
+	_reg_offsets["s3"] = 100
+	_reg_offsets["s4"] = 104
+	_reg_offsets["s5"] = 108
+	_reg_offsets["s6"] = 112
+	_reg_offsets["s7"] = 116
+	_reg_offsets["t8"] = 120
+	_reg_offsets["t9"] = 124
+	_reg_offsets["k0"] = 128
+	_reg_offsets["k1"] = 132
+	_reg_offsets["gp"] = 136
+	_reg_offsets["sp"] = 140
+	_reg_offsets["s8"] = 144     _reg_offsets["fp"] = 144
+	_reg_offsets["ra"] = 148
+
+	_reg_offsets["status"] = 152
+	_reg_offsets["hi"] = 156
+	_reg_offsets["lo"] = 160
+
+        /*
+         * no CONFIG_CPU_HAS_SMARTMIPS support for now, if it is
+         * enabled below values will be wrong
+         */
+	_reg_offsets["badvaddr"] = 164
+	_reg_offsets["cause"] = 168
+	_reg_offsets["epc"] = 172
+
+        /* no cp0_tcstatus register for now */
+        /* no mpl and mtp registers for now */
+%)
+	_stp_regs_registered = 1
+}
+
+function probing_app_with_32bit_regs() %{ /* pure */
+        THIS->__retvalue = _stp_probing_app_with_32bit_regs(CONTEXT->regs);
+%}
+
+function _stp_get_register_by_offset:long (offset:long) %{ /* pure */
+	long value;
+	if (!CONTEXT->regs) {
+		CONTEXT->last_error = "No registers available in this context";
+		return;
+	}
+	if (THIS->offset < 0 || THIS->offset > sizeof(struct pt_regs) - sizeof(long)) {
+		snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer),
+				"Bad register offset: %lld",
+				(long long)THIS->offset);
+		CONTEXT->last_error = CONTEXT->error_buffer;
+		return;
+	}
+	memcpy(&value, ((char *)CONTEXT->regs) + THIS->offset, sizeof(value));
+	THIS->__retvalue = value;
+%}
+
+function _stp_sign_extend32:long (value:long) {
+	if (value & 0x80000000)
+		value |= (0xffffffff << 32)
+	return value
+}
+
+function _stp_register:long (name:string, sign_extend:long) {
+	if (!registers_valid()) {
+		error("cannot access CPU registers in this context")
+		return 0
+	}
+	if (!_stp_regs_registered)
+		_stp_register_regs()
+	offset = _reg_offsets[name]
+	if (offset == 0 && !(name in _reg_offsets)) {
+		error("Unknown register: " . name)
+		return 0
+	}
+	value = _stp_get_register_by_offset(offset)
+%( CONFIG_64BIT == "y" %?
+	if (probing_app_with_32bit_regs()) {
+%)
+		if (sign_extend)
+			value = _stp_sign_extend32(value)
+		else
+			value &= 0xffffffff
+%( CONFIG_64BIT == "y" %?
+	}
+%)
+	return value
+}
+
+/* Return the named register value as a signed value. */
+function register:long (name:string) {
+	return _stp_register(name, 1)
+}
+
+/*
+ * Return the named register value as an unsigned value.  Specifically,
+ * don't sign-extend the register value when promoting it to 64 bits.
+ */
+function u_register:long (name:string) {
+	return _stp_register(name, 0)
+}
+
+/*
+ * Return the value of function arg #argnum (1=first arg).
+ * If truncate=1, mask off the top 32 bits.
+ * If sign_extend=1 and (truncate=1 or the probepoint we've hit is in a
+ * 32-bit app), sign-extend the 32-bit value.
+ */
+function _stp_arg:long (argnum:long, sign_extend:long, truncate:long) {
+	val = 0
+	if (argnum < 1 || argnum > 8) {
+		error(sprintf("Cannot access arg(%d)", argnum))
+		return 0
+	}
+
+	if (argnum == 1)
+		val = u_register("a0")
+	else if (argnum == 2)
+		val = u_register("a1")
+	else if (argnum == 3)
+		val = u_register("a2")
+	else if (argnum == 4)
+		val = u_register("a3")
+	else if (argnum == 5)
+		val = u_register("a4")
+	else if (argnum == 6)
+		val = u_register("a5")
+	else if (argnum == 7)
+		val = u_register("a6")
+	else if (argnum == 8)
+		val = u_register("a7")
+
+	if (truncate) {
+		if (sign_extend)
+			val = _stp_sign_extend32(val)
+		else
+			/* High bits may be garbage. */
+			val = (val & 0xffffffff);
+	}
+	return val;
+}
+
+/* Return the value of function arg #argnum (1=first arg) as a signed int. */
+function int_arg:long (argnum:long) {
+	return _stp_arg(argnum, 1, 1)
+}
+
+/* Return the value of function arg #argnum (1=first arg) as an unsigned int. */
+function uint_arg:long (argnum:long) {
+	return _stp_arg(argnum, 0, 1)
+}
+
+function long_arg:long (argnum:long) {
+	return _stp_arg(argnum, 1, 0)
+}
+
+function ulong_arg:long (argnum:long) {
+	return _stp_arg(argnum, 0, 0)
+}
+
+function longlong_arg:long (argnum:long) {
+	if (probing_app_with_32bit_regs()) {
+		lowbits = _stp_arg(argnum, 0, 1)
+		highbits = _stp_arg(argnum+1, 0, 1)
+		return ((highbits << 32) | lowbits)
+	} else
+		return _stp_arg(argnum, 0, 0)
+}
+
+function ulonglong_arg:long (argnum:long) {
+	return longlong_arg(argnum)
+}
+
+function pointer_arg:long (argnum:long) {
+	return _stp_arg(argnum, 0, 0)
+}
+
+function s32_arg:long (argnum:long) {
+	return int_arg(argnum)
+}
+
+function u32_arg:long (argnum:long) {
+	return uint_arg(argnum)
+}
+
+function s64_arg:long (argnum:long) {
+	return longlong_arg(argnum)
+}
+
+function u64_arg:long (argnum:long) {
+	return ulonglong_arg(argnum)
+}
+
+function asmlinkage() %{ /* pure */ %}
+
+function fastcall() %{ /* pure */ %}
+
+function regparm() %{
+	snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer),
+		"regparm is invalid on mips.");
+	CONTEXT->last_error = CONTEXT->error_buffer;
+%}

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