|
|
132810 |
From 43f6345c9605c0fad57abfe31dda8951f6630ebf Mon Sep 17 00:00:00 2001
|
|
|
132810 |
From: "Frank Ch. Eigler" <fche@redhat.com>
|
|
|
132810 |
Date: Tue, 6 Nov 2018 16:26:57 -0500
|
|
|
132810 |
Subject: [PATCH 22/32] standardize ktime_get_ns() across lkm, bpf runtimes
|
|
|
132810 |
|
|
|
132810 |
Make sure ktime_get_ns() is available across runtimes. In the case of
|
|
|
132810 |
bpf, add a userspace helper to implement the function. Add test case.
|
|
|
132810 |
Add a systemtap.bpf/nobpf.exp test driver, which runs all the
|
|
|
132810 |
bpf_tests but specifically without "--bpf", in the hope that all those
|
|
|
132810 |
scripts should run on the normal backend too. PR23866 blocks some of
|
|
|
132810 |
that at the moment.
|
|
|
132810 |
---
|
|
|
132810 |
stapbpf/bpfinterp.cxx | 13 ++
|
|
|
132810 |
tapset/bpf/time.stp | 2 +-
|
|
|
132810 |
tapset/linux/timestamp_monotonic.stp | 11 ++
|
|
|
132810 |
testsuite/systemtap.bpf/bpf_tests/ktime_get_ns.stp | 33 +++++
|
|
|
132810 |
testsuite/systemtap.bpf/nonbpf.exp | 152 +++++++++++++++++++++
|
|
|
132810 |
5 files changed, 210 insertions(+), 1 deletion(-)
|
|
|
132810 |
create mode 100644 testsuite/systemtap.bpf/bpf_tests/ktime_get_ns.stp
|
|
|
132810 |
create mode 100644 testsuite/systemtap.bpf/nonbpf.exp
|
|
|
132810 |
|
|
|
132810 |
diff --git a/stapbpf/bpfinterp.cxx b/stapbpf/bpfinterp.cxx
|
|
|
132810 |
index fe6eacc50..13ac8ee71 100644
|
|
|
132810 |
--- a/stapbpf/bpfinterp.cxx
|
|
|
132810 |
+++ b/stapbpf/bpfinterp.cxx
|
|
|
132810 |
@@ -162,6 +162,16 @@ bpf_sprintf(std::vector<std::string> &strings, char *fstr,
|
|
|
132810 |
return reinterpret_cast<uint64_t>(strings.back().c_str());
|
|
|
132810 |
}
|
|
|
132810 |
|
|
|
132810 |
+uint64_t
|
|
|
132810 |
+bpf_ktime_get_ns()
|
|
|
132810 |
+{
|
|
|
132810 |
+ struct timespec t;
|
|
|
132810 |
+ clock_gettime (CLOCK_BOOTTIME, &t);
|
|
|
132810 |
+ return (t.tv_sec * 1000000000) + t.tv_nsec;
|
|
|
132810 |
+}
|
|
|
132810 |
+
|
|
|
132810 |
+
|
|
|
132810 |
+
|
|
|
132810 |
uint64_t
|
|
|
132810 |
bpf_interpret(size_t ninsns, const struct bpf_insn insns[],
|
|
|
132810 |
std::vector<int> &map_fds, FILE *output_f)
|
|
|
132810 |
@@ -374,6 +384,9 @@ bpf_interpret(size_t ninsns, const struct bpf_insn insns[],
|
|
|
132810 |
case BPF_FUNC_map_delete_elem:
|
|
|
132810 |
dr = bpf_delete_elem(map_fds[regs[1]], as_ptr(regs[2]));
|
|
|
132810 |
break;
|
|
|
132810 |
+ case BPF_FUNC_ktime_get_ns:
|
|
|
132810 |
+ dr = bpf_ktime_get_ns();
|
|
|
132810 |
+ break;
|
|
|
132810 |
case BPF_FUNC_trace_printk:
|
|
|
132810 |
#pragma GCC diagnostic push
|
|
|
132810 |
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
|
|
|
132810 |
diff --git a/tapset/bpf/time.stp b/tapset/bpf/time.stp
|
|
|
132810 |
index ee615330c..a1c827e73 100644
|
|
|
132810 |
--- a/tapset/bpf/time.stp
|
|
|
132810 |
+++ b/tapset/bpf/time.stp
|
|
|
132810 |
@@ -12,7 +12,7 @@
|
|
|
132810 |
* Description: This function returns the system ktime.
|
|
|
132810 |
*/
|
|
|
132810 |
function ktime_get_ns:long ()
|
|
|
132810 |
-%{ /* bpf */ /* pure */ /* unprivileged */ /* stable */
|
|
|
132810 |
+%{ /* bpf */ /* pure */ /* unprivileged */
|
|
|
132810 |
0x85, 0, 0, 0, 5; /* call BPF_FUNC_ktime_get_ns */
|
|
|
132810 |
0xbf, $$, 0, 0, 0 /* movx $$, r0 */
|
|
|
132810 |
%}
|
|
|
132810 |
diff --git a/tapset/linux/timestamp_monotonic.stp b/tapset/linux/timestamp_monotonic.stp
|
|
|
132810 |
index 6b6d445de..c8d142369 100644
|
|
|
132810 |
--- a/tapset/linux/timestamp_monotonic.stp
|
|
|
132810 |
+++ b/tapset/linux/timestamp_monotonic.stp
|
|
|
132810 |
@@ -148,3 +148,14 @@ function local_clock_ms:long () {
|
|
|
132810 |
function local_clock_s:long () {
|
|
|
132810 |
return local_clock_ns() / 1000000000;
|
|
|
132810 |
}
|
|
|
132810 |
+
|
|
|
132810 |
+
|
|
|
132810 |
+/**
|
|
|
132810 |
+ * sfunction ktime_get_ns - Number of nanoseconds since boot
|
|
|
132810 |
+ *
|
|
|
132810 |
+ * Description: This function returns the system ktime.
|
|
|
132810 |
+ */
|
|
|
132810 |
+function ktime_get_ns:long () %{
|
|
|
132810 |
+ /* pure */ /* unprivileged */
|
|
|
132810 |
+ STAP_RETURN ((int64_t) ktime_get_ns());
|
|
|
132810 |
+%}
|
|
|
132810 |
diff --git a/testsuite/systemtap.bpf/bpf_tests/ktime_get_ns.stp b/testsuite/systemtap.bpf/bpf_tests/ktime_get_ns.stp
|
|
|
132810 |
new file mode 100644
|
|
|
132810 |
index 000000000..0b1d98e94
|
|
|
132810 |
--- /dev/null
|
|
|
132810 |
+++ b/testsuite/systemtap.bpf/bpf_tests/ktime_get_ns.stp
|
|
|
132810 |
@@ -0,0 +1,33 @@
|
|
|
132810 |
+global t1, t2, t3
|
|
|
132810 |
+
|
|
|
132810 |
+probe begin {
|
|
|
132810 |
+ printf("BEGIN\n")
|
|
|
132810 |
+ t1 = ktime_get_ns() // bpfinterp.cxx
|
|
|
132810 |
+}
|
|
|
132810 |
+
|
|
|
132810 |
+probe timer.s(1) {
|
|
|
132810 |
+ t2 = ktime_get_ns() // kernel bpf - XXX watch if timer.s() moves to userspace
|
|
|
132810 |
+}
|
|
|
132810 |
+
|
|
|
132810 |
+probe perf.type(1).config(0).hz(1) {
|
|
|
132810 |
+ t3 = ktime_get_ns() // kernel bpf
|
|
|
132810 |
+}
|
|
|
132810 |
+
|
|
|
132810 |
+
|
|
|
132810 |
+/*
|
|
|
132810 |
+probe kernel.function("SOMETHING") { # to trigger kernel side bpf func
|
|
|
132810 |
+ t3 = ktime.get.ns()
|
|
|
132810 |
+}
|
|
|
132810 |
+*/
|
|
|
132810 |
+
|
|
|
132810 |
+
|
|
|
132810 |
+probe timer.s(5) {
|
|
|
132810 |
+ exit()
|
|
|
132810 |
+}
|
|
|
132810 |
+
|
|
|
132810 |
+probe end {
|
|
|
132810 |
+ if (t1 > 0 && t2 > 0 && t3 > 0)
|
|
|
132810 |
+ printf("END PASS\n")
|
|
|
132810 |
+ else
|
|
|
132810 |
+ printf("END FAIL\n")
|
|
|
132810 |
+}
|
|
|
132810 |
diff --git a/testsuite/systemtap.bpf/nonbpf.exp b/testsuite/systemtap.bpf/nonbpf.exp
|
|
|
132810 |
new file mode 100644
|
|
|
132810 |
index 000000000..35f6a7c99
|
|
|
132810 |
--- /dev/null
|
|
|
132810 |
+++ b/testsuite/systemtap.bpf/nonbpf.exp
|
|
|
132810 |
@@ -0,0 +1,152 @@
|
|
|
132810 |
+# bpf.exp
|
|
|
132810 |
+#
|
|
|
132810 |
+# To restrict scripts to test, set the CHECK_ONLY environment variable.
|
|
|
132810 |
+# For example, to only test the printf and uprobes scripts, run:
|
|
|
132810 |
+#
|
|
|
132810 |
+# make installcheck RUNTESTFLAGS="nonbpf.exp" CHECK_ONLY="printf uprobes"
|
|
|
132810 |
+
|
|
|
132810 |
+set testdir "$srcdir/$subdir/bpf_tests"
|
|
|
132810 |
+
|
|
|
132810 |
+# All tests should start by printing "BEGIN". If OUTPUT_STR is "", then
|
|
|
132810 |
+# the test passes if "END PASS" is read and fails if "END FAIL" is read. Otherwise
|
|
|
132810 |
+# the test passes when "${OUTPUT_STR}END" is read and fails if END is read without
|
|
|
132810 |
+# OUTPUT_STR preceeding it.
|
|
|
132810 |
+proc stapnonbpf_run { TEST_NAME OUTPUT_STR args } {
|
|
|
132810 |
+ global rc
|
|
|
132810 |
+ set rc -1
|
|
|
132810 |
+ set begin_str "BEGIN"
|
|
|
132810 |
+ set pass_str [expr { $OUTPUT_STR == "" ? "END PASS" : "${OUTPUT_STR}END" }]
|
|
|
132810 |
+ set fail_str [expr { $OUTPUT_STR == "" ? "END FAIL" : "END" }]
|
|
|
132810 |
+
|
|
|
132810 |
+ # return codes
|
|
|
132810 |
+ set pass 0
|
|
|
132810 |
+ set fail 1
|
|
|
132810 |
+ set bad_output 2
|
|
|
132810 |
+ set eof_start 3
|
|
|
132810 |
+ set eof_end 4
|
|
|
132810 |
+ set timeout_start 5
|
|
|
132810 |
+ set timeout_end 6
|
|
|
132810 |
+ set invalid_prog 7
|
|
|
132810 |
+ set comp_err 8
|
|
|
132810 |
+
|
|
|
132810 |
+ set cmd [concat stap -v $args]
|
|
|
132810 |
+ # don't the following: ... $test_file_name could be some transient or leftover file
|
|
|
132810 |
+ # if [file readable $test_file_name] { lappend cmd $test_file_name }
|
|
|
132810 |
+
|
|
|
132810 |
+ send_log "executing: $cmd\n"
|
|
|
132810 |
+ eval spawn $cmd
|
|
|
132810 |
+ set mypid [exp_pid -i $spawn_id]
|
|
|
132810 |
+ expect {
|
|
|
132810 |
+ -timeout 30
|
|
|
132810 |
+ -re {^WARNING: cannot find module [^\r]*DWARF[^\r]*\r\n} {exp_continue}
|
|
|
132810 |
+ -re {^WARNING: No unwind data for /.+\r\n} {exp_continue}
|
|
|
132810 |
+ -re {^Pass\ ([1234]):[^\r]*\ in\ ([0-9]+)usr/([0-9]+)sys/([0-9]+)real\ ms\.\r\n}
|
|
|
132810 |
+ {set pass$expect_out(1,string) "\t$expect_out(2,string)\t$expect_out(3,string)\t$expect_out(4,string)"; exp_continue}
|
|
|
132810 |
+ -re {^Pass\ ([34]): using cached [^\r]+\r\n}
|
|
|
132810 |
+ {set pass$expect_out(1,string) "\t0\t0\t0"; exp_continue}
|
|
|
132810 |
+ -re {^Passes: via server [^\r]* using [^\r]* in [0-9]+usr/[0-9]+sys/[0-9]+real ms\.\r\n} {exp_continue}
|
|
|
132810 |
+ -re {^Pass 5: starting run.\r\n} {exp_continue}
|
|
|
132810 |
+ -re $begin_str {
|
|
|
132810 |
+ # By default, "expect -re" will match up to 2000 chars.
|
|
|
132810 |
+ # Increase this to 8K worth of data.
|
|
|
132810 |
+ exp_match_max 8192
|
|
|
132810 |
+
|
|
|
132810 |
+ # Avoid PR17274 to propagate
|
|
|
132810 |
+ set origexpinternal 1
|
|
|
132810 |
+ if {"[exp_internal -info]" == "0"} {set origexpinternal 0}
|
|
|
132810 |
+ #exp_internal 0
|
|
|
132810 |
+
|
|
|
132810 |
+ expect {
|
|
|
132810 |
+ -timeout 20
|
|
|
132810 |
+ -re $pass_str {
|
|
|
132810 |
+ set rc $pass
|
|
|
132810 |
+ }
|
|
|
132810 |
+ -re $fail_str {
|
|
|
132810 |
+ set rc $fail
|
|
|
132810 |
+ }
|
|
|
132810 |
+ default {
|
|
|
132810 |
+ set rc $bad_output
|
|
|
132810 |
+ }
|
|
|
132810 |
+ timeout {
|
|
|
132810 |
+ set rc $timeout_end
|
|
|
132810 |
+ kill -INT -$mypid
|
|
|
132810 |
+ }
|
|
|
132810 |
+ eof { set rc $eof_end }
|
|
|
132810 |
+ }
|
|
|
132810 |
+ exp_internal $origexpinternal
|
|
|
132810 |
+ }
|
|
|
132810 |
+ -re "semantic error:" { set rc $comp_err }
|
|
|
132810 |
+ timeout {
|
|
|
132810 |
+ set rc $timeout_start
|
|
|
132810 |
+ kill -INT -$mypid
|
|
|
132810 |
+ }
|
|
|
132810 |
+ eof { set rc $eof_start }
|
|
|
132810 |
+ }
|
|
|
132810 |
+ # again for good measure with KILL after 3s
|
|
|
132810 |
+ kill -INT -$mypid 3
|
|
|
132810 |
+ catch close
|
|
|
132810 |
+ wait
|
|
|
132810 |
+ return $rc
|
|
|
132810 |
+}
|
|
|
132810 |
+
|
|
|
132810 |
+proc get_output_str { test } {
|
|
|
132810 |
+ global res
|
|
|
132810 |
+ switch $test {
|
|
|
132810 |
+ printf.stp { set res [string repeat "abcd123456" 3] }
|
|
|
132810 |
+ sprintf.stp { set res [string repeat "0123456789" 2] }
|
|
|
132810 |
+ string1.stp { set res {begin\[str0str1str2str3\]probe\[str0str1str2str3\]end\[str0str1str2str3\]} }
|
|
|
132810 |
+ string2.stp { set res {probe0\[str0str1str2str3\]probe1\[str0str1str2str3\]end\[str0str1str2str3\]} }
|
|
|
132810 |
+ default { set res "" }
|
|
|
132810 |
+ }
|
|
|
132810 |
+ return $res
|
|
|
132810 |
+}
|
|
|
132810 |
+
|
|
|
132810 |
+if {[info exists env(CHECK_ONLY)]} {
|
|
|
132810 |
+ set all_files [lsort [glob -nocomplain $testdir/*.stp]]
|
|
|
132810 |
+ set stap_files ""
|
|
|
132810 |
+ foreach file $env(CHECK_ONLY) {
|
|
|
132810 |
+ if {[lsearch $all_files $testdir/$file.stp] >= 0} {
|
|
|
132810 |
+ set stap_files "$stap_files $testdir/$file.stp"
|
|
|
132810 |
+ }
|
|
|
132810 |
+ }
|
|
|
132810 |
+} else {
|
|
|
132810 |
+ set stap_files [lsort [glob -nocomplain $testdir/*.stp]]
|
|
|
132810 |
+}
|
|
|
132810 |
+
|
|
|
132810 |
+foreach file $stap_files {
|
|
|
132810 |
+ global mypid
|
|
|
132810 |
+ set mypid 0
|
|
|
132810 |
+ set test [file tail $file]
|
|
|
132810 |
+ if {! [installtest_p]} { untested $test; continue }
|
|
|
132810 |
+
|
|
|
132810 |
+ # create a process for the tests that require one
|
|
|
132810 |
+ switch $test {
|
|
|
132810 |
+ uprobes.stp {
|
|
|
132810 |
+ eval spawn /usr/bin/sleep 20
|
|
|
132810 |
+ set mypid [exp_pid -i $spawn_id]
|
|
|
132810 |
+ }
|
|
|
132810 |
+ }
|
|
|
132810 |
+
|
|
|
132810 |
+ set output_str [get_output_str $test]
|
|
|
132810 |
+ verbose -log "Running $file"
|
|
|
132810 |
+ switch [stapnonbpf_run $test $output_str $file] {
|
|
|
132810 |
+ 0 { pass $test }
|
|
|
132810 |
+ 1 { fail "$test incorrect result" }
|
|
|
132810 |
+ 2 { fail "$test unexpected output" }
|
|
|
132810 |
+ 3 { fail "$test eof (startup)" }
|
|
|
132810 |
+ 4 { fail "$test eof (shutdown)" }
|
|
|
132810 |
+ 5 { fail "$test timeout (startup)" }
|
|
|
132810 |
+ 6 { fail "$test timeout (startup)" }
|
|
|
132810 |
+ 7 { fail "$test invalid bpf program" }
|
|
|
132810 |
+ 8 { fail "$test compilation" }
|
|
|
132810 |
+ default { fail "$test unknown return value" }
|
|
|
132810 |
+ }
|
|
|
132810 |
+
|
|
|
132810 |
+ if { $mypid > 0 } {
|
|
|
132810 |
+ kill -INT -$mypid 3
|
|
|
132810 |
+ catch close
|
|
|
132810 |
+ wait
|
|
|
132810 |
+ }
|
|
|
132810 |
+}
|
|
|
132810 |
+
|
|
|
132810 |
+
|
|
|
132810 |
--
|
|
|
132810 |
2.14.5
|
|
|
132810 |
|