diff options
author | Frank Ch. Eigler <fche@elastic.org> | 2007-10-11 08:12:09 -0400 |
---|---|---|
committer | Frank Ch. Eigler <fche@elastic.org> | 2007-10-11 08:12:09 -0400 |
commit | 5e1ebf27fd9e9804de45ff4df210124ff58ebdcf (patch) | |
tree | 5803a4bd3315a586df388aac95a599e91b17dbe3 | |
parent | 36c24cdba10c3d20638c78b52cc8e327a3a0b82d (diff) | |
parent | abb3d720eaf5691d8f20237f8832a7ed22d9aead (diff) | |
download | systemtap-steved-5e1ebf27fd9e9804de45ff4df210124ff58ebdcf.tar.gz systemtap-steved-5e1ebf27fd9e9804de45ff4df210124ff58ebdcf.tar.xz systemtap-steved-5e1ebf27fd9e9804de45ff4df210124ff58ebdcf.zip |
Merge branch 'master' of git://sources.redhat.com/git/systemtap
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | examples/ChangeLog | 5 | ||||
-rwxr-xr-x | examples/syscalltimes | 248 | ||||
-rw-r--r-- | examples/syscalltimes.txt | 155 | ||||
-rw-r--r-- | runtime/uprobes/uprobes_ppc64.c | 36 | ||||
-rw-r--r-- | runtime/uprobes/uprobes_ppc64.h | 70 | ||||
-rw-r--r-- | runtime/uprobes/uprobes_s390.c | 208 | ||||
-rw-r--r-- | runtime/uprobes/uprobes_s390.h | 85 | ||||
-rw-r--r-- | tapset/ChangeLog | 20 | ||||
-rw-r--r-- | tapset/nfs_proc.stp | 20 | ||||
-rw-r--r-- | tapset/queue_stats.stp | 6 | ||||
-rw-r--r-- | tapset/udp.stp | 22 |
12 files changed, 875 insertions, 5 deletions
@@ -1,3 +1,8 @@ +2007-10-10 Jim Keniston <jkenisto@us.ibm.com> + + * runtime/uprobes/uprobes_ppc64.[ch]: Added + * runtime/uprobes/uprobes_s390.[ch]: Added + 2007-10-09 Jim Keniston <jkenisto@us.ibm.com> PR 5083 diff --git a/examples/ChangeLog b/examples/ChangeLog index a4df876c..1999521f 100644 --- a/examples/ChangeLog +++ b/examples/ChangeLog @@ -1,3 +1,8 @@ +2007-10-10 Mike Mason + + * syscalltimes, syscalltime.txt: New combination shell/SystemTap script + to measure system call times. + 2007-10-05 Frank Ch. Eigler <fche@elastic.org> * futexes.stp, sig_by_proc.stp, small_demos/rwtiming.stp: Fix elision diff --git a/examples/syscalltimes b/examples/syscalltimes new file mode 100755 index 00000000..84ca77a9 --- /dev/null +++ b/examples/syscalltimes @@ -0,0 +1,248 @@ +#!/bin/bash + +# Syscalltimes systemtap script +# Copyright (C) 2007 IBM Corp. +# +# 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. + +### +### syscalltime - Combination shell/systemtap script to measure system call +### counts and times. Can be filtered by process IDs, process +### names and users. +### + +# Filter options +F_PIDSTR=""; F_PID=0 # Filter by process ID +F_EXECSTR=""; F_EXEC=0 # Filter by process name +F_UIDSTR=""; F_UID=0 # Filter by user +FILTER=0 # Any filters specified? + +# Print options +P_TOTALS=0 # Print totals +P_VERBOSE_STR="" # Print verbose build output + +DELIM="," + +function usage { + echo "USAGE: syscalltimes [-n pname]... [-p pid]... [-u username]..." + echo " [-v]... [-t] [-h]" + echo " -n pname # filter by this process name" + echo " -p pid # filter by this process ID" + echo " -u username # filter by this user" + echo " -t # print totals (default with filters: OFF" + echo " default without filters: ON)" + echo " -v # print verbose output during SystemTap module creation" + echo " -h # print this help text" + echo "" + echo "NOTE: This script can take long time to build. Use -v[vv] to monitor" + echo " the module creation and build process." +} + +# Process options +while getopts n:p:u:vth option; do + case $option in + n) let "F_EXEC++" + F_EXECSTR=$OPTARG$DELIM$F_EXECSTR ;; + + p) let "F_PID++" + F_PIDSTR=$OPTARG$DELIM$F_PIDSTR ;; + + u) uid=`awk -F: '$1 == name {print $3}' name=$OPTARG /etc/passwd` + if [[ $uid != "" ]]; then + let "F_UID++" + F_UIDSTR=$uid$DELIM$F_UIDSTR + else + echo "ERROR: Unknown user:" $OPTARG + let "ERROR++" + fi ;; + + v) P_VERBOSE_STR="-v "$P_VERBOSE_STR ;; + + t) P_TOTALS=1 ;; + + h|?|*) usage + exit 1 ;; + esac +done + +if [[ $ERROR > 0 ]]; then + exit 1 +fi + +if [[ $F_EXEC > 0 || $F_PID > 0 || $F_UID > 0 ]]; then + FILTER=1 +fi + +echo "Creating and building SystemTap module..." + +# +# SystemTap script +# +stap $P_VERBOSE_STR -e ' +global start, timebycall, timebypid, timebyuid, timebyexec +global f_exec_str, f_pid_str, f_uid_str +global f_exec, f_pid, f_uid +global prt_totals, filter_str + +probe begin { + printf("Collecting data - type Ctrl-C to print output and exit...\n") + + # If no filters specified, skip filter processing + if ('$FILTER' == 0) { + filter_str = " (unfiltered)" + prt_totals = 1 // On by default if no filtering + next + } else + filter_str = " (filtered)" + + prt_totals = '$P_TOTALS' + f_exec_str = "'$F_EXECSTR'" + f_pid_str = "'$F_PIDSTR'" + f_uid_str = "'$F_UIDSTR'" + + delim = "'$DELIM'" + + # Process names + if ('$F_EXEC') { + pname = tokenize(f_exec_str, delim) + while (pname != "") { + f_exec[pname] = 1 + pname = tokenize("", delim) + } + } + + # Process IDs + if ('$F_PID') { + pid = tokenize(f_pid_str, delim) + while (pid != "") { + f_pid[strtol(pid, 10)] = 1 + pid = tokenize("", delim) + } + } + + # User IDs + if ('$F_UID') { + uid = tokenize(f_uid_str, delim) + while (uid != "") { + f_uid[strtol(uid, 10)] = 1 + uid = tokenize("", delim) + } + } +} + +probe syscall.* { + start[name, tid()] = gettimeofday_ns() +} + +probe syscall.*.return { + # Skip if we have not seen this before + if (!([name, tid()] in start)) next + + delta = gettimeofday_ns() - start[name, tid()] + + # Check filters + if ('$FILTER') { + target = 0 + if (pid() in f_pid) { + timebypid[name, pid()] <<< delta + target = 1 + } + if (uid() in f_uid) { + timebyuid[name, uid()] <<< delta + target = 1 + } + if (execname() in f_exec) { + timebyexec[name, execname()] <<< delta + target = 1 + } + } else + target = 1 + + # Totals + if (target && prt_totals) + timebycall[name] <<< delta + + delete start[name, tid()] +} + +function print_header() { + printf("%22s %10s %12s %12s %12s %12s\n", + "System Call", "Count", "Total ns", + "Avg ns", "Min ns", "Max ns") +} + +probe end { + if (prt_totals) { + printf("\nTimes for all processes%s:\n\n", filter_str) + print_header() + foreach (call in timebycall) + printf("%22s %10d %12d %12d %12d %12d\n", call, + @count(timebycall[call]), + @sum(timebycall[call]), + @avg(timebycall[call]), + @min(timebycall[call]), + @max(timebycall[call])) + } + + if ('$F_PID') { + curpid = -1 + foreach ([call, pid-] in timebypid) { + if (curpid != pid) { + curpid = pid + printf("\nTimes for process ID %d:\n\n", curpid) + print_header() + } + printf("%22s %10d %12d %12d %12d %12d\n", call, + @count(timebypid[call, pid]), + @sum(timebypid[call, pid]), + @avg(timebypid[call, pid]), + @min(timebypid[call, pid]), + @max(timebypid[call, pid])) + } + printf("\n") + } + + if ('$F_EXEC') { + curexec = "" + foreach ([call, exec-] in timebyexec) { + if (curexec != exec) { + curexec = exec + printf("\nTimes for process name %s:\n\n", curexec) + print_header() + } + printf("%22s %10d %12d %12d %12d %12d\n", call, + @count(timebyexec[call, exec]), + @sum(timebyexec[call, exec]), + @avg(timebyexec[call, exec]), + @min(timebyexec[call, exec]), + @max(timebyexec[call, exec])) + } + printf("\n") + } + + if ('$F_UID') { + curuid = -1 + foreach ([call, uid-] in timebyuid) { + if (curuid != uid) { + curuid = uid + printf("\nTimes for user ID %d:\n\n", curuid) + print_header() + } + printf("%22s %10d %12d %12d %12d %12d\n", call, + @count(timebyuid[call, uid]), + @sum(timebyuid[call, uid]), + @avg(timebyuid[call, uid]), + @min(timebyuid[call, uid]), + @max(timebyuid[call, uid])) + } + printf("\n") + } + + delete timebycall + delete timebypid + delete timebyuid + delete timebyexec +}' diff --git a/examples/syscalltimes.txt b/examples/syscalltimes.txt new file mode 100644 index 00000000..d50f73ad --- /dev/null +++ b/examples/syscalltimes.txt @@ -0,0 +1,155 @@ +# ./syscalltimes -h +USAGE: syscalltimes [-n pname]... [-p pid]... [-u username]... + [-v]... [-t] [-h] + -n pname # filter by this process name + -p pid # filter by this process ID + -u username # filter by this user + -t # print totals (default with filters: OFF + default without filters: ON) + -v # print verbose output during SystemTap module creation + -h # print this help text + +NOTE: This script can take long time to build. Use -v[vv] to monitor + the module creation and build process. + + +# ./syscalltimes -n top -n vi +Creating and building SystemTap module... +Collecting data - type Ctrl-C to print output and exit... + +Times for process name vi: + + System Call Count Total ns Avg ns Min ns Max ns + access 4 59169 14792 7770 27556 + rt_sigprocmask 6 32879 5479 5328 6132 + rt_sigaction 22 119127 5414 5291 6293 + select 15 1605144751 107009650 7386 1117677549 + sysinfo 1 13178 13178 13178 13178 + lseek 2 12869 6434 6331 6538 + getuid 3 16839 5613 5468 5757 + getrlimit 1 5558 5558 5558 5558 + munmap 8 103326 12915 9689 19190 + getpid 1 5639 5639 5639 5639 + unlink 3 143502 47834 20291 97191 + arch_prctl 1 6296 6296 6296 6296 + chdir 6 58086 9681 7213 16062 + getcwd 9 81327 9036 6820 17583 + read 28 341507 12196 6007 54806 + fcntl 4 23418 5854 5478 6459 + sigaltstack 1 5845 5845 5845 5845 + mprotect 13 130272 10020 8255 17130 + statfs 1 10223 10223 10223 10223 + fstat 20 118660 5933 5446 7050 + readlink 1 17884 17884 17884 17884 + readlinkat 1 7889 7889 7889 7889 + socket 2 24932 12466 8090 16842 + stat 13 120911 9300 7376 19549 + ioctl 19 135172 7114 5504 11711 + execve 1 262658 262658 262658 262658 + write 15 382744 25516 8391 136359 + uname 1 6772 6772 6772 6772 + close 30 210468 7015 5478 12543 + fchdir 6 34269 5711 5496 6185 + open 31 474649 15311 7807 54475 + chmod 1 12865 12865 12865 12865 + brk 6 48116 8019 5782 10240 + lstat 2 15369 7684 7334 8035 + connect 2 29287 14643 10616 18671 + +Times for process name top: + + System Call Count Total ns Avg ns Min ns Max ns + arch_prctl 1 6424 6424 6424 6424 + fcntl 97 607311 6260 5170 10873 + read 970 12341710 12723 5574 446707 + lseek 11 66250 6022 5481 7165 + rt_sigaction 71 380049 5352 5255 6374 + access 5 66406 13281 8942 24323 + select 3 6385526578 2128508859 499261647 2999551597 + getdents 21 889837 42373 6386 73490 + getuid 1 5494 5494 5494 5494 + munmap 15 174255 11617 8872 17670 + write 10 2309851 230985 16248 2006254 + uname 1 10474 10474 10474 10474 + close 932 5749946 6169 5348 21248 + ioctl 14 122233 8730 5824 14243 + execve 1 261447 261447 261447 261447 + brk 4 26527 6631 5493 8285 + connect 2 28533 14266 10756 17777 + open 934 9289314 9945 8473 30315 + mprotect 10 97990 9799 8295 14636 + stat 455 3834994 8428 7920 26084 + socket 2 21980 10990 8990 12990 + fstat 26 150418 5785 5426 7127 + alarm 90 536017 5955 5543 11487 + + +# ./syscalltimes -v +Creating and building SystemTap module... +Pass 1: parsed user script and 42 library script(s) in 200usr/10sys/218real ms. +Pass 2: analyzed script: 768 probe(s), 15 function(s), 15 embed(s), 13 global(s) in 35870usr/140sys/36036real ms. +Pass 3: using cached /root/.systemtap/cache/d5/stap_d5fcd430388d4f4a30f63d03aaa3eb80_392196.c +Pass 4: using cached /root/.systemtap/cache/d5/stap_d5fcd430388d4f4a30f63d03aaa3eb80_392196.ko +Pass 5: starting run. +Collecting data - type Ctrl-C to print output and exit... + +Times for all processes (unfiltered): + + System Call Count Total ns Avg ns Min ns Max ns + writev 681 6526983 9584 6807 18709 + write 421 4367057 10373 6424 52077 + uname 15 98071 6538 6336 6787 + close 459 9528659 20759 5265 1346856 + inotify_add_watch 17 164258 9662 8000 17280 + ioctl 1205 28994711 24062 5211 2928218 + execve 12 2148953 179079 10195 280392 + brk 309 2400150 7767 5383 23454 + lstat 5 43864 8772 7938 10426 + connect 24 352784 14699 10679 25868 + getppid 12 71219 5934 5812 6123 + wait4 24 20952033 873001 5664 3387688 + open 377 22181286 58836 8819 3011655 + dup2 18 109197 6066 5865 6403 + bind 3 25322 8440 8263 8759 + poll 1034 36509105361 35308612 5499 1999784046 + getgid 12 65851 5487 5335 5667 + compat_execve 12 3012173 251014 182782 472356 + mprotect 150 1434021 9560 7854 13812 + gettimeofday 10 60416 6041 5238 7429 + recvmsg 9 116065 12896 6889 37388 + readlink 12 638216 53184 46337 64203 + readlinkat 12 530499 44208 37794 55136 + stat 140 1244798 8891 6702 17331 + socket 39 435318 11162 7642 16694 + getsockname 3 18899 6299 6198 6443 + statfs 6 62737 10456 10311 10671 + fstat 238 1400126 5882 5502 12739 + geteuid 12 73475 6122 5248 14048 + readv 27 349998 12962 7150 21210 + arch_prctl 21 135320 6443 6231 6832 + nanosleep 28 8927802107 318850075 150954837 2001911237 + futex 595 8755563465 14715232 5431 1000945645 + read 2586 5154654212 1993292 5622 4985306501 + getpgrp 12 67137 5594 5469 5740 + fcntl 51 289553 5677 5353 6835 + pipe 12 122220 10185 8771 13959 + setitimer 159 1004756 6319 5551 8776 + lseek 4 24304 6076 5900 6253 + mmap2 19 182403 9600 7496 13574 + access 105 1220874 11627 8077 33600 + rt_sigreturn 93 665180 7152 5541 8265 + rt_sigaction 171 967575 5658 5278 18684 + rt_sigprocmask 132 760337 5760 5273 14170 + clock_gettime 151 997395 6605 5275 9090 + pread 192 2387721 12436 5679 43553 + select 925 24357064459 26331961 6669 2861600879 + getegid 12 63624 5302 5200 5466 + getpid 12 66761 5563 5348 5701 + getuid 12 67112 5592 5483 5790 + sendto 3 54766 18255 17541 19501 + munmap 116 1432698 12350 8634 48526 + getdents 6 57855 9642 6248 13313 + times 10 59281 5928 5514 6617 + ppoll 24 4799366329 199973597 199872030 200070128 +Pass 5: run completed in 20usr/90sys/8215real ms. + diff --git a/runtime/uprobes/uprobes_ppc64.c b/runtime/uprobes/uprobes_ppc64.c new file mode 100644 index 00000000..d80676e9 --- /dev/null +++ b/runtime/uprobes/uprobes_ppc64.c @@ -0,0 +1,36 @@ +/* + * Userspace Probes (UProbes) for PowerPC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright IBM Corporation, 2007 + */ +/* + * In versions of uprobes built in the SystemTap runtime, this file + * is #included at the end of uprobes.c. + */ + +/* + * Replace the return address with the trampoline address. Returns + * the original return address. + */ +static +unsigned long arch_hijack_uret_addr(unsigned long trampoline_address, + struct pt_regs *regs, struct uprobe_task *utask) +{ + unsigned long orig_ret_addr = regs->link; + regs->link = trampoline_address; + return orig_ret_addr; +} diff --git a/runtime/uprobes/uprobes_ppc64.h b/runtime/uprobes/uprobes_ppc64.h new file mode 100644 index 00000000..619ba324 --- /dev/null +++ b/runtime/uprobes/uprobes_ppc64.h @@ -0,0 +1,70 @@ +#ifndef _ASM_UPROBES_H +#define _ASM_UPROBES_H +/* + * Userspace Probes (UProbes) for PowerPC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright IBM Corporation, 2007 + */ +#include <linux/types.h> +#include <linux/ptrace.h> +#include <linux/signal.h> + +#define BREAKPOINT_SIGNAL SIGTRAP +#define SSTEP_SIGNAL SIGTRAP + +/* Normally defined in Kconfig */ +#undef CONFIG_UPROBES_SSOL +#define CONFIG_URETPROBES 1 + +typedef unsigned int uprobe_opcode_t; +#define BREAKPOINT_INSTRUCTION 0x7fe00008 /* trap */ +#define BP_INSN_SIZE 4 +#define MAX_UINSN_BYTES 4 +#define SLOT_IP 32 /* instruction pointer slot from include/asm/elf.h */ + +/* Architecture specific switch for where the IP points after a bp hit */ +#define ARCH_BP_INST_PTR(inst_ptr) (inst_ptr) + +struct uprobe_probept; +struct uprobe_task; + +static inline int arch_validate_probed_insn(struct uprobe_probept *ppt) +{ + return 0; +} + +/* On powerpc, nip points to the trap. */ +static inline unsigned long arch_get_probept(struct pt_regs *regs) +{ + return (unsigned long)(regs->nip); +} + +static inline void arch_reset_ip_for_sstep(struct pt_regs *regs) +{ +} + +#ifdef CONFIG_URETPROBES +static inline void arch_restore_uret_addr(unsigned long ret_addr, + struct pt_regs *regs) +{ + regs->nip = ret_addr; +} +#endif /* CONFIG_URETPROBES */ + +static unsigned long arch_hijack_uret_addr(unsigned long trampoline_addr, + struct pt_regs *regs, struct uprobe_task *utask); +#endif /* _ASM_UPROBES_H */ diff --git a/runtime/uprobes/uprobes_s390.c b/runtime/uprobes/uprobes_s390.c new file mode 100644 index 00000000..f97dd408 --- /dev/null +++ b/runtime/uprobes/uprobes_s390.c @@ -0,0 +1,208 @@ +/* + * Userspace Probes (UProbes) + * arch/s390/uprobes/uprobes_s390.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) IBM Corporation, 2006 + */ +/* + * In versions of uprobes built in the SystemTap runtime, this file + * is #included at the end of uprobes.c. + */ +#include <linux/uaccess.h> + +/* adapted from s390/kernel/kprobes.c is_prohibited_opcode() */ +/* TODO More instructions?? Should floating point inst be added?? */ +static int prohibited_opcode(uprobe_opcode_t *instruction) +{ + switch (*(__u8 *) instruction) { + case 0x0c: /* bassm */ + case 0x0b: /* bsm */ + case 0x83: /* diag */ + case 0x44: /* ex */ + return -EINVAL; + } + switch (*(__u16 *) instruction) { + case 0x0101: /* pr */ + case 0xb25a: /* bsa */ + case 0xb240: /* bakr */ + case 0xb258: /* bsg */ + case 0xb218: /* pc */ + case 0xb228: /* pt */ + return -EINVAL; + } + return 0; +} + +static +int arch_validate_probed_insn(struct uprobe_probept *ppt) +{ + if (ppt->vaddr & 0x01) { + printk("Attempt to register uprobe at an unaligned address\n"); + return -EPERM; + } + + /* Make sure the probe isn't going on a difficult instruction */ + if (prohibited_opcode((uprobe_opcode_t *) ppt->insn)) + return -EPERM; + + return 0; +} + +/* + * Get an instruction slot from the process's SSOL area, containing the + * instruction at ppt's probepoint. Point the psw.addr at that slot, in + * preparation for single-stepping out of line. + */ +static +void uprobe_pre_ssout(struct uprobe_task *utask, struct uprobe_probept *ppt, + struct pt_regs *regs) +{ + struct uprobe_ssol_slot *slot; + + slot = uprobe_get_insn_slot(ppt); + if (!slot) { + utask->doomed = 1; + return; + } + regs->psw.addr = (long)slot->insn; + utask->singlestep_addr = regs->psw.addr; +} + +static +void uprobe_post_ssout(struct uprobe_task *utask, struct uprobe_probept *ppt, + struct pt_regs *regs) +{ + int ilen, fixup, reg; + unsigned long copy_ins_addr = utask->singlestep_addr; + unsigned long orig_ins_addr = ppt->vaddr; + + up_read(&ppt->slot->rwsem); + + /* default fixup method */ + fixup = FIXUP_PSW_NORMAL;; + + /* get r1 operand */ + reg = (*ppt->insn & 0xf0) >> 4; + + /* save the instruction length (pop 5-5) in bytes */ + switch (*(__u8 *) (ppt->insn) >> 6) { + case 0: + ilen = 2; + break; + case 1: + case 2: + ilen = 4; + break; + case 3: + ilen = 6; + break; + default: + ilen = 0; + BUG(); + } + + + switch (*(__u8 *) ppt->insn) { + case 0x05: /* balr */ + case 0x0d: /* basr */ + fixup = FIXUP_RETURN_REGISTER; + /* if r2 = 0, no branch will be taken */ + if ((*ppt->insn & 0x0f) == 0) + fixup |= FIXUP_BRANCH_NOT_TAKEN; + break; + case 0x06: /* bctr */ + case 0x07: /* bcr */ + fixup = FIXUP_BRANCH_NOT_TAKEN; + break; + case 0x45: /* bal */ + case 0x4d: /* bas */ + fixup = FIXUP_RETURN_REGISTER; + break; + case 0x47: /* bc */ + case 0x46: /* bct */ + case 0x86: /* bxh */ + case 0x87: /* bxle */ + fixup = FIXUP_BRANCH_NOT_TAKEN; + break; + case 0x82: /* lpsw */ + fixup = FIXUP_NOT_REQUIRED; + break; + case 0xb2: /* lpswe */ + if (*(((__u8 *) ppt->insn) + 1) == 0xb2) { + fixup = FIXUP_NOT_REQUIRED; + } + break; + case 0xa7: /* bras */ + if ((*ppt->insn & 0x0f) == 0x05) { + fixup |= FIXUP_RETURN_REGISTER; + } + break; + case 0xc0: + if ((*ppt->insn & 0x0f) == 0x00 /* larl */ + || (*ppt->insn & 0x0f) == 0x05) /* brasl */ + fixup |= FIXUP_RETURN_REGISTER; + break; + case 0xeb: + if (*(((__u8 *) ppt->insn) + 5 ) == 0x44 || /* bxhg */ + *(((__u8 *) ppt->insn) + 5) == 0x45) {/* bxleg */ + fixup = FIXUP_BRANCH_NOT_TAKEN; + } + break; + case 0xe3: /* bctg */ + if (*(((__u8 *) ppt->insn) + 5) == 0x46) { + fixup = FIXUP_BRANCH_NOT_TAKEN; + } + break; + } + + /* do the fixup and adjust psw as needed */ + regs->psw.addr &= PSW_ADDR_INSN; + + if (fixup & FIXUP_PSW_NORMAL) + regs->psw.addr = orig_ins_addr + regs->psw.addr - + copy_ins_addr; + + if (fixup & FIXUP_BRANCH_NOT_TAKEN) + if (regs->psw.addr - copy_ins_addr == ilen) + regs->psw.addr = orig_ins_addr + ilen; + + if (fixup & FIXUP_RETURN_REGISTER) + regs->gprs[reg] = (orig_ins_addr + (regs->gprs[reg] - + copy_ins_addr)) | PSW_ADDR_AMODE; + + regs->psw.addr |= PSW_ADDR_AMODE; +} + + +/* + * Replace the return address with the trampoline address. Returns + * the original return address. + */ +static +unsigned long arch_hijack_uret_addr(unsigned long trampoline_address, + struct pt_regs *regs, struct uprobe_task *utask) +{ + unsigned long orig_ret_addr; +#ifdef CONFIG_COMPAT + if (test_tsk_thread_flag(utask->tsk, TIF_31BIT)) + orig_ret_addr = regs->gprs[14]&0x7FFFFFFFUL; + else +#endif + orig_ret_addr = regs->gprs[14]; + regs->gprs[14] = trampoline_address; + return orig_ret_addr; +} diff --git a/runtime/uprobes/uprobes_s390.h b/runtime/uprobes/uprobes_s390.h new file mode 100644 index 00000000..4f3a8187 --- /dev/null +++ b/runtime/uprobes/uprobes_s390.h @@ -0,0 +1,85 @@ +#ifndef _ASM_UPROBES_H +#define _ASM_UPROBES_H +/* + * Userspace Probes (UProbes) + * include/asm-s390/uprobes.h + * + * Adapted from include/asm-i386/uprobes.h by: + * David Wilder <dwilder.us.ibm.com> 2007 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) IBM Corporation, 2006 + */ +#include <linux/types.h> +#include <linux/ptrace.h> + +/* Normally defined in Kconfig */ +#define CONFIG_URETPROBES 1 +#define CONFIG_UPROBES_SSOL 1 + +typedef u16 uprobe_opcode_t; + +#define BREAKPOINT_INSTRUCTION 0x0002 +#define BP_INSN_SIZE 2 +#define MAX_UINSN_BYTES 6 + +#define BREAKPOINT_SIGNAL SIGILL +#define SSTEP_SIGNAL SIGTRAP + +#ifdef CONFIG_COMPAT +#define SLOT_IP (test_tsk_thread_flag(current, TIF_31BIT) ? 0x04 : 0x08) +#else +#define SLOT_IP 0x08 +#endif + +#define FIXUP_PSW_NORMAL 0x08 +#define FIXUP_BRANCH_NOT_TAKEN 0x04 +#define FIXUP_RETURN_REGISTER 0x02 +#define FIXUP_NOT_REQUIRED 0x01 + +/* Architecture specific switch for where the IP points after a bp hit */ +#define ARCH_BP_INST_PTR(inst_ptr) (inst_ptr - BP_INSN_SIZE) + +struct uprobe_probept; +struct uprobe_task; +static int arch_validate_probed_insn(struct uprobe_probept *ppt); + +/* + * On s390, a trap leaves the instruction pointer pointing past the + * trap instruction. + */ +static inline unsigned long arch_get_probept(struct pt_regs *regs) +{ + return (unsigned long) (regs->psw.addr - BP_INSN_SIZE); +} + +static inline void arch_reset_ip_for_sstep(struct pt_regs *regs) +{ + regs->psw.addr -= BP_INSN_SIZE; +} + +#ifdef CONFIG_URETPROBES +static inline void arch_restore_uret_addr(unsigned long ret_addr, + struct pt_regs *regs) +{ + regs->psw.addr = ret_addr; +} + +static unsigned long arch_hijack_uret_addr(unsigned long trampoline_addr, + struct pt_regs *regs, struct uprobe_task *utask); + +#endif /* CONFIG_URETPROBES */ +#endif /* _ASM_UPROBES_H */ diff --git a/tapset/ChangeLog b/tapset/ChangeLog index 287b0823..72dca971 100644 --- a/tapset/ChangeLog +++ b/tapset/ChangeLog @@ -1,3 +1,23 @@ +2007-10-11 Zhaolei <zhaolei@cn.fujitsu.com> + + * queue_stats.stp (qsq_utilization): Update queue account datas + before calculate. + (qsq_blocked): Ditto. + (qsq_wait_queue_length): Ditto. + (qsq_service_time): Ditto. + (qsq_wait_time): Ditto. + (qsq_throughput): Ditto. + +2007-10-11 Zhaolei <zhaolei@cn.fujitsu.com> + + From Cai Fei <caifei@cn.fujitsu.com> + * nfs_proc.stp (__nfs_write_data_info): Add data-access code for + count, valid and timestamp. + +2007-10-11 Zhaolei <zhaolei@cn.fujitsu.com> + + * udp.stp: Add name argument for all probes. + 2007-10-10 Martin Hunt <hunt@redhat.com> * aux_syscalls.stp (_stp_lookup_str): When defaulting diff --git a/tapset/nfs_proc.stp b/tapset/nfs_proc.stp index 0b07fb54..bd7baa80 100644 --- a/tapset/nfs_proc.stp +++ b/tapset/nfs_proc.stp @@ -101,10 +101,14 @@ function __nfs_read_data_info:long (rdata :long,index :long) %{ /* pure */ /* 0: get ip address 1: get proto + 2: get res->count + 3: get res->fattr->valid + 4: get timestamp */ function __nfs_write_data_info:long (wdata :long,index :long) %{ /* pure */ struct nfs_write_data * wdata = (struct nfs_write_data *)(long)THIS->wdata; struct rpc_task *task = &(wdata->task); + struct nfs_writeres *wres = &(wdata->res); int index = THIS->index; switch(index) { @@ -114,9 +118,25 @@ function __nfs_write_data_info:long (wdata :long,index :long) %{ /* pure */ case 1: THIS->__retvalue = get_prot(task); break; + + case 2: + THIS->__retvalue = kread(&(wres->count)); + break; + case 3: { + struct nfs_fattr *fattr = kread(&(wres->fattr)); + THIS->__retvalue = kread(&(fattr->valid)); + break; + } +#ifdef CONFIG_NFS_V4 + case 4: + THIS->__retvalue = kread(&(wdata->timestamp)); + break; +#endif default: + THIS->__retvalue = 0; break; } + CATCH_DEREF_FAULT(); %} function __nfsv4_bitmask :long(dir:long,i:long) %{ /* pure */ diff --git a/tapset/queue_stats.stp b/tapset/queue_stats.stp index 9d89903c..5cf24c40 100644 --- a/tapset/queue_stats.stp +++ b/tapset/queue_stats.stp @@ -70,35 +70,41 @@ function qsq_start (qname) { # reset statistics for new baseline # fraction of time that any request was being serviced function qsq_utilization (qname, scale) { + _qs_update (qname) elapsed = qs_time() - qs_stime[qname] return (scale * qs_rtime[qname]) / elapsed } # fraction of time that any request was blocked in the wait queue function qsq_blocked (qname, scale) { + _qs_update (qname) elapsed = qs_time() - qs_stime[qname] return (scale * qs_wtime[qname]) / elapsed } # length of wait queue function qsq_wait_queue_length (qname, scale) { + _qs_update (qname) elapsed = qs_time() - qs_stime[qname] return (scale * qs_wlentime[qname]) / elapsed } # service time (amount of time per request service) function qsq_service_time (qname, scale) { + _qs_update (qname) return (scale * qs_rlentime[qname]) / qs_dcount[qname] } # wait time (amount of time in queue + service per request) function qsq_wait_time (qname, scale) { + _qs_update (qname) return (scale * (qs_rlentime[qname] + qs_wlentime[qname])) / qs_dcount[qname] } # service rate (number of requests served per unit time) function qsq_throughput (qname, scale) { + _qs_update (qname) elapsed = qs_time() - qs_stime[qname] return (scale * qs_dcount[qname]) / elapsed } diff --git a/tapset/udp.stp b/tapset/udp.stp index 9e7051a1..1559058b 100644 --- a/tapset/udp.stp +++ b/tapset/udp.stp @@ -21,9 +21,11 @@ // The process which sends a udp message // // Arguments: -// sock - network socket -// size - number of bytes to send +// name - name of this probe +// sock - network socket +// size - number of bytes to send probe udp.sendmsg = kernel.function("udp_sendmsg") { + name = "udp.sendmsg" sock = $sk size = $len } @@ -36,9 +38,11 @@ probe udp.sendmsg = kernel.function("udp_sendmsg") { // The process which sends a udp message // // Arguments: +// name - name of this probe // size - number of bytes sent // probe udp.sendmsg.return = kernel.function("udp_sendmsg").return { + name = "udp.sendmsg" size = $return } @@ -50,10 +54,12 @@ probe udp.sendmsg.return = kernel.function("udp_sendmsg").return { // The process which receives a udp message // // Arguments: +// name - name of this probe // sock - network socket // size - number of bytes to be received // probe udp.recvmsg = kernel.function("udp_recvmsg") { + name = "udp.recvmsg" sock = $sk size = $len } @@ -66,9 +72,11 @@ probe udp.recvmsg = kernel.function("udp_recvmsg") { // The process which receives a udp message // // Arguments: +// name - name of this probe // size - number of bytes received // probe udp.recvmsg.return = kernel.function("udp_recvmsg").return { + name = "udp.recvmsg" size = $return } @@ -80,10 +88,12 @@ probe udp.recvmsg.return = kernel.function("udp_recvmsg").return { // The process which disconnects udp // // Arguments: -// sock - network socket -// flags - flags (e.g. FIN, etc) +// name - name of this probe +// sock - network socket +// flags - flags (e.g. FIN, etc) // probe udp.disconnect = kernel.function("udp_disconnect") { + name = "udp.disconnect" sock = $sk flags = $flags } @@ -96,8 +106,10 @@ probe udp.disconnect = kernel.function("udp_disconnect") { // The process which disconnects udp // // Arguments: -// ret - error code (0: no error) +// name - name of this probe +// ret - error code (0: no error) // probe udp.disconnect.return = kernel.function("udp_disconnect").return { + name = "udp.disconnect" ret = $return } |