From 1c9db4fdf66fe88a731319b99942872fa567d742 Mon Sep 17 00:00:00 2001 From: askeshav Date: Fri, 28 Oct 2005 22:49:28 +0000 Subject: [PATCH] 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 --- runtime/copy.c | 12 ++++++- runtime/current.c | 42 ++++++++++++++++++++++ runtime/loc2c-runtime.h | 48 ++++++++++++++++++++++++- runtime/regs.c | 80 +++++++++++++++++++++++++++++++++++++++++ runtime/regs.h | 15 +++++++- runtime/runtime.h | 13 +++++++ runtime/stack.c | 66 ++++++++++++++++++++++++++++++++++ tapsets.cxx | 12 +++++++ translate.cxx | 2 ++ 9 files changed, 287 insertions(+), 3 deletions(-) create mode 100644 runtime/regs.c diff --git a/runtime/copy.c b/runtime/copy.c index 25f4d6950..86c8f65fe 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 00ddb3e15..0b2d84ad9 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 ed174db3d..f9bcf2ad4 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 #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 000000000..51c46db32 --- /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 e634581c8..0e759d1d4 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 e077c29a7..3bc6671b7 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 bc9630dc2..c09b8171f 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, ¶); + else + unw_init_running(__stp_show_stack_addr, ¶); +} + #elif defined (__i386__) static inline int valid_stack_ptr(struct thread_info *tinfo, void *p) diff --git a/tapsets.cxx b/tapsets.cxx index 5fcef4aa5..68e0ff3f6 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 7a37c3a1f..6abecbea9 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 "; s.op->newline() << "#include "; s.op->newline() << "#endif"; -- 2.43.5