summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authoraskeshav <askeshav>2005-10-28 22:49:28 +0000
committeraskeshav <askeshav>2005-10-28 22:49:28 +0000
commit1c9db4fdf66fe88a731319b99942872fa567d742 (patch)
tree33a86507a7fcf9a9c771cf9a1801c8f81c566cf8 /runtime
parent063b69fe3f1109ec81b5e4c1f1333a442ccb3734 (diff)
downloadsystemtap-steved-1c9db4fdf66fe88a731319b99942872fa567d742.tar.gz
systemtap-steved-1c9db4fdf66fe88a731319b99942872fa567d742.tar.xz
systemtap-steved-1c9db4fdf66fe88a731319b99942872fa567d742.zip
IA64 Runtime support patches. With this in place
Systemtap should now be able to build on Ia64. Includes supports for - function probes, return probes, function parameter access and dumping stack backtrace. Added by Anil S Keshavamurthy <Anil.s.keshavamurthy@intel.com>
Diffstat (limited to 'runtime')
-rw-r--r--runtime/copy.c12
-rw-r--r--runtime/current.c42
-rw-r--r--runtime/loc2c-runtime.h48
-rw-r--r--runtime/regs.c80
-rw-r--r--runtime/regs.h15
-rw-r--r--runtime/runtime.h13
-rw-r--r--runtime/stack.c66
7 files changed, 273 insertions, 3 deletions
diff --git a/runtime/copy.c b/runtime/copy.c
index 25f4d695..86c8f65f 100644
--- a/runtime/copy.c
+++ b/runtime/copy.c
@@ -1,3 +1,13 @@
+/* Copy from user space functions
+ * Copyright (C) 2005 Red Hat Inc.
+ * Copyright (C) 2005 Intel 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
+ * Public License (GPL); either version 2, or (at your option) any
+ * later version.
+ */
+
#ifndef _COPY_C_ /* -*- linux-c -*- */
#define _COPY_C_
@@ -74,7 +84,7 @@ do { \
: "i"(-EFAULT), "0"(count), "1"(count), "3"(src), "4"(dst) \
: "memory"); \
} while (0)
-#elif defined (__powerpc64__)
+#elif defined (__powerpc64__) || defined (__ia64__)
#define __stp_strncpy_from_user(dst,src,count,res) \
do { res = __strncpy_from_user(dst, src, count); } while(0)
#endif
diff --git a/runtime/current.c b/runtime/current.c
index 00ddb3e1..0b2d84ad 100644
--- a/runtime/current.c
+++ b/runtime/current.c
@@ -1,3 +1,13 @@
+/* Functions to access the members of pt_regs struct
+ * Copyright (C) 2005 Red Hat Inc.
+ * Copyright (C) 2005 Intel 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
+ * Public License (GPL); either version 2, or (at your option) any
+ * later version.
+ */
+
#ifndef _CURRENT_C_ /* -*- linux-c -*- */
#define _CURRENT_C_
@@ -31,6 +41,8 @@ unsigned long _stp_ret_addr (struct pt_regs *regs)
return regs->esp;
#elif defined (__powerpc64__)
return REG_LINK(regs);
+#elif defined (__ia64__)
+ return regs->b0;
#else
#error Unimplemented architecture
#endif
@@ -99,6 +111,36 @@ void _stp_sprint_regs(String str, struct pt_regs * regs)
_stp_sprintf(str,"CR2: %016lx CR3: %016lx CR4: %016lx\n", cr2, cr3, cr4);
}
+#elif defined (__ia64__)
+void _stp_sprint_regs(String str, struct pt_regs * regs)
+{
+ unsigned long ip = regs->cr_iip + ia64_psr(regs)->ri;
+
+ _stp_sprintf(str, "\nPid: %d, CPU %d, comm: %20s\n", current->pid,
+ smp_processor_id(), current->comm);
+ _stp_sprintf(str, "psr : %016lx ifs : %016lx ip : [<%016lx>] \n",
+ regs->cr_ipsr, regs->cr_ifs, ip);
+ _stp_sprintf(str, "unat: %016lx pfs : %016lx rsc : %016lx\n",
+ regs->ar_unat, regs->ar_pfs, regs->ar_rsc);
+ _stp_sprintf(str, "rnat: %016lx bsps: %016lx pr : %016lx\n",
+ regs->ar_rnat, regs->ar_bspstore, regs->pr);
+ _stp_sprintf(str, "ldrs: %016lx ccv : %016lx fpsr: %016lx\n",
+ regs->loadrs, regs->ar_ccv, regs->ar_fpsr);
+ _stp_sprintf(str, "csd : %016lx ssd : %016lx\n",
+ regs->ar_csd, regs->ar_ssd);
+ _stp_sprintf(str, "b0 : %016lx b6 : %016lx b7 : %016lx\n",
+ regs->b0, regs->b6, regs->b7);
+ _stp_sprintf(str, "f6 : %05lx%016lx f7 : %05lx%016lx\n",
+ regs->f6.u.bits[1], regs->f6.u.bits[0],
+ regs->f7.u.bits[1], regs->f7.u.bits[0]);
+ _stp_sprintf(str, "f8 : %05lx%016lx f9 : %05lx%016lx\n",
+ regs->f8.u.bits[1], regs->f8.u.bits[0],
+ regs->f9.u.bits[1], regs->f9.u.bits[0]);
+ _stp_sprintf(str, "f10 : %05lx%016lx f11 : %05lx%016lx\n",
+ regs->f10.u.bits[1], regs->f10.u.bits[0],
+ regs->f11.u.bits[1], regs->f11.u.bits[0]);
+}
+
#elif defined (__i386__)
/** Write the registers to a string.
diff --git a/runtime/loc2c-runtime.h b/runtime/loc2c-runtime.h
index ed174db3..f9bcf2ad 100644
--- a/runtime/loc2c-runtime.h
+++ b/runtime/loc2c-runtime.h
@@ -1,4 +1,12 @@
-/* target operations */
+/* target operations
+ * Copyright (C) 2005 Red Hat Inc.
+ * Copyright (C) 2005 Intel 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
+ * Public License (GPL); either version 2, or (at your option) any
+ * later version.
+ */
#include <linux/types.h>
#define intptr_t long
@@ -50,6 +58,13 @@
#define dwarf_register_6(regs) regs->esi
#define dwarf_register_7(regs) regs->edi
+#elif defined __ia64__
+#undef fetch_register
+#undef store_register
+
+#define fetch_register(regno) ia64_fetch_register(regno, c->regs)
+#define store_register(regno, value) ia64_store_register(regno, c->regs, value)
+
#elif defined __x86_64__
#define dwarf_register_0(regs) regs->rax
@@ -113,6 +128,37 @@
goto deref_fault; \
})
+#elif defined __ia64__
+#define deref(size, addr) \
+ ({ \
+ int _bad = 0; \
+ intptr_t _v=0; \
+ switch (size){ \
+ case 1: __get_user_size(_v, addr, 1, _bad); break; \
+ case 2: __get_user_size(_v, addr, 2, _bad); break; \
+ case 4: __get_user_size(_v, addr, 4, _bad); break; \
+ case 8: __get_user_size(_v, addr, 8, _bad); break; \
+ default: __get_user_unknown(); break; \
+ } \
+ if (_bad) \
+ goto deref_fault; \
+ _v; \
+ })
+
+#define store_deref(size, addr, value) \
+ ({ \
+ int _bad=0; \
+ switch (size){ \
+ case 1: __put_user_size(value, addr, 1, _bad); break; \
+ case 2: __put_user_size(value, addr, 2, _bad); break; \
+ case 4: __put_user_size(value, addr, 4, _bad); break; \
+ case 8: __put_user_size(value, addr, 8, _bad); break; \
+ default: __put_user_unknown(); break; \
+ } \
+ if (_bad) \
+ goto deref_fault; \
+ })
+
#elif defined __powerpc64__
#define deref(size, addr) \
diff --git a/runtime/regs.c b/runtime/regs.c
new file mode 100644
index 00000000..51c46db3
--- /dev/null
+++ b/runtime/regs.c
@@ -0,0 +1,80 @@
+/* register access functions
+ * Copyright (C) 2005 Intel 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
+ * Public License (GPL); either version 2, or (at your option) any
+ * later version.
+ */
+
+#ifndef _REG_C_ /* -*- linux-c -*- */
+#define _REG_C_
+
+#if defined __ia64__
+
+struct ia64_stap_get_arbsp_param {
+ unsigned long ip;
+ unsigned long *address;
+};
+
+static void ia64_stap_get_arbsp(struct unw_frame_info *info, void *arg)
+{
+ unsigned long ip;
+ struct ia64_stap_get_arbsp_param *lp = arg;
+
+ do {
+ unw_get_ip(info, &ip);
+ if (ip == 0)
+ break;
+ if (ip == lp->ip) {
+ unw_get_bsp(info, (unsigned long*)&lp->address);
+ return;
+ }
+ } while (unw_unwind(info) >= 0);
+ lp->address = 0;
+}
+
+static long ia64_fetch_register(int regno, struct pt_regs *pt_regs)
+{
+ struct ia64_stap_get_arbsp_param pa;
+
+ if (regno < 32 || regno > 127)
+ return 0;
+
+ pa.ip = pt_regs->cr_iip;
+ unw_init_running(ia64_stap_get_arbsp, &pa);
+ if (pa.address == 0)
+ return 0;
+
+ return *ia64_rse_skip_regs(pa.address, regno-32);
+}
+
+static void ia64_store_register(int regno,
+ struct pt_regs *pt_regs,
+ unsigned long value)
+{
+ struct ia64_stap_get_arbsp_param pa;
+ unsigned long rsc_save = 0;
+
+ if (regno < 32 || regno > 127)
+ return;
+
+ pa.ip = pt_regs->cr_iip;
+ unw_init_running(ia64_stap_get_arbsp, &pa);
+ if (pa.address == 0)
+ return;
+ *ia64_rse_skip_regs(pa.address, regno-32) = value;
+ //Invalidate all stacked registers outside the current frame
+ asm volatile( "mov %0=ar.rsc;;\n\t"
+ "mov ar.rsc=0;;\n\t"
+ "{\n\tloadrs;;\n\t\n\t\n\t}\n\t"
+ "mov ar.rsc=%1\n\t"
+ :"=r" (rsc_save):"r" (rsc_save):"memory");
+
+ return;
+}
+
+#endif /* if defined __ia64__ */
+
+
+#endif /* _REG_C_ */
diff --git a/runtime/regs.h b/runtime/regs.h
index e634581c..0e759d1d 100644
--- a/runtime/regs.h
+++ b/runtime/regs.h
@@ -1,7 +1,16 @@
+/* common register includes used in multiple modules
+ * Copyright (C) 2005 Red Hat Inc.
+ * Copyright (C) 2005 Intel 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
+ * Public License (GPL); either version 2, or (at your option) any
+ * later version.
+ */
+
#ifndef _REGS_H_ /* -*- linux-c -*- */
#define _REGS_H_
-/* common register includes used in multiple modules */
#ifdef __x86_64__
@@ -13,6 +22,10 @@
#define REG_IP(regs) regs->eip
#define REG_SP(regs) regs->esp
+#elif defined (__ia64__)
+#define REG_IP(regs) ((regs)->cr_iip +ia64_psr(regs)->ri)
+#define REG_SP(regs) ((regs)->r12)
+
#elif defined (__powerpc64__)
#define REG_IP(regs) regs->nip
diff --git a/runtime/runtime.h b/runtime/runtime.h
index e077c29a..3bc6671b 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -1,5 +1,6 @@
/* main header file
* Copyright (C) 2005 Red Hat Inc.
+ * Copyright (C) 2005 Intel 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
@@ -125,6 +126,9 @@ static const char * _stp_kallsyms_lookup_tabled (unsigned long addr,
}
#endif
+#ifdef __ia64__
+ struct fnptr func_entry, *pfunc_entry;
+#endif
int init_module (void)
{
_stp_kta = (int (*)(unsigned long))kallsyms_lookup_name("__kernel_text_address");
@@ -134,8 +138,17 @@ int init_module (void)
_stp_kallsyms_lookup = & _stp_kallsyms_lookup_tabled;
else
#endif
+#ifdef __ia64__
+ {
+ func_entry.gp = ((struct fnptr *) kallsyms_lookup_name)->gp;
+ func_entry.ip = kallsyms_lookup_name("kallsyms_lookup");
+ _stp_kallsyms_lookup = (const char * (*)(unsigned long,unsigned long *,unsigned long *,char **,char *))&func_entry;
+
+ }
+#else
_stp_kallsyms_lookup = (const char * (*)(unsigned long,unsigned long *,unsigned long *,char **,char *))
kallsyms_lookup_name("kallsyms_lookup");
+#endif
return _stp_transport_init();
}
diff --git a/runtime/stack.c b/runtime/stack.c
index bc9630dc..c09b8171 100644
--- a/runtime/stack.c
+++ b/runtime/stack.c
@@ -1,3 +1,13 @@
+/* Stack tracing functions
+ * Copyright (C) 2005 Red Hat Inc.
+ * Copyright (C) 2005 Intel 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
+ * Public License (GPL); either version 2, or (at your option) any
+ * later version.
+ */
+
#ifndef _STACK_C_ /* -*- linux-c -*- */
#define _STACK_C_
@@ -38,6 +48,62 @@ static void __stp_stack_sprint (String str, unsigned long *stack, int verbose, i
}
}
+#elif defined (__ia64__)
+struct dump_para{
+ unsigned long *sp;
+ String str;
+};
+
+static void __stp_show_stack_sym(struct unw_frame_info *info, void *arg)
+{
+ unsigned long ip, skip=1;
+ String str = ((struct dump_para*)arg)->str;
+ struct pt_regs *regs = container_of(((struct dump_para*)arg)->sp, struct pt_regs, r12);
+
+ do {
+ unw_get_ip(info, &ip);
+ if (ip == 0) break;
+ if (skip){
+ if (ip == REG_IP(regs))
+ skip = 0;
+ else continue;
+ }
+ _stp_string_cat(str, " ");
+ _stp_symbol_sprint(str, ip);
+ _stp_string_cat (str, "\n");
+ } while (unw_unwind(info) >= 0);
+}
+
+static void __stp_show_stack_addr(struct unw_frame_info *info, void *arg)
+{
+ unsigned long ip, skip=1;
+ String str = ((struct dump_para*)arg)->str;
+ struct pt_regs *regs = container_of(((struct dump_para*)arg)->sp, struct pt_regs, r12);
+
+ do {
+ unw_get_ip(info, &ip);
+ if (ip == 0) break;
+ if (skip){
+ if (ip == REG_IP(regs))
+ skip = 0;
+ continue;
+ }
+ _stp_sprintf (str, "%lx ", ip);
+ } while (unw_unwind(info) >= 0);
+}
+
+static void __stp_stack_sprint (String str, unsigned long *stack, int verbose, int levels)
+{
+ struct dump_para para;
+
+ para.str = str;
+ para.sp = stack;
+ if (verbose)
+ unw_init_running(__stp_show_stack_sym, &para);
+ else
+ unw_init_running(__stp_show_stack_addr, &para);
+}
+
#elif defined (__i386__)
static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)