summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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
-rw-r--r--tapsets.cxx12
-rw-r--r--translate.cxx2
9 files changed, 287 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)
diff --git a/tapsets.cxx b/tapsets.cxx
index 5fcef4aa..68e0ff3f 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -1,5 +1,6 @@
// tapset resolution
// 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
@@ -1772,6 +1773,16 @@ query_func_info (Dwarf_Addr entrypc,
}
else
{
+#ifdef __ia64__
+ // In IA64 platform function probe point is set at its
+ // entry point rather than prologue end pointer
+ if (q->sess.verbose)
+ clog << "querying entrypc of function '"
+ << fi.name << "'" << endl;
+ query_statement (fi.name, fi.decl_file, fi.decl_line,
+ &fi.die, entrypc, q);
+
+#else
if (q->sess.verbose)
clog << "querying prologue-end of function '"
<< fi.name << "'" << endl;
@@ -1782,6 +1793,7 @@ query_func_info (Dwarf_Addr entrypc,
query_statement (fi.name, fi.decl_file, fi.decl_line,
&fi.die, fi.prologue_end, q);
+#endif
}
}
catch (semantic_error &e)
diff --git a/translate.cxx b/translate.cxx
index 7a37c3a1..6abecbea 100644
--- a/translate.cxx
+++ b/translate.cxx
@@ -1,5 +1,6 @@
// translation pass
// 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
@@ -2626,6 +2627,7 @@ translate_pass (systemtap_session& s)
s.op->newline() << "#include \"runtime.h\"";
s.op->newline() << "#include \"current.c\"";
s.op->newline() << "#include \"stack.c\"";
+ s.op->newline() << "#include \"regs.c\"";
s.op->newline() << "#include <linux/string.h>";
s.op->newline() << "#include <linux/timer.h>";
s.op->newline() << "#endif";