]> sourceware.org Git - systemtap.git/commitdiff
BZ1431263: Add hardware breakpoint functional test.
authorDavid Smith <dsmith@redhat.com>
Mon, 27 Mar 2017 15:33:14 +0000 (10:33 -0500)
committerDavid Smith <dsmith@redhat.com>
Mon, 27 Mar 2017 15:33:14 +0000 (10:33 -0500)
* testsuite/systemtap.base/hw_breakpoint.exp: New hardware breakpoint
  test.
* testsuite/systemtap.base/stap_hwbkpt_kmod.Makefile: Ditto.
* testsuite/systemtap.base/stap_hwbkpt_kmod.c: Ditto.

testsuite/systemtap.base/hw_breakpoint.exp [new file with mode: 0644]
testsuite/systemtap.base/stap_hwbkpt_kmod.Makefile [new file with mode: 0644]
testsuite/systemtap.base/stap_hwbkpt_kmod.c [new file with mode: 0644]

diff --git a/testsuite/systemtap.base/hw_breakpoint.exp b/testsuite/systemtap.base/hw_breakpoint.exp
new file mode 100644 (file)
index 0000000..4f838be
--- /dev/null
@@ -0,0 +1,147 @@
+set test "hw_breakpoint"
+if {![installtest_p]} { untested $test; return }
+# Note that 'hwbkpt_probes_p' really tests for kernel support. We
+# won't know if this hardware actually supports these probes until we
+# try them below.
+if {![hwbkpt_probes_p]} { untested $test; return }
+
+set build_dir ""
+set uname [exec /bin/uname -r]
+set mod_base stap_hwbkpt_kmod
+set mod_name ${mod_base}.ko
+set mod_cmd /proc/stap_hwbkpt_cmd
+
+proc build_and_install_module {} {
+    global build_dir
+    global srcdir subdir
+    global mod_name mod_base
+
+    # Create the build directory and populate it
+    if {[catch {exec mktemp -d -t staptestXXXXXX} build_dir]} {
+       verbose -log "Failed to create temporary directory: $build_dir"
+       return 0
+    }
+    if {[catch {exec cp $srcdir/$subdir/${mod_base}.c $build_dir/} res]} {
+       verbose -log "$res"
+       return 0
+    }
+    if {[catch {exec cp -p $srcdir/$subdir/${mod_base}.Makefile $build_dir/Makefile } res]} {
+       verbose -log "$res"
+       return 0
+    }
+
+    # Build the module
+    if {[catch {exec make -C $build_dir clean} res]} {
+       verbose -log "$res"
+       return 0
+    }
+    catch {exec make -C $build_dir} res
+    if {![file exists $build_dir/${mod_name}]} {
+       verbose -log "$res"
+       return 0
+    }
+    set res [as_root [list cp $build_dir/${mod_name} /lib/modules/$::uname/kernel/]]
+    if { $res != 0 } {
+       verbose -log "$res"
+       return 0
+    }
+
+    # Install the module
+    set res [as_root [list /sbin/insmod /lib/modules/$::uname/kernel/${mod_name}]]
+    if {$res != 0} {
+       verbose -log "$res"
+       return 0
+    }
+    return 1
+}
+
+proc cleanup_module {} {
+    global build_dir mod_name mod_base
+    as_root [list /bin/rm -f /lib/modules/$::uname/kernel/${mod_name}]
+    as_root [list /sbin/rmmod ${mod_base}]
+    if {$build_dir != ""} {
+       catch { exec rm -rf $build_dir }
+    }
+}
+
+if {[build_and_install_module] == 0} {
+    verbose -log "BUILD FAILED"
+    fail "$test (could not build/install module)"
+    return
+} else {
+    pass "$test (built and installed module)"
+}
+
+set sym_name "stap_hwbkpt_data"
+if {[catch {exec grep ${sym_name} /proc/kallsyms | awk "{print \$1}" } \
+     res]} {
+    fail "$test (couldn't find module data)"
+    cleanup_module
+    return 0
+}
+    
+set sym_addr "0x${res}"
+pass "$test (found symbol address)"
+verbose -log "probing ${sym_addr}..."
+
+# Make sure cmd file exists
+if {! [file exists ${mod_cmd}]} {
+    fail "$test (couldn't find cmd file - $mod_cmd)"
+    cleanup_module
+    return 0
+}
+pass "$test (found cmd file - $mod_cmd)"
+
+set found 0
+set no_hardware_support 0
+
+# Test address support
+spawn stap -e {probe kernel.data($1).rw { printf("value accessed\n"); exit() }} -c "echo 0 > ${mod_cmd}" ${sym_addr}
+expect {
+    -timeout 240
+    -re {ERROR: probe kernel.data.+ registration error} {
+       incr no_hardware_support; exp_continue } 
+    -re {value accessed\r\n} { incr found; exp_continue }
+    eof { }
+    timeout { fail "$test - addr (${script_name} (timeout))" }
+}
+catch {close}
+
+# get the return code of the process
+set rc [lindex [wait -i $spawn_id] 3]
+
+if { $no_hardware_support == 1 } {
+    xfail "$test - addr (kernel support, but no hardware support)"
+} elseif { $rc == 0 && $found == 1 } {
+    pass "$test - addr (hw breakpoint support)"
+} else {
+    fail "$test - addr ($rc, $found)"
+}
+
+set found 0
+set no_hardware_support 0
+
+# Test symbol support
+spawn stap -e {probe kernel.data(@1).rw { printf("value accessed\n"); exit() }} -c "echo 0 > ${mod_cmd}" ${sym_name}
+expect {
+    -timeout 240
+    -re {ERROR: probe kernel.data.+ registration error} {
+       incr no_hardware_support; exp_continue } 
+    -re {value accessed\r\n} { incr found; exp_continue }
+    eof { }
+    timeout { fail "$test - ${script_name} (timeout)" }
+}
+catch {close}
+
+# get the return code of the process
+set rc [lindex [wait -i $spawn_id] 3]
+
+if { $no_hardware_support == 1 } {
+    xfail "$test - symbol (kernel support, but no hardware support)"
+} elseif { $rc == 0 && $found == 1 } {
+    pass "$test - symbol (hw breakpoint support)"
+} else {
+    fail "$test - symbol ($rc, $found)"
+}
+
+cleanup_module
diff --git a/testsuite/systemtap.base/stap_hwbkpt_kmod.Makefile b/testsuite/systemtap.base/stap_hwbkpt_kmod.Makefile
new file mode 100644 (file)
index 0000000..b92c0ad
--- /dev/null
@@ -0,0 +1,8 @@
+obj-m := stap_hwbkpt_kmod.o
+KDIR := /lib/modules/$(shell uname -r)/build
+PWD := $(shell pwd)
+default:
+       $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
+clean:
+       rm -f *.mod.c stap_hwbkpt_kmod.ko *.o .*.cmd Modules.symvers
+       rm -rf .tmp_versions
diff --git a/testsuite/systemtap.base/stap_hwbkpt_kmod.c b/testsuite/systemtap.base/stap_hwbkpt_kmod.c
new file mode 100644 (file)
index 0000000..c3cb97d
--- /dev/null
@@ -0,0 +1,94 @@
+/* -*- linux-c -*- 
+ * Systemtap Test Module
+ * Copyright (C) 2017 Red Hat Inc.
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <linux/compiler.h>
+#include <asm/uaccess.h>
+
+/*
+ * The purpose of this module is to provide a memory location that
+ * will be modified from user context via a /proc file.  Systemtap
+ * scripts set kernel.data probes on the memory location and run tests
+ * to see if the expected output is received. This is better than
+ * using the kernel's own memory location, since we can't determine
+ * when they will get read/written.
+ */
+
+/************ Below are the functions to create this module ************/
+
+static struct proc_dir_entry *stm_ctl = NULL;
+
+// The memory location to probe/watch.
+int stap_hwbkpt_data = -1;
+
+static ssize_t stm_write_cmd (struct file *file, const char __user *buf,
+                              size_t count, loff_t *ppos)
+{
+       char type;
+
+       if (get_user(type, (char __user *)buf))
+               return -EFAULT;
+
+       switch (type) {
+       case '0':
+       case '1':
+       case '2':
+               stap_hwbkpt_data = __INT_MAX__;
+               break;
+       default:
+               printk ("stap_hwbkpt_kmod: invalid command type %d\n",
+                       (int)type);
+               return -EINVAL;
+       }
+  
+       return count;
+}
+
+static ssize_t stm_read_cmd(struct file *file, char __user *buffer,
+                           size_t buflen, loff_t *fpos)
+{
+       size_t bytes = sizeof(stap_hwbkpt_data);
+
+       if (buflen == 0 || *fpos >= bytes)
+               return 0;
+
+       bytes = min(bytes - (size_t)*fpos, buflen);
+       if (copy_to_user(buffer, &stap_hwbkpt_data + *fpos, bytes))
+               return -EFAULT;
+       *fpos += bytes;
+       return bytes;
+}
+
+static struct file_operations stm_fops_cmd = {
+       .owner = THIS_MODULE,
+       .write = stm_write_cmd,
+       .read = stm_read_cmd,
+};
+
+#define CMD_FILE "stap_hwbkpt_cmd"
+
+int init_module(void)
+{
+       stm_ctl = proc_create (CMD_FILE, 0666, NULL, &stm_fops_cmd);
+       if (stm_ctl == NULL) 
+               return -1;
+       return 0;
+}
+
+void cleanup_module(void)
+{
+       if (stm_ctl)
+               remove_proc_entry (CMD_FILE, NULL);
+}
+
+MODULE_DESCRIPTION("systemtap test module");
+MODULE_LICENSE("GPL");
This page took 0.040496 seconds and 5 git commands to generate.