summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrank Ch. Eigler <fche@elastic.org>2007-10-11 08:12:09 -0400
committerFrank Ch. Eigler <fche@elastic.org>2007-10-11 08:12:09 -0400
commit5e1ebf27fd9e9804de45ff4df210124ff58ebdcf (patch)
tree5803a4bd3315a586df388aac95a599e91b17dbe3
parent36c24cdba10c3d20638c78b52cc8e327a3a0b82d (diff)
parentabb3d720eaf5691d8f20237f8832a7ed22d9aead (diff)
downloadsystemtap-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--ChangeLog5
-rw-r--r--examples/ChangeLog5
-rwxr-xr-xexamples/syscalltimes248
-rw-r--r--examples/syscalltimes.txt155
-rw-r--r--runtime/uprobes/uprobes_ppc64.c36
-rw-r--r--runtime/uprobes/uprobes_ppc64.h70
-rw-r--r--runtime/uprobes/uprobes_s390.c208
-rw-r--r--runtime/uprobes/uprobes_s390.h85
-rw-r--r--tapset/ChangeLog20
-rw-r--r--tapset/nfs_proc.stp20
-rw-r--r--tapset/queue_stats.stp6
-rw-r--r--tapset/udp.stp22
12 files changed, 875 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index 4c1801d6..77883fc6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
}