blob: eee5885e18b4f8a00f909388c8f59e3c325814cf [file] [log] [blame]
From 982d59f0bfdb7a85fd64fcebf4d18b49dfdf5120 Mon Sep 17 00:00:00 2001
From: Li xin <lixin.fnst@cn.fujitsu.com>
Date: Fri, 17 Oct 2014 15:06:28 +0300
Subject: [PATCH] ktap-0.4
---
drivers/staging/Kconfig | 2
drivers/staging/Makefile | 1
drivers/staging/ktap/Kconfig | 32
drivers/staging/ktap/Makefile | 203 +
drivers/staging/ktap/README.md | 167
drivers/staging/ktap/RELEASES.txt | 155
drivers/staging/ktap/doc/tutorial.md | 691 +++
drivers/staging/ktap/include/ktap_ffi.h | 180
drivers/staging/ktap/include/ktap_opcodes.h | 239 +
drivers/staging/ktap/include/ktap_types.h | 609 +++
drivers/staging/ktap/runtime/ffi/call_x86_64.S | 143
drivers/staging/ktap/runtime/ffi/cdata.c | 67
drivers/staging/ktap/runtime/ffi/ffi_call.c | 427 ++
drivers/staging/ktap/runtime/ffi/ffi_symbol.c | 174
drivers/staging/ktap/runtime/ffi/ffi_type.c | 51
drivers/staging/ktap/runtime/ffi/ffi_util.c | 92
drivers/staging/ktap/runtime/kp_amalg.c | 43
drivers/staging/ktap/runtime/kp_load.c | 401 ++
drivers/staging/ktap/runtime/kp_load.h | 6
drivers/staging/ktap/runtime/kp_obj.c | 478 ++
drivers/staging/ktap/runtime/kp_obj.h | 29
drivers/staging/ktap/runtime/kp_opcode.c | 134
drivers/staging/ktap/runtime/kp_str.c | 460 ++
drivers/staging/ktap/runtime/kp_str.h | 20
drivers/staging/ktap/runtime/kp_tab.c | 1396 +++++++
drivers/staging/ktap/runtime/kp_tab.h | 32
drivers/staging/ktap/runtime/kp_transport.c | 641 +++
drivers/staging/ktap/runtime/kp_transport.h | 13
drivers/staging/ktap/runtime/kp_vm.c | 1496 +++++++
drivers/staging/ktap/runtime/kp_vm.h | 16
drivers/staging/ktap/runtime/ktap.c | 217 +
drivers/staging/ktap/runtime/ktap.h | 130
drivers/staging/ktap/runtime/lib_ansi.c | 155
drivers/staging/ktap/runtime/lib_base.c | 607 +++
drivers/staging/ktap/runtime/lib_ffi.c | 50
drivers/staging/ktap/runtime/lib_kdebug.c | 426 ++
drivers/staging/ktap/runtime/lib_timer.c | 193
drivers/staging/ktap/samples/ansi/ansi_color_demo.kp | 22
drivers/staging/ktap/samples/basic/backtrace.kp | 6
drivers/staging/ktap/samples/basic/event_trigger.kp | 24
drivers/staging/ktap/samples/basic/event_trigger_ftrace.kp | 28
drivers/staging/ktap/samples/basic/ftrace.kp | 6
drivers/staging/ktap/samples/basic/function_time.kp | 57
drivers/staging/ktap/samples/basic/kretprobe.kp | 6
drivers/staging/ktap/samples/ffi/ffi_kmalloc.kp | 19
drivers/staging/ktap/samples/ffi/printk.kp | 10
drivers/staging/ktap/samples/ffi/sched_clock.kp | 6
drivers/staging/ktap/samples/game/tetris.kp | 293 +
drivers/staging/ktap/samples/helloworld.kp | 3
drivers/staging/ktap/samples/interrupt/hardirq_time.kp | 24
drivers/staging/ktap/samples/interrupt/softirq_time.kp | 24
drivers/staging/ktap/samples/io/kprobes-do-sys-open.kp | 20
drivers/staging/ktap/samples/io/traceio.kp | 54
drivers/staging/ktap/samples/mem/kmalloc-top.kp | 17
drivers/staging/ktap/samples/mem/kmem.kp | 30
drivers/staging/ktap/samples/profiling/function_profiler.kp | 41
drivers/staging/ktap/samples/profiling/stack_profile.kp | 30
drivers/staging/ktap/samples/schedule/sched_transition.kp | 5
drivers/staging/ktap/samples/schedule/schedtimes.kp | 125
drivers/staging/ktap/samples/syscalls/errinfo.kp | 145
drivers/staging/ktap/samples/syscalls/execve.kp | 8
drivers/staging/ktap/samples/syscalls/opensnoop.kp | 31
drivers/staging/ktap/samples/syscalls/sctop.kp | 13
drivers/staging/ktap/samples/syscalls/syscalls.kp | 6
drivers/staging/ktap/samples/syscalls/syscalls_count.kp | 54
drivers/staging/ktap/samples/syscalls/syscalls_count_by_proc.kp | 22
drivers/staging/ktap/samples/syscalls/syslatl.kp | 30
drivers/staging/ktap/samples/syscalls/syslist.kp | 31
drivers/staging/ktap/samples/tracepoints/eventcount.kp | 210 +
drivers/staging/ktap/samples/tracepoints/eventcount_by_proc.kp | 57
drivers/staging/ktap/samples/tracepoints/tracepoints.kp | 6
drivers/staging/ktap/samples/userspace/gcc_unwind.kp | 9
drivers/staging/ktap/samples/userspace/glibc_func_hist.kp | 44
drivers/staging/ktap/samples/userspace/glibc_sdt.kp | 11
drivers/staging/ktap/samples/userspace/glibc_trace.kp | 11
drivers/staging/ktap/samples/userspace/malloc_free.kp | 20
drivers/staging/ktap/samples/userspace/malloc_size_hist.kp | 22
drivers/staging/ktap/test/arg.kp | 24
drivers/staging/ktap/test/arithmetic.kp | 50
drivers/staging/ktap/test/benchmark/sembench.c | 556 ++
drivers/staging/ktap/test/benchmark/test.sh | 26
drivers/staging/ktap/test/concat.kp | 15
drivers/staging/ktap/test/count.kp | 20
drivers/staging/ktap/test/ffi/.gitignore | 2
drivers/staging/ktap/test/ffi/Makefile | 46
drivers/staging/ktap/test/ffi/cparser_test.c | 322 +
drivers/staging/ktap/test/ffi/ffi_test.kp | 47
drivers/staging/ktap/test/ffi/ktap_ffi_test.c | 64
drivers/staging/ktap/test/fibonacci.kp | 36
drivers/staging/ktap/test/function.kp | 88
drivers/staging/ktap/test/if.kp | 24
drivers/staging/ktap/test/kprobe.kp | 19
drivers/staging/ktap/test/kretprobe.kp | 14
drivers/staging/ktap/test/ksym.kp | 17
drivers/staging/ktap/test/len.kp | 25
drivers/staging/ktap/test/looping.kp | 40
drivers/staging/ktap/test/pairs.kp | 84
drivers/staging/ktap/test/ptable.kp | 46
drivers/staging/ktap/test/run_test.sh | 62
drivers/staging/ktap/test/stack_overflow.kp | 9
drivers/staging/ktap/test/table.kp | 71
drivers/staging/ktap/test/timer.kp | 28
drivers/staging/ktap/test/tracepoint.kp | 22
drivers/staging/ktap/test/zerodivide.kp | 5
drivers/staging/ktap/userspace/code.c | 998 +++++
drivers/staging/ktap/userspace/cparser.h | 202 +
drivers/staging/ktap/userspace/dump.c | 251 +
drivers/staging/ktap/userspace/eventdef.c | 857 ++++
drivers/staging/ktap/userspace/ffi/cparser.c | 1755 ++++++++
drivers/staging/ktap/userspace/ffi/ctype.c | 551 ++
drivers/staging/ktap/userspace/ktapc.h | 393 ++
drivers/staging/ktap/userspace/ktapio.c | 106
drivers/staging/ktap/userspace/lex.c | 632 +++
drivers/staging/ktap/userspace/main.c | 727 +++
drivers/staging/ktap/userspace/parser.c | 1963 ++++++++++
drivers/staging/ktap/userspace/symbol.c | 291 +
drivers/staging/ktap/userspace/symbol.h | 50
drivers/staging/ktap/userspace/util.c | 381 +
118 files changed, 22675 insertions(+)
create mode 100644 drivers/staging/ktap/Kconfig
create mode 100644 drivers/staging/ktap/Makefile
create mode 100644 drivers/staging/ktap/README.md
create mode 100644 drivers/staging/ktap/RELEASES.txt
create mode 100644 drivers/staging/ktap/doc/tutorial.md
create mode 100644 drivers/staging/ktap/include/ktap_ffi.h
create mode 100644 drivers/staging/ktap/include/ktap_opcodes.h
create mode 100644 drivers/staging/ktap/include/ktap_types.h
create mode 100644 drivers/staging/ktap/runtime/ffi/call_x86_64.S
create mode 100644 drivers/staging/ktap/runtime/ffi/cdata.c
create mode 100644 drivers/staging/ktap/runtime/ffi/ffi_call.c
create mode 100644 drivers/staging/ktap/runtime/ffi/ffi_symbol.c
create mode 100644 drivers/staging/ktap/runtime/ffi/ffi_type.c
create mode 100644 drivers/staging/ktap/runtime/ffi/ffi_util.c
create mode 100644 drivers/staging/ktap/runtime/kp_amalg.c
create mode 100644 drivers/staging/ktap/runtime/kp_load.c
create mode 100644 drivers/staging/ktap/runtime/kp_load.h
create mode 100644 drivers/staging/ktap/runtime/kp_obj.c
create mode 100644 drivers/staging/ktap/runtime/kp_obj.h
create mode 100644 drivers/staging/ktap/runtime/kp_opcode.c
create mode 100644 drivers/staging/ktap/runtime/kp_str.c
create mode 100644 drivers/staging/ktap/runtime/kp_str.h
create mode 100644 drivers/staging/ktap/runtime/kp_tab.c
create mode 100644 drivers/staging/ktap/runtime/kp_tab.h
create mode 100644 drivers/staging/ktap/runtime/kp_transport.c
create mode 100644 drivers/staging/ktap/runtime/kp_transport.h
create mode 100644 drivers/staging/ktap/runtime/kp_vm.c
create mode 100644 drivers/staging/ktap/runtime/kp_vm.h
create mode 100644 drivers/staging/ktap/runtime/ktap.c
create mode 100644 drivers/staging/ktap/runtime/ktap.h
create mode 100644 drivers/staging/ktap/runtime/lib_ansi.c
create mode 100644 drivers/staging/ktap/runtime/lib_base.c
create mode 100644 drivers/staging/ktap/runtime/lib_ffi.c
create mode 100644 drivers/staging/ktap/runtime/lib_kdebug.c
create mode 100644 drivers/staging/ktap/runtime/lib_timer.c
create mode 100644 drivers/staging/ktap/samples/ansi/ansi_color_demo.kp
create mode 100644 drivers/staging/ktap/samples/basic/backtrace.kp
create mode 100644 drivers/staging/ktap/samples/basic/event_trigger.kp
create mode 100644 drivers/staging/ktap/samples/basic/event_trigger_ftrace.kp
create mode 100644 drivers/staging/ktap/samples/basic/ftrace.kp
create mode 100644 drivers/staging/ktap/samples/basic/function_time.kp
create mode 100644 drivers/staging/ktap/samples/basic/kretprobe.kp
create mode 100644 drivers/staging/ktap/samples/ffi/ffi_kmalloc.kp
create mode 100644 drivers/staging/ktap/samples/ffi/printk.kp
create mode 100644 drivers/staging/ktap/samples/ffi/sched_clock.kp
create mode 100644 drivers/staging/ktap/samples/game/tetris.kp
create mode 100644 drivers/staging/ktap/samples/helloworld.kp
create mode 100644 drivers/staging/ktap/samples/interrupt/hardirq_time.kp
create mode 100644 drivers/staging/ktap/samples/interrupt/softirq_time.kp
create mode 100644 drivers/staging/ktap/samples/io/kprobes-do-sys-open.kp
create mode 100644 drivers/staging/ktap/samples/io/traceio.kp
create mode 100644 drivers/staging/ktap/samples/mem/kmalloc-top.kp
create mode 100644 drivers/staging/ktap/samples/mem/kmem.kp
create mode 100644 drivers/staging/ktap/samples/profiling/function_profiler.kp
create mode 100644 drivers/staging/ktap/samples/profiling/stack_profile.kp
create mode 100644 drivers/staging/ktap/samples/schedule/sched_transition.kp
create mode 100644 drivers/staging/ktap/samples/schedule/schedtimes.kp
create mode 100644 drivers/staging/ktap/samples/syscalls/errinfo.kp
create mode 100644 drivers/staging/ktap/samples/syscalls/execve.kp
create mode 100644 drivers/staging/ktap/samples/syscalls/opensnoop.kp
create mode 100644 drivers/staging/ktap/samples/syscalls/sctop.kp
create mode 100644 drivers/staging/ktap/samples/syscalls/syscalls.kp
create mode 100644 drivers/staging/ktap/samples/syscalls/syscalls_count.kp
create mode 100644 drivers/staging/ktap/samples/syscalls/syscalls_count_by_proc.kp
create mode 100644 drivers/staging/ktap/samples/syscalls/syslatl.kp
create mode 100644 drivers/staging/ktap/samples/syscalls/syslist.kp
create mode 100644 drivers/staging/ktap/samples/tracepoints/eventcount.kp
create mode 100644 drivers/staging/ktap/samples/tracepoints/eventcount_by_proc.kp
create mode 100644 drivers/staging/ktap/samples/tracepoints/tracepoints.kp
create mode 100644 drivers/staging/ktap/samples/userspace/gcc_unwind.kp
create mode 100644 drivers/staging/ktap/samples/userspace/glibc_func_hist.kp
create mode 100644 drivers/staging/ktap/samples/userspace/glibc_sdt.kp
create mode 100644 drivers/staging/ktap/samples/userspace/glibc_trace.kp
create mode 100644 drivers/staging/ktap/samples/userspace/malloc_free.kp
create mode 100644 drivers/staging/ktap/samples/userspace/malloc_size_hist.kp
create mode 100644 drivers/staging/ktap/test/arg.kp
create mode 100644 drivers/staging/ktap/test/arithmetic.kp
create mode 100644 drivers/staging/ktap/test/benchmark/sembench.c
create mode 100644 drivers/staging/ktap/test/benchmark/test.sh
create mode 100644 drivers/staging/ktap/test/concat.kp
create mode 100644 drivers/staging/ktap/test/count.kp
create mode 100644 drivers/staging/ktap/test/ffi/.gitignore
create mode 100644 drivers/staging/ktap/test/ffi/Makefile
create mode 100644 drivers/staging/ktap/test/ffi/cparser_test.c
create mode 100644 drivers/staging/ktap/test/ffi/ffi_test.kp
create mode 100644 drivers/staging/ktap/test/ffi/ktap_ffi_test.c
create mode 100644 drivers/staging/ktap/test/fibonacci.kp
create mode 100644 drivers/staging/ktap/test/function.kp
create mode 100644 drivers/staging/ktap/test/if.kp
create mode 100644 drivers/staging/ktap/test/kprobe.kp
create mode 100644 drivers/staging/ktap/test/kretprobe.kp
create mode 100644 drivers/staging/ktap/test/ksym.kp
create mode 100644 drivers/staging/ktap/test/len.kp
create mode 100644 drivers/staging/ktap/test/looping.kp
create mode 100644 drivers/staging/ktap/test/pairs.kp
create mode 100644 drivers/staging/ktap/test/ptable.kp
create mode 100644 drivers/staging/ktap/test/run_test.sh
create mode 100644 drivers/staging/ktap/test/stack_overflow.kp
create mode 100644 drivers/staging/ktap/test/table.kp
create mode 100644 drivers/staging/ktap/test/timer.kp
create mode 100644 drivers/staging/ktap/test/tracepoint.kp
create mode 100644 drivers/staging/ktap/test/zerodivide.kp
create mode 100644 drivers/staging/ktap/userspace/code.c
create mode 100644 drivers/staging/ktap/userspace/cparser.h
create mode 100644 drivers/staging/ktap/userspace/dump.c
create mode 100644 drivers/staging/ktap/userspace/eventdef.c
create mode 100644 drivers/staging/ktap/userspace/ffi/cparser.c
create mode 100644 drivers/staging/ktap/userspace/ffi/ctype.c
create mode 100644 drivers/staging/ktap/userspace/ktapc.h
create mode 100644 drivers/staging/ktap/userspace/ktapio.c
create mode 100644 drivers/staging/ktap/userspace/lex.c
create mode 100644 drivers/staging/ktap/userspace/main.c
create mode 100644 drivers/staging/ktap/userspace/parser.c
create mode 100644 drivers/staging/ktap/userspace/symbol.c
create mode 100644 drivers/staging/ktap/userspace/symbol.h
create mode 100644 drivers/staging/ktap/userspace/util.c
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -146,4 +146,6 @@ source "drivers/staging/dgnc/Kconfig"
source "drivers/staging/dgap/Kconfig"
+source "drivers/staging/ktap/Kconfig"
+
endif # STAGING
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -65,3 +65,4 @@ obj-$(CONFIG_XILLYBUS) += xillybus/
obj-$(CONFIG_DGNC) += dgnc/
obj-$(CONFIG_DGAP) += dgap/
obj-$(CONFIG_MTD_SPINAND_MT29F) += mt29f_spinand/
+obj-$(CONFIG_KTAP) += ktap/
--- /dev/null
+++ b/drivers/staging/ktap/Kconfig
@@ -0,0 +1,32 @@
+config KTAP
+ tristate "a programable dynamic tracing tool for Linux"
+ depends on PERF_EVENTS && EVENT_TRACING
+ default n
+ help
+ ktap is a new script-based dynamic tracing tool for Linux,
+ it uses a scripting language and lets users trace the
+ Linux kernel dynamically. ktap is designed to give
+ operational insights with interoperability that allow
+ users to tune, troubleshoot and extend kernel and application.
+ It's similar with Linux Systemtap and Solaris Dtrace.
+
+ ktap have different design principles from Linux mainstream
+ dynamic tracing language in that it's based on bytecode,
+ so it doesn't depend upon GCC, doesn't require compiling
+ kernel module for each script, safe to use in production
+ environment, fulfilling the embedded ecosystem's tracing needs.
+
+ See ktap tutorial for more information:
+ http://www.ktap.org/doc/tutorial.html
+
+config KTAP_FFI
+ tristate "FFI support for ktap"
+ depends on KTAP
+ depends on X86_64
+ default n
+ help
+ This option brings FFI support to ktap. With FFI enabled ktap,
+ users can call into native kernel C function directly in ktap
+ script. Except for a new cdef keyword, this option also adds
+ a ffi module which exports helper functions like ffi.new and
+ ffi.sizeof.
--- /dev/null
+++ b/drivers/staging/ktap/Makefile
@@ -0,0 +1,203 @@
+
+#
+# Define NO_LIBELF if you do not want libelf dependency (e.g. cross-builds)
+# (this will also disable resolve resolving symbols in DSO functionality)
+#
+# Define FFI if you want to compile ktap with FFI support. By default This
+# toggle is off.
+#
+# Define amalg to enable amalgamation build, This compiles the ktapvm as
+# one huge C file and allows GCC to generate faster and shorter code. Alas,
+# this requires lots of memory during the build.
+# Recommend to use amalgmation build as default.
+amalg = 1
+NO_LIBELF = 1
+# Do not instrument the tracer itself:
+ifdef CONFIG_FUNCTION_TRACER
+ORIG_CFLAGS := $(KBUILD_CFLAGS)
+KBUILD_CFLAGS = $(subst -pg,,$(ORIG_CFLAGS))
+endif
+
+all: mod ktap
+
+INC = include
+RUNTIME = runtime
+
+FFIDIR = $(RUNTIME)/ffi
+KTAP_LIBS = -lpthread
+
+LIB_OBJS += $(RUNTIME)/lib_base.o $(RUNTIME)/lib_kdebug.o $(RUNTIME)/lib_timer.o \
+ $(RUNTIME)/lib_ansi.o
+
+ifndef amalg
+ifdef FFI
+FFI_OBJS += $(FFIDIR)/ffi_call.o $(FFIDIR)/ffi_type.o $(FFIDIR)/ffi_symbol.o \
+ $(FFIDIR)/cdata.o $(FFIDIR)/ffi_util.o
+RUNTIME_OBJS += $(FFI_OBJS)
+LIB_OBJS += $(RUNTIME)/lib_ffi.o
+endif
+RUNTIME_OBJS += $(RUNTIME)/ktap.o $(RUNTIME)/kp_load.o $(RUNTIME)/kp_obj.o \
+ $(RUNTIME)/kp_str.o $(RUNTIME)/kp_tab.o $(RUNTIME)/kp_vm.o \
+ $(RUNTIME)/kp_opcode.o $(RUNTIME)/kp_transport.o \
+ $(LIB_OBJS)
+else
+RUNTIME_OBJS += $(RUNTIME)/kp_amalg.o
+endif
+
+ifdef FFI
+ifeq ($(KBUILD_MODULES), 1)
+ifdef CONFIG_X86_64
+# call_x86_64.o is compiled from call_x86_64.S
+RUNTIME_OBJS += $(FFIDIR)/call_x86_64.o
+else
+$(error ktap FFI only supports x86_64 for now!)
+endif
+endif
+
+
+ccflags-y += -DCONFIG_KTAP_FFI
+endif
+
+obj-m += ktapvm.o
+ktapvm-y := $(RUNTIME_OBJS)
+
+KVERSION ?= $(shell uname -r)
+KERNEL_SRC ?= /lib/modules/$(KVERSION)/build
+PWD := $(shell pwd)
+mod:
+ $(MAKE) -C $(KERNEL_SRC) M=$(PWD) modules
+
+modules_install:
+ $(MAKE) -C $(KERNEL_SRC) M=$(PWD) modules_install
+
+KTAPC_CFLAGS = -Wall -O2
+
+
+# try-cc
+# Usage: option = $(call try-cc, source-to-build, cc-options, msg)
+ifneq ($(V),1)
+TRY_CC_OUTPUT= > /dev/null 2>&1
+endif
+TRY_CC_MSG=echo " CHK $(3)" 1>&2;
+
+try-cc = $(shell sh -c \
+ 'TMP="/tmp/.$$$$"; \
+ $(TRY_CC_MSG) \
+ echo "$(1)" | \
+ $(CC) -x c - $(2) -o "$$TMP" $(TRY_CC_OUTPUT) && echo y; \
+ rm -f "$$TMP"')
+
+
+define SOURCE_LIBELF
+#include <libelf.h>
+
+int main(void)
+{
+ Elf *elf = elf_begin(0, ELF_C_READ, 0);
+ return (long)elf;
+}
+endef
+
+FLAGS_LIBELF = -lelf
+
+ifdef NO_LIBELF
+ KTAPC_CFLAGS += -DNO_LIBELF
+else
+ifneq ($(call try-cc,$(SOURCE_LIBELF),$(FLAGS_LIBELF),libelf),y)
+ $(warning No libelf found, disables symbol resolving, please install elfutils-libelf-devel/libelf-dev);
+ NO_LIBELF := 1
+ KTAPC_CFLAGS += -DNO_LIBELF
+else
+ KTAP_LIBS += -lelf
+endif
+endif
+
+UDIR = userspace
+
+$(UDIR)/lex.o: $(UDIR)/lex.c $(INC)/*
+ $(QUIET_CC)$(CC) $(DEBUGINFO_FLAG) $(KTAPC_CFLAGS) -o $@ -c $<
+$(UDIR)/parser.o: $(UDIR)/parser.c $(INC)/*
+ $(QUIET_CC)$(CC) $(DEBUGINFO_FLAG) $(KTAPC_CFLAGS) -o $@ -c $<
+$(UDIR)/code.o: $(UDIR)/code.c $(INC)/*
+ $(QUIET_CC)$(CC) $(DEBUGINFO_FLAG) $(KTAPC_CFLAGS) -o $@ -c $<
+$(UDIR)/dump.o: $(UDIR)/dump.c $(INC)/*
+ $(QUIET_CC)$(CC) $(DEBUGINFO_FLAG) $(KTAPC_CFLAGS) -o $@ -c $<
+$(UDIR)/main.o: $(UDIR)/main.c $(INC)/*
+ $(QUIET_CC)$(CC) $(DEBUGINFO_FLAG) $(KTAPC_CFLAGS) -o $@ -c $<
+$(UDIR)/util.o: $(UDIR)/util.c $(INC)/*
+ $(QUIET_CC)$(CC) $(DEBUGINFO_FLAG) $(KTAPC_CFLAGS) -o $@ -c $<
+$(UDIR)/ktapio.o: $(UDIR)/ktapio.c $(INC)/*
+ $(QUIET_CC)$(CC) $(DEBUGINFO_FLAG) $(KTAPC_CFLAGS) -o $@ -c $<
+$(UDIR)/eventdef.o: $(UDIR)/eventdef.c $(INC)/*
+ $(QUIET_CC)$(CC) $(DEBUGINFO_FLAG) $(KTAPC_CFLAGS) -o $@ -c $<
+$(UDIR)/kp_opcode.o: $(RUNTIME)/kp_opcode.c $(INC)/*
+ $(QUIET_CC)$(CC) $(DEBUGINFO_FLAG) $(KTAPC_CFLAGS) -o $@ -c $<
+$(UDIR)/kp_tab.o: $(RUNTIME)/kp_tab.c $(INC)/*
+ $(QUIET_CC)$(CC) $(DEBUGINFO_FLAG) $(KTAPC_CFLAGS) -o $@ -c $<
+$(UDIR)/kp_str.o: $(RUNTIME)/kp_str.c $(INC)/*
+ $(QUIET_CC)$(CC) $(DEBUGINFO_FLAG) $(KTAPC_CFLAGS) -o $@ -c $<
+$(UDIR)/kp_obj.o: $(RUNTIME)/kp_obj.c $(INC)/*
+ $(QUIET_CC)$(CC) $(DEBUGINFO_FLAG) $(KTAPC_CFLAGS) -o $@ -c $<
+ifndef NO_LIBELF
+$(UDIR)/symbol.o: $(UDIR)/symbol.c
+ $(QUIET_CC)$(CC) $(DEBUGINFO_FLAG) $(KTAPC_CFLAGS) -o $@ -c $<
+endif
+ifdef FFI
+KTAPC_CFLAGS += -DCONFIG_KTAP_FFI
+$(UDIR)/ffi_type.o: $(RUNTIME)/ffi/ffi_type.c $(INC)/*
+ $(QUIET_CC)$(CC) $(DEBUGINFO_FLAG) $(KTAPC_CFLAGS) -o $@ -c $<
+$(UDIR)/ffi/cparser.o: $(UDIR)/ffi/cparser.c $(INC)/*
+ $(QUIET_CC)$(CC) $(DEBUGINFO_FLAG) $(KTAPC_CFLAGS) -o $@ -c $<
+$(UDIR)/ffi/ctype.o: $(UDIR)/ffi/ctype.c $(INC)/*
+ $(QUIET_CC)$(CC) $(DEBUGINFO_FLAG) $(KTAPC_CFLAGS) -o $@ -c $<
+endif
+
+
+KTAPOBJS =
+KTAPOBJS += $(UDIR)/lex.o
+KTAPOBJS += $(UDIR)/parser.o
+KTAPOBJS += $(UDIR)/code.o
+KTAPOBJS += $(UDIR)/dump.o
+KTAPOBJS += $(UDIR)/main.o
+KTAPOBJS += $(UDIR)/util.o
+KTAPOBJS += $(UDIR)/ktapio.o
+KTAPOBJS += $(UDIR)/eventdef.o
+KTAPOBJS += $(UDIR)/kp_opcode.o
+KTAPOBJS += $(UDIR)/kp_tab.o
+KTAPOBJS += $(UDIR)/kp_str.o
+KTAPOBJS += $(UDIR)/kp_obj.o
+ifndef NO_LIBELF
+KTAPOBJS += $(UDIR)/symbol.o
+endif
+ifdef FFI
+KTAPOBJS += $(UDIR)/ffi_type.o
+KTAPOBJS += $(UDIR)/ffi/cparser.o
+KTAPOBJS += $(UDIR)/ffi/ctype.o
+endif
+
+ktap: $(KTAPOBJS)
+ $(QUIET_LINK)$(CC) $(KTAPC_CFLAGS) -o $@ $(KTAPOBJS) $(KTAP_LIBS)
+
+KMISC := /lib/modules/$(KVERSION)/ktapvm/
+
+install: mod ktap
+ install -d $(KMISC)
+ install -m 644 -c *.ko /lib/modules/$(KVERSION)/ktapvm/
+ /sbin/depmod -a
+
+load:
+ insmod ktapvm.ko
+
+unload:
+ rmmod ktapvm
+
+test: FORCE
+ cd test; sh ./run_test.sh; cd -
+
+clean:
+ $(MAKE) -C $(KERNEL_SRC) M=$(PWD) clean
+ $(RM) ktap
+
+PHONY += FORCE
+FORCE:
+
--- /dev/null
+++ b/drivers/staging/ktap/README.md
@@ -0,0 +1,167 @@
+# ktap
+
+A New Scripting Dynamic Tracing Tool For Linux
+[www.ktap.org][homepage]
+
+ktap is a new scripting dynamic tracing tool for Linux,
+it uses a scripting language and lets users trace the Linux kernel dynamically.
+ktap is designed to give operational insights with interoperability
+that allows users to tune, troubleshoot and extend kernel and application.
+It's similar with Linux Systemtap and Solaris Dtrace.
+
+ktap have different design principles from Linux mainstream dynamic tracing
+language in that it's based on bytecode, so it doesn't depend upon GCC,
+doesn't require compiling kernel module for each script, safe to use in
+production environment, fulfilling the embedded ecosystem's tracing needs.
+
+More information can be found at [ktap homepage][homepage].
+
+[homepage]: http://www.ktap.org
+
+## Highlights
+
+ * simple but powerful scripting language
+ * register based interpreter (heavily optimized) in Linux kernel
+ * small and lightweight (6KLOC of interpreter)
+ * not depend on gcc for each script running
+ * easy to use in embedded environment without debugging info
+ * support for tracepoint, kprobe, uprobe, function trace, timer, and more
+ * supported in x86, arm, ppc, mips
+ * safety in sandbox
+
+## Building & Running
+
+1. Clone ktap from github
+
+ $ git clone http://github.com/ktap/ktap.git
+
+2. Compiling ktap
+
+ $ cd ktap
+ $ make #generate ktapvm kernel module and ktap binary
+
+3. Load ktapvm kernel module(make sure debugfs mounted)
+
+ $ make load #need to be root or have sudo access
+
+4. Running ktap
+
+ $ ./ktap samples/helloworld.kp
+
+
+## Examples
+
+1. simplest one-liner command to enable all tracepoints
+
+ ktap -e "trace *:* { print(argevent) }"
+
+2. syscall tracing on target process
+
+ ktap -e "trace syscalls:* { print(argevent) }" -- ls
+
+3. ftrace(kernel newer than 3.3, and must compiled with CONFIG_FUNCTION_TRACER)
+
+ ktap -e "trace ftrace:function { print(argevent) }"
+
+ ktap -e "trace ftrace:function /ip==mutex*/ { print(argevent) }"
+
+4. simple syscall tracing
+
+ trace syscalls:* {
+ print(cpu(), pid(), execname(), argevent)
+ }
+
+5. syscall tracing in histogram style
+
+ s = {}
+
+ trace syscalls:sys_enter_* {
+ s[argname] += 1
+ }
+
+ trace_end {
+ histogram(s)
+ }
+
+6. kprobe tracing
+
+ trace probe:do_sys_open dfd=%di fname=%dx flags=%cx mode=+4($stack) {
+ print("entry:", execname(), argevent)
+ }
+
+ trace probe:do_sys_open%return fd=$retval {
+ print("exit:", execname(), argevent)
+ }
+
+7. uprobe tracing
+
+ trace probe:/lib/libc.so.6:malloc {
+ print("entry:", execname(), argevent)
+ }
+
+ trace probe:/lib/libc.so.6:malloc%return {
+ print("exit:", execname(), argevent)
+ }
+
+8. stapsdt tracing (userspace static marker)
+
+ trace sdt:/lib64/libc.so.6:lll_futex_wake {
+ print("lll_futex_wake", execname(), argevent)
+ }
+
+ or:
+
+ #trace all static mark in libc
+ trace sdt:/lib64/libc.so.6:* {
+ print(execname(), argevent)
+ }
+
+9. timer
+
+ tick-1ms {
+ printf("time fired on one cpu\n");
+ }
+
+ profile-2s {
+ printf("time fired on every cpu\n");
+ }
+
+10. FFI (Call kernel function from ktap script, need compile with FFI=1)
+
+ cdef[[
+ int printk(char *fmt, ...);
+ ]]
+
+ C.printk("This message is called from ktap ffi\n")
+
+More examples can be found at [samples][samples_dir] directory.
+
+[samples_dir]: https://github.com/ktap/ktap/tree/master/samples
+
+## Mailing list
+
+ktap@freelists.org
+You can subscribe to ktap mailing list at link (subscribe before posting):
+http://www.freelists.org/list/ktap
+
+
+## Copyright and License
+
+ktap is licensed under GPL v2
+
+Copyright (C) 2012-2013, Jovi Zhangwei <jovi.zhangwei@gmail.com>.
+All rights reserved.
+
+
+## Contribution
+
+ktap is still under active development, so contributions are welcome.
+You are encouraged to report bugs, provide feedback, send feature request,
+or hack on it.
+
+
+## See More
+
+More info can be found at [documentation][tutorial]
+[tutorial]: http://www.ktap.org/doc/tutorial.html
+
--- /dev/null
+++ b/drivers/staging/ktap/RELEASES.txt
@@ -0,0 +1,155 @@
+Version 0.4 (Dec 9 2013)
+-------------------------
+= Highlight changes from v0.3
+
+ * kernel symbol read (syntax: `symbol_name`)
+
+ * parse symbol on uprobe (need libelf link)
+ trace probe:/lib64/libc.so.6:malloc {}
+ trace probe:/lib64/libc.so.6:malloc%return {}
+ trace probe:/lib64/libc.so.6:* {} # trace all function in glibc
+
+ * support static marker(SDT)
+ trace sdt:/lib64/libc.so.6:setjmp {}
+ trace sdt:/lib64/libc.so.6:* {} # trace all sdt in glibc
+
+ * support kprobe wildcard
+ trace probe:vfs* {}
+
+ * support run multiple ktap instances concurrently
+
+ * add command option for list available events and symbols
+ -le [glob] : list pre-defined events in system
+ -lf DSO : list available functions from DSO
+ -lm DSO : list available sdt notes from DSO
+
+ * better annotation for output of argname
+
+ * basic FFI support (depend on CONFIG_KTAP_FFI)
+ FFI will allow call kernel function from ktap script
+
+ cdef [[ int printk(char *fmt, ...); ]]
+ C.printk("this is ffi printk from ktap\n")
+
+ (currently only support basic C types, structure support is ongoing)
+
+ * New sample scripts
+ userspace/malloc_size_hist.kp
+ userspace/malloc_free.kp
+ userspace/gcc_unwind.kp
+ userspace/glibc_sdt.kp #trace all static marker in glibc
+ userspace/glibc_trace.kp #trace all functions in glibc
+ userspace/glibc_func_hist.kp #show glibc functions in histogram
+ syscalls/syslatl.kp #syscall latency linear aggregation
+ syscalls/syslist.kp #syscall latency as a list with counts
+ syscalls/opensnoop.kp #trace open() syscalls and print basic details
+ ffi/ffi_kmalloc.kp
+ ffi/printk.kp
+ ffi/sched_clock.kp
+
+ * use amalgamation build as default
+ x86_64 build: ktap binary size is 98K, ktapvm.ko size is 983K
+
+ * Big cleanups and lots of bugfix
+
+
+Version 0.3 (Oct 29 2013)
+-------------------------
+= Highlight changes from v0.2
+
+ * Homepage released: www.ktap.org
+
+ * Tutorial: http://www.ktap.org/doc/tutorial.html
+
+ * Wiki: https://github.com/ktap/ktap/wiki
+
+ * simple new tracing block syntax
+ trace EVENTDEF { action }
+ trace_end { action }
+
+ * New event tracing keywords: argevent, argname, arg1..arg9
+ trace "syscalls:*" function () {
+ print(argevent)
+ }
+
+ * New timer block syntax
+ tick-N { action }
+ profile-N { action }
+
+ * Basic aggregation support
+ It's similar with systemtap, use "<<<" operator
+ support aggregate function: count, sum, avg, max, min
+
+ * Introduce new "+=" operator
+
+ * Introduce sort_paris for table sort iteration
+
+ * New sample scripts
+ helloworld.kp
+ syscalls/sctop.kp
+ profiling/stack_profile.kp
+ io/traceio.kp
+ mem/kmalloc-top.kp
+ syscalls/errinfo.kp
+ schedule/schedtimes.kp
+ game/tetris.kp
+
+ * ansi library for sending ANSI escape sequences
+
+
+ * statistics of ktapvm
+
+ * Big cleanups and lots of bugfix
+
+Version 0.2 (Jul 31 2013)
+-------------------------
+
+= Script highlight changes from v0.1
+
+ * new tracing block syntax
+ trace EVENTDEF function (e) { BODY }
+ trace_end function (e) { BODY }
+
+ * support trace filter
+ trace 'sched:sched_switch /prev_comm == foo || next_comm == foo/
+
+ * support kprobe/kretprobe
+ trace "probe:do_sys_open dfd=%di filename=%dx flags=%cx mode=+4($stack)"
+ trace "probe:do_sys_open%return fd=$retval"
+
+ * support uprobe/uretprobe
+ trace "probe:/lib/libc.so.6:0x000773c0"
+ trace "probe:/lib/libc.so.6:0x000773c0%return"
+
+ * support function tracing
+ trace "ftrace:function /ip == mutex*/"
+
+ * support oneline scripting
+ ktap -e 'trace "syscalls:*" function (e) { print(e) }'
+
+ * specific pid or cpu to tracing
+ ktap -C cpu *.kp
+ ktap -p pid *.kp
+
+ * more sample scripts
+
+ * support calling print_backtrace() in any context
+
+ * support calling exit() in any context
+
+= Backend highlight changes from v0.1
+
+ * unified perf callback mechanism
+ * use ring buffer transport instead of relayfs
+ * reentrant in ktap tracing
+ * performance boost(use percpu data in many case)
+ * safe table/string manipulation
+ * safe ktap exit
+ * big code cleanups
+ * fixed a lot of bugs, more stable than v0.1
+
+Version 0.1 (May 21 2013)
+-------------------------
+
+ https://lwn.net/Articles/551253/
+
--- /dev/null
+++ b/drivers/staging/ktap/doc/tutorial.md
@@ -0,0 +1,691 @@
+% The ktap Tutorial
+
+# Introduction
+
+ktap is a new script-based dynamic tracing tool for linux
+http://www.ktap.org
+
+ktap is a new script-based dynamic tracing tool for Linux,
+it uses a scripting language and lets users trace the Linux kernel dynamically.
+ktap is designed to give operational insights with interoperability
+that allows users to tune, troubleshoot and extend kernel and application.
+It's similar with Linux Systemtap and Solaris Dtrace.
+
+ktap have different design principles from Linux mainstream dynamic tracing
+language in that it's based on bytecode, so it doesn't depend upon GCC,
+doesn't require compiling kernel module for each script, safe to use in
+production environment, fulfilling the embedded ecosystem's tracing needs.
+
+Highlights features:
+
+* simple but powerful scripting language
+* register based interpreter (heavily optimized) in Linux kernel
+* small and lightweight
+* not depend on gcc for each script running
+* easy to use in embedded environment without debugging info
+* support for tracepoint, kprobe, uprobe, function trace, timer, and more
+* supported in x86, arm, ppc, mips
+* safety in sandbox
+
+
+# Getting started
+
+Requirements
+
+* Linux 3.1 or later(Need some kernel patches for kernel earlier than 3.1)
+* CONFIG_EVENT_TRACING enabled
+* CONFIG_PERF_EVENTS enabled
+* CONFIG_DEBUG_FS enabled
+ make sure debugfs mounted before insmod ktapvm
+ mount debugfs: mount -t debugfs none /sys/kernel/debug/
+* libelf (optional)
+ Install elfutils-libelf-devel on RHEL-based distros, or libelf-dev on
+ Debian-based distros.
+ Use `make NO_LIBELF=1` to build without libelf support.
+ libelf is required for resolving symbols to addresses in DSO, and for sdt.
+
+Note that those configuration is always enabled in Linux distribution,
+like REHL, Fedora, Ubuntu, etc.
+
+1. Clone ktap from github
+
+ $ git clone http://github.com/ktap/ktap.git
+
+2. Compiling ktap
+
+ $ cd ktap
+ $ make #generate ktapvm kernel module and ktap binary
+
+3. Load ktapvm kernel module(make sure debugfs mounted)
+
+ $ make load #need to be root or have sudo access
+
+4. Running ktap
+
+ $ ./ktap scripts/helloworld.kp
+
+
+# Language basics
+
+## Syntax basics
+
+ktap's syntax is design on the mind of C language syntax friendly,
+to make it easy scripting by kernel developer.
+
+1. Variable declaration
+The biggest syntax differences with C is that ktap is a dynamic typed
+language, so you won't need add any variable type declaration, just
+use the variable.
+
+2. function
+All functions in ktap should use keyword "function" declaration
+
+3. comments
+The comments of ktap is starting from '#', long comments doesn't support now.
+
+4. others
+Don't need place any ';' at the ending of statement in ktap.
+ktap use free syntax style, so you can choose to use the ';' or not.
+
+ktap use nil as NULL, the result of any number operate on nil is nil.
+
+ktap don't have array structure, also don't have any pointer operation.
+
+## Control structures
+
+ktap if/else is same as C language.
+
+There have two method of for-loop in ktap:
+
+ for (i = init, limit, step) { body }
+
+this is same as below in C:
+
+ for (i = init; i < limit; i += step) { body }
+
+The next for-loop method is:
+
+ for (k, v in pairs(t)) { body } # looping all elements of table
+
+Note that ktap don't have "continue" keyword, but C does.
+
+## Date structures
+
+Associative array is heavily used in ktap, it's also called by table.
+
+table declaration:
+
+ t = {}
+
+how to use table:
+
+ t[1] = 1
+ t[1] = "xxx"
+ t["key"] = 10
+ t["key"] = "value"
+
+ for (k, v in pairs(t)) { body } # looping all elements of table
+
+
+# Built in functions and librarys
+
+## Built in functions
+
+**print (...)**
+Receives any number of arguments, and prints their values,
+print is not intended for formatted output, but only as a
+quick way to show a value, typically for debugging.
+For formatted output, use printf.
+
+**printf (fmt, ...)**
+Similar with C printf, use for format string output.
+
+**pairs (t)**
+Returns three values: the next function, the table t, and nil,
+so that the construction
+for (k,v in pairs(t)) { body }
+will iterate over all key-value pairs of table t.
+
+**len (t) /len (s)**
+If the argument is string, return length of string,
+if the argument is table, return counts of table pairs.
+
+**in_interrupt ()**
+checking is context is interrupt context
+
+**exit ()**
+quit ktap executing, similar with exit syscall
+
+**pid ()**
+return current process pid
+
+**tid ()**
+return current thread id
+
+**uid ()**
+return current process uid
+
+**execname ()**
+return current process exec name string
+
+**cpu ()**
+return current cpu id
+
+**arch ()**
+return machine architecture, like x86, arm, etc.
+
+**kernel_v ()**
+return Linux kernel version string, like 3.9, etc.
+
+**user_string (addr)**
+Receive userspace address, read string from userspace, return string.
+
+**histogram (t)**
+Receive table, output table histogram to user.
+
+**curr_task_info (offset, fetch_bytes)**
+fetch value in field offset of task_struct structure, argument fetch_bytes
+could be 4 or 8, if fetch_bytes is not given, default is 4.
+
+user may need to get field offset by gdb, for example:
+gdb vmlinux
+(gdb)p &(((struct task_struct *)0).prio)
+
+**print_backtrace ()**
+print current task stack info
+
+
+## Librarys
+
+### Kdebug Library
+
+**kdebug.probe_by_id (eventdef_info, eventfun)**
+
+This function is underly representation of high level tracing primitive.
+Note that eventdef_info is just a userspace memory pointer refer to real
+eventdef_info structure, the structure defintion is:
+
+ struct ktap_eventdef_info {
+ int nr; /* the number to id */
+ int *id_arr; /* id array */
+ char *filter;
+ };
+
+Those id is read from /sys/kernel/debug/tracing/events/$SYS/$EVENT/id
+
+The second argument in above examples is a function:
+function eventfun () { action }
+
+
+**kdebug.probe_end (endfunc)**
+
+This function is used for invoking a function when tracing end, it will wait
+until user press CTRL+C to stop tracing, then ktap will call endfunc function,
+user could show tracing results in that function, or do other things.
+
+User don't have to use kdebug library directly, use trace/trace_end keyword.
+
+### Timer Library
+
+
+
+# Linux tracing basics
+
+tracepoints, probe, timer
+filters
+above explaintion
+Ring buffer
+
+# Tracing semantics in ktap
+
+## Tracing block
+
+**trace EVENTDEF /FILTER/ { ACTION }**
+
+This is the basic tracing block for ktap, you need to use a specific EVENTDEF
+string, and own event function.
+
+There have four type of EVENTDEF, tracepoint, kprobe, uprobe, sdt.
+
+- tracepoint:
+
+ EventDef Description
+ -------------------- -------------------------------
+ syscalls:* trace all syscalls events
+ syscalls:sys_enter_* trace all syscalls entry events
+ kmem:* trace all kmem related events
+ sched:* trace all sched related events
+ sched:sched_switch trace sched_switch tracepoint
+ \*:\* trace all tracepoints in system
+
+ All tracepoint events are based on:
+ /sys/kernel/debug/tracing/events/$SYS/$EVENT
+
+- ftrace(kernel newer than 3.3, and must compiled with CONFIG_FUNCTION_TRACER)
+
+ EventDef Description
+ -------------------- -------------------------------
+ ftrace:function trace kernel functions based on ftrace
+
+ User need to use filter (/ip==*/) to trace specfic functions.
+ Function must be listed in /sys/kernel/debug/tracing/available_filter_functions
+
+> ***Note*** of function event
+>
+> perf support ftrace:function tracepoint since Linux 3.3(see below commit),
+> ktap is based on perf callback, so it means kernel must be newer than 3.3
+> then can use this feature.
+>
+> commit ced39002f5ea736b716ae233fb68b26d59783912
+> Author: Jiri Olsa <jolsa@redhat.com>
+> Date: Wed Feb 15 15:51:52 2012 +0100
+>
+> ftrace, perf: Add support to use function tracepoint in perf
+>
+
+- kprobe:
+
+ EventDef Description
+ -------------------- -----------------------------------
+ probe:schedule trace schedule function
+ probe:schedule%return trace schedule function return
+ probe:SyS_write trace SyS_write function
+ probe:vfs* trace wildcards vfs related function
+
+ kprobe functions must be listed in /proc/kallsyms
+- uprobe:
+
+ EventDef Description
+ ------------------------------------ ---------------------------
+ probe:/lib64/libc.so.6:malloc trace malloc function
+ probe:/lib64/libc.so.6:malloc%return trace malloc function return
+ probe:/lib64/libc.so.6:free trace free function
+ probe:/lib64/libc.so.6:0x82000 trace function with file offset 0x82000
+ probe:/lib64/libc.so.6:* trace all libc function
+
+ symbol resolving need libelf support
+
+- sdt:
+
+ EventDef Description
+ ------------------------------------ --------------------------
+ sdt:/libc64/libc.so.6:lll_futex_wake trace stapsdt lll_futex_wake
+ sdt:/libc64/libc.so.6:* trace all static markers in libc
+
+ sdt resolving need libelf support
+
+
+**trace_end { ACTION }**
+
+## Tracing built-in variables
+
+**argevent**
+event object, you can print it by: print(argevent), it will print events
+into human readable string, the result is mostly same as each entry of
+/sys/kernel/debug/tracing/trace
+
+**argname**
+event name, each event have a name associated with it.
+
+**arg1..9**
+get argument 1..9 of event object.
+
+> ***Note*** of arg offset
+>
+> The arg offset(1..9) is determined by event format shown in debugfs.
+>
+> #cat /sys/kernel/debug/tracing/events/sched/sched_switch/format
+> name: sched_switch
+> ID: 268
+> format:
+> field:char prev_comm[32]; <- arg1
+> field:pid_t prev_pid; <- arg2
+> field:int prev_prio; <- arg3
+> field:long prev_state; <- arg4
+> field:char next_comm[32]; <- arg5
+> field:pid_t next_pid; <- arg6
+> field:int next_prio; <- arg7
+>
+> As shown, tracepoint event sched:sched_switch have 7 arguments, from arg1 to
+> arg7.
+>
+> Need to note that arg1 of syscall event is syscall number, not first argument
+> of syscall function. Use arg2 as first argument of syscall function.
+> For example:
+>
+> SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
+> <arg2> <arg3> <arg4>
+>
+> This is similar with kprobe and uprobe, the arg1 of kprobe/uprobe event
+> always is _probe_ip, not the first argument given by user, for example:
+>
+> # ktap -e 'trace probe:/lib64/libc.so.6:malloc size=%di'
+>
+> # cat /sys/kernel/debug/tracing/events/ktap_uprobes_3796/malloc/format
+> field:unsigned long __probe_ip; <- arg1
+> field:u64 size; <- arg2
+
+
+## Timer syntax
+
+**tick-Ns { ACTION }**
+**tick-Nsec { ACTION }**
+**tick-Nms { ACTION }**
+**tick-Nmsec { ACTION }**
+**tick-Nus { ACTION }**
+**tick-Nusec { ACTION }**
+
+**profile-Ns { ACTION }**
+**profile-Nsec { ACTION }**
+**profile-Nms { ACTION }**
+**profile-Nmsec { ACTION }**
+**profile-Nus { ACTION }**
+**profile-Nusec { ACTION }**
+
+architecture overview picture reference(pnp format)
+one-liners
+simple event tracing
+
+# Advanced tracing pattern
+
+Aggregation/Histogram
+thread local
+flame graph
+
+# Overhead/Performance
+
+ktap have more fast boot time thant Systemtap(try the helloword script)
+ktap have little memory usage than Systemtap
+and some scripts show that ktap have a little overhead than Systemtap
+(we choosed two scripts to compare, function profile, stack profile.
+this is not means all scripts in Systemtap have big overhead than ktap)
+
+
+# FAQ
+
+**Q: Why use bytecode design?**
+A: Using bytecode would be a clean and lightweight solution,
+ you don't need gcc toolchain to compile every scripts, all you
+ need is a ktapvm kernel modules and userspace tool called ktap.
+ Since its language virtual machine design, it have great portability,
+ suppose you are working at a multi-arch cluster, if you want to run
+ a tracing script on each board, you won't need cross-compile tracing
+ script onto all board, what you really need to do is use ktap tool
+ to run script just in time.
+
+ Bytecode based design also will make executing more safer, than native code
+ generation.
+
+ Reality already showing that SystemTap is not widely used in embedded Linux,
+ caused by problem of SystemTap's architecture design choice, it's a natural
+ design for Redhat and IBM, because Redhat/IBM is focusing on server area,
+ not embedded area.
+
+**Q: What's the differences with SystemTap and Dtrace?**
+A: For SystemTap, the answer is already mentioned at above question,
+ SystemTap use translator design, for trade-off on performance with usability,
+ based on GCC, that's what ktap want to solve.
+
+ For Dtrace, one common design with Dtrace is also use bytecode, so basically
+ Dtrace and ktap is on the same road. There have some projects aim to porting
+ Dtrace from Solaris to Linux, but the process is still on the road, Dtrace
+ is rooted in Solaris, and there have many huge differences between Solaris
+ tracing infrastructure with Linux's.
+
+ Dtrace is based on D language, a language subset of C, it's a restricted
+ language, like without for-looping, for safty use in production system.
+ It seems that Dtrace for Linux only support x86 architecture, not work on
+ powerpc and arm/mips, obviously it's not suit for embedded Linux currently.
+
+ Dtrace use ctf as input for debuginfo handing, compare with vmlinux for
+ SystemTap.
+
+ On the license part, Dtrace is released as CDDL, which is incompatible with
+ GPL(this is why it's impossible to upstream Dtrace into mainline).
+
+**Q: Why use dynamically typed language? but not statically typed language?**
+A: It's hard to say which one is more better than other, dynamically typed
+ language bring efficiency and fast prototype production, but loosing type
+ check at compiling phase, and easy to make mistake in runtime, also it's
+ need many runtime checking, In contrast, statically typed language win on
+ programing safety, and performance. Statically language would suit for
+ interoperate with kernel, as kernel is wrote mainly in C, Need to note that
+ SystemTap and Dtrace both is statically language.
+
+ ktap choose dynamically typed language as initial implementation.
+
+**Q: Why we need ktap for event tracing? There already have a built-in ftrace**
+A: This also is a common question for all dynamic tracing tool, not only ktap.
+ ktap provide more flexibility than built-in tracing infrastructure. Suppose
+ you need print a global variable when tracepoint hit, or you want print
+ backtrace, even more, you want to store some info into associative array, and
+ display it in histogram style when tracing end, in these case, some of them
+ ftrace can take it, some of them ftrace can not.
+ Overall, ktap provide you with great flexibility to scripting your own trace
+ need.
+
+**Q: How about the performance? Is ktap slow?**
+A: ktap is not slow, the bytecode is very high-level, based on lua, the language
+ virtual machine is register-based(compare with stack-based), with little
+ instruction, the table data structure is heavily optimized in ktapvm.
+ ktap use per-cpu allocation in many place, without global locking scheme,
+ it's very fast when executing tracepoint callback.
+ Performance benchmark showing that the overhead of ktap running is nearly
+ 10%(store event name into associative array), compare with full speed
+ running without any tracepoint enabled.
+
+ ktap will optimize overhead all the time, hopefully the overhead will
+ decrease to little than 5%, even more.
+
+**Q: Why not porting a high level language implementation into kernel directly?
+ Like python/JVM?**
+A: I take serious on the size of vm and memory footprint. Python vm is large,
+ it's not suit to embed into kernel, and python have some functionality
+ which we don't need.
+
+ The bytecode of other high level language is also big, ktap only have 32
+ bytecodes, python/java/erlang have nearly two hundred bytecodes.
+ There also have some problems when porting those language into kernel,
+ userspace programming have many differences with kernel programming,
+ like float numbers, handle sleeping code carefully in kernel, deadloop is
+ not allowed in kernel, multi-thread management, etc.., so it's impossible
+ to porting language implementation into kernel with little adaption work.
+
+**Q: What's the status of ktap now?**
+A: Basically it works on x86-32, x86-64, powerpc, arm, it also could work for
+ other hardware architecture, but not proven yet(I don't have enough hardware
+ to test)
+ If you found some bug, fix it on you own programming skill, or report to me.
+
+**Q: How to hack ktap? I want to write some extensions onto ktap.**
+A: welcome hacking.
+ You can write your own library to fulfill your specific need,
+ you can write any script as you want.
+
+**Q: What's the plan of ktap? any roadmap?**
+A: the current plan is deliver stable ktapvm kernel modules, more ktap script,
+ and bugfix.
+
+
+# References
+
+* [Linux Performance Analysis and Tools][LPAT]
+* [Dtrace Blog][dtraceblog]
+* [Dtrace User Guide][dug]
+* [LWN: ktap -- yet another kernel tracer][lwn1]
+* [LWN: Ktap almost gets into 3.13][lwn2]
+* [staging: ktap: add to the kernel tree][ktap_commit]
+* [ktap introduction in LinuxCon Japan 2013][lcj](content is out of date)
+* [ktap Examples by Brendan Gregg][KEBG]
+
+[LPAT]: http://www.brendangregg.com/Slides/SCaLE_Linux_Performance2013.pdf
+[dtraceblog]: http://dtrace.org/blogs/
+[dug]: http://docs.huihoo.com/opensolaris/dtrace-user-guide/html/index.html
+[lwn1]: http://lwn.net/Articles/551314/
+[lwn2]: http://lwn.net/Articles/572788/
+[ktap_commit]: https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=c63a164271f81220ff4966d41218a9101f3d0ec4
+[lcj]: http://events.linuxfoundation.org/sites/events/files/lcjpcojp13_zhangwei.pdf
+[KEBG]: http://www.brendangregg.com/ktap.html
+
+# History
+
+* ktap was invented at 2002
+* First RFC sent to LKML at 2012.12.31
+* The code was released in github at 2013.01.18
+* ktap released v0.1 at 2013.05.21
+* ktap released v0.2 at 2013.07.31
+* ktap released v0.3 at 2013.10.29
+
+For more release info, please look at RELEASES.txt in project root directory.
+
+# Examples
+
+1. simplest one-liner command to enable all tracepoints
+
+ ktap -e "trace *:* { print(argevent) }"
+
+2. syscall tracing on target process
+
+ ktap -e "trace syscalls:* { print(argevent) }" -- ls
+
+3. ftrace(kernel newer than 3.3, and must compiled with CONFIG_FUNCTION_TRACER)
+
+ ktap -e "trace ftrace:function { print(argevent) }"
+
+ ktap -e "trace ftrace:function /ip==mutex*/ { print(argevent) }"
+
+4. simple syscall tracing
+
+ trace syscalls:* {
+ print(cpu(), pid(), execname(), argevent)
+ }
+
+5. syscall tracing in histogram style
+
+ s = {}
+
+ trace syscalls:sys_enter_* {
+ s[argname] += 1
+ }
+
+ trace_end {
+ histogram(s)
+ }
+
+6. kprobe tracing
+
+ trace probe:do_sys_open dfd=%di fname=%dx flags=%cx mode=+4($stack) {
+ print("entry:", execname(), argevent)
+ }
+
+ trace probe:do_sys_open%return fd=$retval {
+ print("exit:", execname(), argevent)
+ }
+
+7. uprobe tracing
+
+ trace probe:/lib/libc.so.6:malloc {
+ print("entry:", execname(), argevent)
+ }
+
+ trace probe:/lib/libc.so.6:malloc%return {
+ print("exit:", execname(), argevent)
+ }
+
+8. stapsdt tracing (userspace static marker)
+
+ trace sdt:/lib64/libc.so.6:lll_futex_wake {
+ print("lll_futex_wake", execname(), argevent)
+ }
+
+ or:
+
+ #trace all static mark in libc
+ trace sdt:/lib64/libc.so.6:* {
+ print(execname(), argevent)
+ }
+
+9. timer
+
+ tick-1ms {
+ printf("time fired on one cpu\n");
+ }
+
+ profile-2s {
+ printf("time fired on every cpu\n");
+ }
+
+10. FFI (Call kernel function from ktap script, need compile with FFI=1)
+
+ cdef[[
+ int printk(char *fmt, ...);
+ ]]
+
+ C.printk("This message is called from ktap ffi\n")
+
+More examples can be found at [samples][samples_dir] directory.
+
+[samples_dir]: https://github.com/ktap/ktap/tree/master/samples
+
+# Appendix
+
+Here is the complete syntax of ktap in extended BNF.
+(based on lua syntax: http://www.lua.org/manual/5.1/manual.html#5.1)
+
+ chunk ::= {stat [';']} [laststat [';']
+
+ block ::= chunk
+
+ stat ::= varlist '=' explist |
+ functioncall |
+ { block } |
+ while exp { block } |
+ repeat block until exp |
+ if exp { block {elseif exp { block }} [else block] } |
+ for Name '=' exp ',' exp [',' exp] { block } |
+ for namelist in explist { block } |
+ function funcname funcbody |
+ local function Name funcbody |
+ local namelist ['=' explist]
+
+ laststat ::= return [explist] | break
+
+ funcname ::= Name {'.' Name} [':' Name]
+
+ varlist ::= var {',' var}
+
+ var ::= Name | prefixexp '[' exp ']'| prefixexp '.' Name
+
+ namelist ::= Name {',' Name}
+
+ explist ::= {exp ',' exp
+
+ exp ::= nil | false | true | Number | String | '...' | function |
+ prefixexp | tableconstructor | exp binop exp | unop exp
+
+ prefixexp ::= var | functioncall | '(' exp ')'
+
+ functioncall ::= prefixexp args | prefixexp ':' Name args
+
+ args ::= '(' [explist] ')' | tableconstructor | String
+
+ function ::= function funcbody
+
+ funcbody ::= '(' [parlist] ')' { block }
+
+ parlist ::= namelist [',' '...'] | '...'
+
+ tableconstructor ::= '{' [fieldlist] '}'
+
+ fieldlist ::= field {fieldsep field} [fieldsep]
+
+ field ::= '[' exp ']' '=' exp | Name '=' exp | exp
+
+ fieldsep ::= ',' | ';'
+
+ binop ::= '+' | '-' | '*' | '/' | '^' | '%' | '..' |
+ '<' | '<=' | '>' | '>=' | '==' | '!=' |
+ and | or
+
+ unop ::= '-'
+
--- /dev/null
+++ b/drivers/staging/ktap/include/ktap_ffi.h
@@ -0,0 +1,180 @@
+#ifndef __KTAP_FFI_H__
+#define __KTAP_FFI_H__
+
+#ifdef CONFIG_KTAP_FFI
+
+#include "../include/ktap_types.h"
+
+/*
+ * Types design in FFI module
+ *
+ * ktap_cdata is an instance of csymbol, so it's a combination of csymbol
+ * and it's actual data in memory.
+ *
+ * csymbol structs are globally unique and readonly type that represent C
+ * types. For non scalar C types like struct and function, helper structs are
+ * used to store detailed information. See csymbol_func and csymbol_struct for
+ * more information.
+ */
+
+typedef enum {
+ /* 0 - 4 */
+ FFI_VOID,
+ FFI_UINT8,
+ FFI_INT8,
+ FFI_UINT16,
+ FFI_INT16,
+ /* 5 - 9 */
+ FFI_UINT32,
+ FFI_INT32,
+ FFI_UINT64,
+ FFI_INT64,
+ FFI_PTR,
+ /* 10 - 12 */
+ FFI_FUNC,
+ FFI_STRUCT,
+ FFI_UNKNOWN,
+} ffi_type;
+#define NUM_FFI_TYPE ((int)FFI_UNKNOWN)
+
+
+/* following struct and macros are added for C typedef
+ * size and alignment calculation */
+typedef struct {
+ size_t size;
+ size_t align;
+ const char *name;
+} ffi_mode;
+extern const ffi_mode const ffi_type_modes[];
+
+#define ffi_type_size(t) (ffi_type_modes[t].size)
+#define ffi_type_align(t) (ffi_type_modes[t].align)
+#define ffi_type_name(t) (ffi_type_modes[t].name)
+
+
+/* start of csymbol definition */
+#define CSYM_NAME_MAX_LEN 64
+
+typedef struct csymbol_func {
+ void *addr; /* function address */
+ csymbol_id ret_id; /* function return type */
+ int arg_nr; /* number of arguments */
+ csymbol_id *arg_ids; /* function argument types */
+ unsigned has_var_arg; /* is this a var arg function? */
+} csymbol_func;
+
+typedef struct struct_member {
+ char name[CSYM_NAME_MAX_LEN]; /* name for this struct member */
+ csymbol_id id; /* type for this struct member */
+} struct_member;
+
+typedef struct csymbol_struct {
+ int memb_nr; /* number of members */
+ struct_member *members; /* array for each member definition */
+ size_t size; /* bytes used to store struct */
+ /* alignment of the struct, 0 indicates uninitialization */
+ size_t align;
+} csymbol_struct;
+
+
+/* wrapper struct for all C symbols */
+typedef struct csymbol {
+ char name[CSYM_NAME_MAX_LEN]; /* name for this symbol */
+ ffi_type type; /* type for this symbol */
+ /* following members are used only for non scalar C types */
+ union {
+ csymbol_id p; /* pointer type */
+ csymbol_func f; /* C function type */
+ csymbol_struct st; /* struct type */
+ csymbol_id td; /* typedef type */
+ } u;
+} csymbol;
+
+/* lookup csymbol address by it's id */
+inline csymbol *ffi_get_csym_by_id(ktap_state *ks, csymbol_id id);
+#define id_to_csym(ks, id) (ffi_get_csym_by_id(ks, id))
+
+/* helper macros for struct csymbol */
+#define csym_type(cs) ((cs)->type)
+#define csym_name(cs) ((cs)->name)
+
+/*
+ * helper macros for pointer symbol
+ */
+#define csym_ptr_deref_id(cs) ((cs)->u.p)
+#define csym_set_ptr_deref_id(cs, id) ((cs)->u.p = (id))
+/* following macro gets csymbol address */
+#define csym_ptr_deref(ks, cs) (id_to_csym(ks, csym_ptr_deref_id(cs)))
+
+/*
+ * helper macros for function symbol
+ * csym_* accepts csymbol type
+ * csymf_* accepts csymbol_func type
+ */
+#define csymf_addr(csf) ((csf)->addr)
+#define csymf_ret_id(csf) ((csf)->ret_id)
+#define csymf_arg_nr(csf) ((csf)->arg_nr)
+#define csymf_arg_ids(csf) ((csf)->arg_ids)
+/* get csymbol id for the nth argument */
+#define csymf_arg_id(csf, n) ((csf)->arg_ids[n])
+#define csym_func(cs) (&((cs)->u.f))
+#define csym_func_addr(cs) (csymf_addr(csym_func(cs)))
+#define csym_func_arg_ids(cs) (csymf_arg_ids(csym_func(cs)))
+/* following macros get csymbol address */
+#define csymf_ret(ks, csf) (id_to_csym(ks, csymf_ret_id(csf)))
+/* get csymbol address for the nth argument */
+#define csymf_arg(ks, csf, n) (id_to_csym(ks, csymf_arg_id(csf, n)))
+#define csym_func_arg(ks, cs, n) (csymf_arg(ks, csym_func(cs), n))
+
+/*
+ * helper macors for struct symbol
+ * csym_* accepts csymbol type
+ * csymst_* accepts csymbol_struct type
+ */
+#define csymst_mb_nr(csst) ((csst)->memb_nr)
+#define csym_struct(cs) (&(cs)->u.st)
+#define csym_struct_mb(cs) (csymst_mb(ks, csym_struct(cs), n))
+/* following macro gets csymbol address for the nth struct member */
+#define csymst_mb(ks, csst, n) (id_to_csym(ks, (csst)->members[n].id))
+
+
+/*
+ * helper macros for ktap_cdata type
+ */
+#define cd_csym_id(cd) ((cd)->id)
+#define cd_set_csym_id(cd, id) (cd_csym_id(cd) = (id))
+#define cd_csym(ks, cd) (id_to_csym(ks, cd_csym_id(cd)))
+#define cd_type(ks, cd) (cd_csym(ks, cd)->type)
+
+#define cd_int(cd) ((cd)->u.i)
+#define cd_ptr(cd) ((cd)->u.p)
+#define cd_struct(cd) ((cd)->u.st)
+
+
+#ifdef __KERNEL__
+size_t csym_size(ktap_state *ks, csymbol *sym);
+size_t csym_align(ktap_state *ks, csymbol *sym);
+size_t csym_struct_offset(ktap_state *ks, csymbol_struct *csst, int idx);
+void init_csym_struct(ktap_state *ks, csymbol_struct *csst);
+
+void kp_ffi_free_symbol(ktap_state *ks);
+csymbol_id ffi_get_csym_id(ktap_state *ks, char *name);
+
+ktap_cdata *kp_cdata_new(ktap_state *ks);
+void kp_cdata_dump(ktap_state *ks, ktap_cdata *cd);
+ktap_cdata *kp_cdata_new_ptr(ktap_state *ks, void *addr, csymbol_id id);
+ktap_cdata *kp_cdata_new_struct(ktap_state *ks, void *val, csymbol_id id);
+
+int kp_ffi_call(ktap_state *ks, csymbol_func *cf);
+#endif /* for __KERNEL__ */
+
+#else
+
+static void __maybe_unused kp_ffi_free_symbol(ktap_state *ks)
+{
+ return;
+}
+
+#endif /* CONFIG_KTAP_FFI */
+
+#endif /* __KTAP_FFI_H__ */
--- /dev/null
+++ b/drivers/staging/ktap/include/ktap_opcodes.h
@@ -0,0 +1,239 @@
+#ifndef __KTAP_BYTECODE_H__
+#define __KTAP_BYTECODE_H__
+
+
+/* opcode is copied from lua initially */
+
+typedef enum {
+/*----------------------------------------------------------------------
+ * name args description
+ * ------------------------------------------------------------------------*/
+OP_MOVE,/* A B R(A) := R(B) */
+OP_LOADK,/* A Bx R(A) := Kst(Bx) */
+OP_LOADKX,/* A R(A) := Kst(extra arg) */
+OP_LOADBOOL,/* A B C R(A) := (Bool)B; if (C) pc++ */
+OP_LOADNIL,/* A B R(A), R(A+1), ..., R(A+B) := nil */
+OP_GETUPVAL,/* A B R(A) := UpValue[B] */
+
+OP_GETTABUP,/* A B C R(A) := UpValue[B][RK(C)] */
+OP_GETTABLE,/* A B C R(A) := R(B)[RK(C)] */
+
+OP_SETTABUP,/* A B C UpValue[A][RK(B)] := RK(C) */
+OP_SETTABUP_INCR,/* A B C UpValue[A][RK(B)] += RK(C) */
+OP_SETTABUP_AGGR,/* A B C UpValue[A][RK(B)] <<< RK(C) */
+OP_SETUPVAL,/* A B UpValue[B] := R(A) */
+OP_SETTABLE,/* A B C R(A)[RK(B)] := RK(C) */
+OP_SETTABLE_INCR,/* A B C R(A)[RK(B)] += RK(C) */
+OP_SETTABLE_AGGR,/* A B C R(A)[RK(B)] <<< RK(C) */
+
+OP_NEWTABLE,/* A B C R(A) := {} (size = B,C) */
+
+OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */
+
+OP_ADD,/* A B C R(A) := RK(B) + RK(C) */
+OP_SUB,/* A B C R(A) := RK(B) - RK(C) */
+OP_MUL,/* A B C R(A) := RK(B) * RK(C) */
+OP_DIV,/* A B C R(A) := RK(B) / RK(C) */
+OP_MOD,/* A B C R(A) := RK(B) % RK(C) */
+OP_POW,/* A B C R(A) := RK(B) ^ RK(C) */
+OP_UNM,/* A B R(A) := -R(B) */
+OP_NOT,/* A B R(A) := not R(B) */
+OP_LEN,/* A B R(A) := length of R(B) */
+
+OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */
+
+OP_JMP,/* A sBx pc+=sBx; if (A) close all upvalues >= R(A) + 1 */
+OP_EQ,/* A B C if ((RK(B) == RK(C)) != A) then pc++ */
+OP_LT,/* A B C if ((RK(B) < RK(C)) != A) then pc++ */
+OP_LE,/* A B C if ((RK(B) <= RK(C)) != A) then pc++ */
+
+OP_TEST,/* A C if not (R(A) <=> C) then pc++ */
+OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */
+
+OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
+OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
+OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */
+
+OP_FORLOOP,/* A sBx R(A)+=R(A+2);
+ if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/
+OP_FORPREP,/* A sBx R(A)-=R(A+2); pc+=sBx */
+
+OP_TFORCALL,/* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); */
+OP_TFORLOOP,/* A sBx if R(A+1) != nil then { R(A)=R(A+1); pc += sBx }*/
+
+OP_SETLIST,/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */
+
+OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx]) */
+
+OP_VARARG,/* A B R(A), R(A+1), ..., R(A+B-2) = vararg */
+
+OP_EXTRAARG,/* Ax extra (larger) argument for previous opcode */
+
+OP_EVENT,/* A B C R(A) := R(B)[C] */
+
+OP_EVENTNAME, /* A R(A) = event_name() */
+
+OP_EVENTARG,/* A B R(A) := event_arg(B)*/
+
+OP_LOAD_GLOBAL,/* A B C R(A) := R(B)[C] */
+
+OP_EXIT,
+
+} OpCode;
+
+
+#define NUM_OPCODES ((int)OP_LOAD_GLOBAL + 1)
+
+
+enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */
+
+
+/*
+ * ** size and position of opcode arguments.
+ * */
+#define SIZE_C 9
+#define SIZE_B 9
+#define SIZE_Bx (SIZE_C + SIZE_B)
+#define SIZE_A 8
+#define SIZE_Ax (SIZE_C + SIZE_B + SIZE_A)
+
+#define SIZE_OP 6
+
+#define POS_OP 0
+#define POS_A (POS_OP + SIZE_OP)
+#define POS_C (POS_A + SIZE_A)
+#define POS_B (POS_C + SIZE_C)
+#define POS_Bx POS_C
+#define POS_Ax POS_A
+
+
+
+/*
+ * ** limits for opcode arguments.
+ * ** we use (signed) int to manipulate most arguments,
+ * ** so they must fit in LUAI_BITSINT-1 bits (-1 for sign)
+ * */
+#define MAXARG_Bx ((1<<SIZE_Bx)-1)
+#define MAXARG_sBx (MAXARG_Bx>>1) /* `sBx' is signed */
+
+#define MAXARG_Ax ((1<<SIZE_Ax)-1)
+
+#define MAXARG_A ((1<<SIZE_A)-1)
+#define MAXARG_B ((1<<SIZE_B)-1)
+#define MAXARG_C ((1<<SIZE_C)-1)
+
+
+/* creates a mask with `n' 1 bits at position `p' */
+#define MASK1(n,p) ((~((~(ktap_instruction)0)<<(n)))<<(p))
+
+/* creates a mask with `n' 0 bits at position `p' */
+#define MASK0(n,p) (~MASK1(n,p))
+
+/*
+ * ** the following macros help to manipulate instructions
+ * */
+
+#define GET_OPCODE(i) ((OpCode)((i)>>POS_OP) & MASK1(SIZE_OP,0))
+#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \
+ ((((ktap_instruction)o)<<POS_OP)&MASK1(SIZE_OP,POS_OP))))
+
+#define getarg(i,pos,size) ((int)((i)>>pos) & MASK1(size,0))
+#define setarg(i,v,pos,size) ((i) = (((i)&MASK0(size,pos)) | \
+ ((((ktap_instruction)v)<<pos)&MASK1(size,pos))))
+
+#define GETARG_A(i) getarg(i, POS_A, SIZE_A)
+#define SETARG_A(i,v) setarg(i, v, POS_A, SIZE_A)
+
+#define GETARG_B(i) getarg(i, POS_B, SIZE_B)
+#define SETARG_B(i,v) setarg(i, v, POS_B, SIZE_B)
+
+#define GETARG_C(i) getarg(i, POS_C, SIZE_C)
+#define SETARG_C(i,v) setarg(i, v, POS_C, SIZE_C)
+
+#define GETARG_Bx(i) getarg(i, POS_Bx, SIZE_Bx)
+#define SETARG_Bx(i,v) setarg(i, v, POS_Bx, SIZE_Bx)
+
+#define GETARG_Ax(i) getarg(i, POS_Ax, SIZE_Ax)
+#define SETARG_Ax(i,v) setarg(i, v, POS_Ax, SIZE_Ax)
+
+#define GETARG_sBx(i) (GETARG_Bx(i)-MAXARG_sBx)
+#define SETARG_sBx(i,b) SETARG_Bx((i), (unsigned int)(b)+MAXARG_sBx)
+
+#define CREATE_ABC(o,a,b,c) (((ktap_instruction)(o))<<POS_OP) \
+ | (((ktap_instruction)(a))<<POS_A) \
+ | (((ktap_instruction)(b))<<POS_B) \
+ | (((ktap_instruction)(c))<<POS_C)
+
+#define CREATE_ABx(o,a,bc) (((ktap_instruction)(o))<<POS_OP) \
+ | (((ktap_instruction)(a))<<POS_A) \
+ | (((ktap_instruction)(bc))<<POS_Bx)
+
+#define CREATE_Ax(o,a) (((ktap_instruction)(o))<<POS_OP) \
+ | (((ktap_instruction)(a))<<POS_Ax)
+
+
+
+/*
+ * ** Macros to operate RK indices
+ * */
+
+/* this bit 1 means constant (0 means register) */
+#define BITRK (1 << (SIZE_B - 1))
+
+/* test whether value is a constant */
+#define ISK(x) ((x) & BITRK)
+
+/* gets the index of the constant */
+#define INDEXK(r) ((int)(r) & ~BITRK)
+
+#define MAXINDEXRK (BITRK - 1)
+
+/* code a constant index as a RK value */
+#define RKASK(x) ((x) | BITRK)
+
+
+/*
+ * ** invalid register that fits in 8 bits
+ * */
+#define NO_REG MAXARG_A
+
+
+/*
+ * ** R(x) - register
+ * ** Kst(x) - constant (in constant table)
+ * ** RK(x) == if ISK(x) then Kst(INDEXK(x)) else R(x)
+ * */
+
+
+
+/*
+ * ** masks for instruction properties. The format is:
+ * ** bits 0-1: op mode
+ * ** bits 2-3: C arg mode
+ * ** bits 4-5: B arg mode
+ * ** bit 6: instruction set register A
+ * ** bit 7: operator is a test (next instruction must be a jump)
+ * */
+
+enum OpArgMask {
+ OpArgN, /* argument is not used */
+ OpArgU, /* argument is used */
+ OpArgR, /* argument is a register or a jump offset */
+ OpArgK /* argument is a constant or register/constant */
+};
+
+extern const u8 ktap_opmodes[NUM_OPCODES];
+
+#define getOpMode(m) ((enum OpMode)ktap_opmodes[m] & 3)
+#define getBMode(m) ((enum OpArgMask)(ktap_opmodes[m] >> 4) & 3)
+#define getCMode(m) ((enum OpArgMask)(ktap_opmodes[m] >> 2) & 3)
+#define testAMode(m) (ktap_opmodes[m] & (1 << 6))
+#define testTMode(m) (ktap_opmodes[m] & (1 << 7))
+
+
+/* number of list items to accumulate before a SETLIST instruction */
+#define LFIELDS_PER_FLUSH 50
+
+extern const char *const ktap_opnames[NUM_OPCODES + 1];
+
+#endif /* __KTAP_BYTECODE_H__ */
--- /dev/null
+++ b/drivers/staging/ktap/include/ktap_types.h
@@ -0,0 +1,609 @@
+#ifndef __KTAP_TYPES_H__
+#define __KTAP_TYPES_H__
+
+#ifdef __KERNEL__
+#include <linux/perf_event.h>
+#else
+typedef char u8;
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#endif
+
+/*
+ * The first argument type of kdebug.probe_by_id()
+ * The value is a userspace memory pointer.
+ */
+typedef struct ktap_eventdef_info {
+ int nr;
+ int *id_arr;
+ char *filter;
+} ktap_eventdef_info;
+
+typedef struct ktap_parm {
+ char *trunk; /* __user */
+ int trunk_len;
+ int argc;
+ char **argv; /* __user */
+ int verbose;
+ int trace_pid;
+ int workload;
+ int trace_cpu;
+ int print_timestamp;
+ int quiet;
+} ktap_parm;
+
+/*
+ * Ioctls that can be done on a ktap fd:
+ * todo: use _IO macro in include/uapi/asm-generic/ioctl.h
+ */
+#define KTAP_CMD_IOC_VERSION ('$' + 0)
+#define KTAP_CMD_IOC_RUN ('$' + 1)
+#define KTAP_CMD_IOC_EXIT ('$' + 3)
+
+#define KTAP_ENV "_ENV"
+
+#define KTAP_VERSION_MAJOR "0"
+#define KTAP_VERSION_MINOR "4"
+
+#define KTAP_VERSION "ktap " KTAP_VERSION_MAJOR "." KTAP_VERSION_MINOR
+#define KTAP_AUTHOR "Jovi Zhangwei <jovi.zhangwei@gmail.com>"
+#define KTAP_COPYRIGHT KTAP_VERSION " Copyright (C) 2012-2013, " KTAP_AUTHOR
+
+#define MYINT(s) (s[0] - '0')
+#define VERSION (MYINT(KTAP_VERSION_MAJOR) * 16 + MYINT(KTAP_VERSION_MINOR))
+#define FORMAT 0 /* this is the official format */
+
+#define KTAP_SIGNATURE "\033ktap"
+
+/* data to catch conversion errors */
+#define KTAPC_TAIL "\x19\x93\r\n\x1a\n"
+
+/* size in bytes of header of binary files */
+#define KTAPC_HEADERSIZE (sizeof(KTAP_SIGNATURE) - sizeof(char) + 2 + \
+ 6 + sizeof(KTAPC_TAIL) - sizeof(char))
+
+typedef long ktap_number;
+#define kp_number2int(i, n) ((i) = (int)(n))
+
+typedef int ktap_instruction;
+
+typedef union ktap_gcobject ktap_gcobject;
+
+#define CommonHeader ktap_gcobject *next; u8 tt;
+
+typedef union ktap_string {
+ int dummy; /* ensures maximum alignment for strings */
+ struct {
+ CommonHeader;
+ u8 extra; /* reserved words for short strings; "has hash" for longs */
+ unsigned int hash;
+ size_t len; /* number of characters in string */
+ } tsv;
+ /* short string is stored here, just after tsv */
+} ktap_string;
+
+
+struct ktap_state;
+typedef int (*ktap_cfunction) (struct ktap_state *ks);
+
+typedef struct ktap_value {
+ union {
+ ktap_gcobject *gc; /* collectable objects */
+ void *p; /* light userdata */
+ int b; /* booleans */
+ ktap_cfunction f; /* light C functions */
+ ktap_number n; /* numbers */
+ } val;
+ int type;
+} ktap_value;
+
+typedef ktap_value * StkId;
+
+
+/*
+ * Description of an upvalue for function prototypes
+ */
+typedef struct ktap_upvaldesc {
+ ktap_string *name; /* upvalue name (for debug information) */
+ u8 instack; /* whether it is in stack */
+ u8 idx; /* index of upvalue (in stack or in outer function's list) */
+} ktap_upvaldesc;
+
+/*
+ * Description of a local variable for function prototypes
+ * (used for debug information)
+ */
+typedef struct ktap_locvar {
+ ktap_string *varname;
+ int startpc; /* first point where variable is active */
+ int endpc; /* first point where variable is dead */
+} ktap_locvar;
+
+
+typedef struct ktap_upval {
+ CommonHeader;
+ ktap_value *v; /* points to stack or to its own value */
+ union {
+ ktap_value value; /* the value (when closed) */
+ struct { /* double linked list (when open) */
+ struct ktap_upval *prev;
+ struct ktap_upval *next;
+ } l;
+ } u;
+} ktap_upval;
+
+
+#define KTAP_MAX_STACK_ENTRIES 100
+
+typedef struct ktap_btrace {
+ CommonHeader;
+ unsigned int nr_entries;
+ /* entries stored in here, after nr_entries */
+} ktap_btrace;
+
+typedef struct ktap_closure {
+ CommonHeader;
+ u8 nupvalues;
+ struct ktap_proto *p;
+ struct ktap_upval *upvals[1]; /* list of upvalues */
+ ktap_gcobject *gclist;
+} ktap_closure;
+
+typedef struct ktap_proto {
+ CommonHeader;
+ ktap_value *k; /* constants used by the function */
+ ktap_instruction *code;
+ struct ktap_proto **p; /* functions defined inside the function */
+ int *lineinfo; /* map from opcodes to source lines (debug information) */
+ struct ktap_locvar *locvars; /* information about local variables (debug information) */
+ struct ktap_upvaldesc *upvalues; /* upvalue information */
+ ktap_closure *cache; /* last created closure with this prototype */
+ ktap_string *source; /* used for debug information */
+ int sizeupvalues; /* size of 'upvalues' */
+ int sizek; /* size of `k' */
+ int sizecode;
+ int sizelineinfo;
+ int sizep; /* size of `p' */
+ int sizelocvars;
+ int linedefined;
+ int lastlinedefined;
+ u8 numparams; /* number of fixed parameters */
+ u8 is_vararg;
+ u8 maxstacksize; /* maximum stack used by this function */
+} ktap_proto;
+
+
+/*
+ * information about a call
+ */
+typedef struct ktap_callinfo {
+ StkId func; /* function index in the stack */
+ StkId top; /* top for this function */
+ struct ktap_callinfo *prev, *next; /* dynamic call link */
+ short nresults; /* expected number of results from this function */
+ u8 callstatus;
+ int extra;
+ union {
+ struct { /* only for ktap functions */
+ StkId base; /* base for this function */
+ const unsigned int *savedpc;
+ } l;
+ struct { /* only for C functions */
+ int ctx; /* context info. in case of yields */
+ u8 status;
+ } c;
+ } u;
+} ktap_callinfo;
+
+
+/*
+ * ktap_tab
+ */
+typedef struct ktap_tkey {
+ struct ktap_tnode *next; /* for chaining */
+ ktap_value tvk;
+} ktap_tkey;
+
+
+typedef struct ktap_tnode {
+ ktap_value i_val;
+ ktap_tkey i_key;
+} ktap_tnode;
+
+
+typedef struct ktap_stat_data {
+ int count;
+ int sum;
+ int min, max;
+} ktap_stat_data;
+
+
+typedef struct ktap_tab {
+ CommonHeader;
+#ifdef __KERNEL__
+ arch_spinlock_t lock;
+#endif
+ u8 flags; /* 1<<p means tagmethod(p) is not present */
+ u8 lsizenode; /* log2 of size of `node' array */
+ int sizearray; /* size of `array' array */
+ ktap_value *array; /* array part */
+ ktap_tnode *node;
+ ktap_tnode *lastfree; /* any free position is before this position */
+
+ int with_stats; /* for aggregation table: ptable */
+ ktap_stat_data *sd_arr;
+ ktap_stat_data *sd_rec;
+
+ ktap_tnode *sorted; /* sorted table, with linked node list */
+ ktap_tnode *sort_head;
+
+ ktap_gcobject *gclist;
+} ktap_tab;
+
+#define lmod(s,size) ((int)((s) & ((size)-1)))
+
+/* parallel table */
+typedef struct ktap_ptab {
+ CommonHeader;
+ ktap_tab **tbl; /* percpu table */
+ ktap_tab *agg;
+} ktap_ptab;
+
+typedef struct ktap_stringtable {
+ ktap_gcobject **hash;
+ int nuse;
+ int size;
+} ktap_stringtable;
+
+#ifdef CONFIG_KTAP_FFI
+typedef int csymbol_id;
+typedef struct csymbol csymbol;
+
+/* global ffi state maintained in each ktap vm instance */
+typedef struct ffi_state {
+ ktap_tab *ctable;
+ int csym_nr;
+ csymbol *csym_arr;
+} ffi_state;
+
+/* instance of csymbol */
+typedef struct ktap_cdata {
+ CommonHeader;
+ csymbol_id id;
+ union {
+ uint64_t i;
+ void *p; /* pointer address */
+ void *st; /* struct member data */
+ } u;
+} ktap_cdata;
+#endif
+
+typedef struct ktap_stats {
+ int mem_allocated;
+ int nr_mem_allocate;
+ int nr_mem_free;
+ int events_hits;
+ int events_missed;
+} ktap_stats;
+
+#define KTAP_STATS(ks) this_cpu_ptr(G(ks)->stats)
+
+enum {
+ KTAP_PERCPU_DATA_STATE,
+ KTAP_PERCPU_DATA_STACK,
+ KTAP_PERCPU_DATA_BUFFER,
+ KTAP_PERCPU_DATA_BUFFER2,
+ KTAP_PERCPU_DATA_BTRACE,
+
+ KTAP_PERCPU_DATA_MAX
+};
+
+typedef struct ktap_global_state {
+ ktap_stringtable strt; /* hash table for strings */
+ ktap_value registry;
+ unsigned int seed; /* randonized seed for hashes */
+
+ ktap_gcobject *allgc; /* list of all collectable objects */
+
+ ktap_upval uvhead; /* head of double-linked list of all open upvalues */
+
+ struct ktap_state *mainthread;
+#ifdef __KERNEL__
+ /* global percpu data(like stack) */
+ void __percpu *pcpu_data[KTAP_PERCPU_DATA_MAX][PERF_NR_CONTEXTS];
+
+ int __percpu *recursion_context[PERF_NR_CONTEXTS];
+
+ arch_spinlock_t str_lock; /* string opertion lock */
+
+ ktap_parm *parm;
+ pid_t trace_pid;
+ struct task_struct *trace_task;
+ cpumask_var_t cpumask;
+ struct ring_buffer *buffer;
+ struct dentry *trace_pipe_dentry;
+ int nr_builtin_cfunction;
+ ktap_value *cfunction_tbl;
+ struct task_struct *task;
+ int trace_enabled;
+ struct list_head timers;
+ struct list_head probe_events_head;
+ int exit;
+ int wait_user;
+ ktap_closure *trace_end_closure;
+ struct ktap_stats __percpu *stats;
+ struct kmem_cache *pevent_cache;
+#ifdef CONFIG_KTAP_FFI
+ ffi_state ffis;
+#endif
+#endif
+ int error;
+} ktap_global_state;
+
+typedef struct ktap_state {
+ CommonHeader;
+ ktap_global_state *g;
+ int stop;
+ StkId top;
+ ktap_callinfo *ci;
+ const unsigned long *oldpc;
+ StkId stack_last;
+ StkId stack;
+ ktap_gcobject *openupval;
+ ktap_callinfo baseci;
+
+ /* list of temp collectable objects, free when thread exit */
+ ktap_gcobject *gclist;
+
+#ifdef __KERNEL__
+ struct ktap_event *current_event;
+#endif
+} ktap_state;
+
+
+typedef struct gcheader {
+ CommonHeader;
+} gcheader;
+
+/*
+ * Union of all collectable objects
+ */
+union ktap_gcobject {
+ gcheader gch; /* common header */
+ union ktap_string ts;
+ struct ktap_closure cl;
+ struct ktap_tab h;
+ struct ktap_ptab ph;
+ struct ktap_proto p;
+ struct ktap_upval uv;
+ struct ktap_state th; /* thread */
+ struct ktap_btrace bt; /* backtrace object */
+#ifdef CONFIG_KTAP_FFI
+ struct ktap_cdata cd;
+#endif
+};
+
+#define gch(o) (&(o)->gch)
+
+/* macros to convert a GCObject into a specific value */
+#define rawgco2ts(o) (&((o)->ts))
+
+#define gco2ts(o) (&rawgco2ts(o)->tsv)
+#define gco2uv(o) (&((o)->uv))
+#define obj2gco(v) ((ktap_gcobject *)(v))
+#define check_exp(c, e) (e)
+
+
+/* predefined values in the registry */
+#define KTAP_RIDX_MAINTHREAD 1
+#define KTAP_RIDX_GLOBALS 2
+#define KTAP_RIDX_LAST KTAP_RIDX_GLOBALS
+
+#define KTAP_TNONE (-1)
+
+#define KTAP_TNIL 0
+#define KTAP_TBOOLEAN 1
+#define KTAP_TLIGHTUSERDATA 2
+#define KTAP_TNUMBER 3
+#define KTAP_TSTRING 4
+#define KTAP_TSHRSTR (KTAP_TSTRING | (0 << 4)) /* short strings */
+#define KTAP_TLNGSTR (KTAP_TSTRING | (1 << 4)) /* long strings */
+#define KTAP_TTABLE 5
+#define KTAP_TFUNCTION 6
+#define KTAP_TCLOSURE (KTAP_TFUNCTION | (0 << 4)) /* closure */
+#define KTAP_TCFUNCTION (KTAP_TFUNCTION | (1 << 4)) /* light C function */
+#define KTAP_TTHREAD 7
+#define KTAP_TPROTO 8
+#define KTAP_TUPVAL 9
+#define KTAP_TEVENT 10
+#define KTAP_TBTRACE 11
+#define KTAP_TPTABLE 12
+#define KTAP_TSTATDATA 13
+#define KTAP_TCDATA 14
+/*
+ * type number is ok so far, but it may collide later between
+ * 16+ and | (1 << 4), so be careful on this.
+ */
+
+#define ttype(o) ((o->type) & 0x3F)
+#define settype(obj, t) ((obj)->type = (t))
+
+/* raw type tag of a TValue */
+#define rttype(o) ((o)->type)
+
+/* tag with no variants (bits 0-3) */
+#define novariant(x) ((x) & 0x0F)
+
+/* type tag of a TValue with no variants (bits 0-3) */
+#define ttypenv(o) (novariant(rttype(o)))
+
+#define val_(o) ((o)->val)
+#define gcvalue(o) (val_(o).gc)
+
+#define bvalue(o) (val_(o).b)
+#define nvalue(o) (val_(o).n)
+#define hvalue(o) (&val_(o).gc->h)
+#define phvalue(o) (&val_(o).gc->ph)
+#define clvalue(o) (&val_(o).gc->cl)
+
+#define getstr(ts) (const char *)((ts) + 1)
+#define eqshrstr(a, b) ((a) == (b))
+#define rawtsvalue(o) (&val_(o).gc->ts)
+#define svalue(o) getstr(rawtsvalue(o))
+
+#define pvalue(o) (&val_(o).p)
+#define sdvalue(o) ((ktap_stat_data *)val_(o).p)
+#define fvalue(o) (val_(o).f)
+#define evalue(o) (val_(o).p)
+#define btvalue(o) (&val_(o).gc->bt)
+#define cdvalue(o) (&val_(o).gc->cd)
+
+#define is_nil(o) ((o)->type == KTAP_TNIL)
+#define is_boolean(o) ((o)->type == KTAP_TBOOLEAN)
+#define is_false(o) (is_nil(o) || (is_boolean(o) && bvalue(o) == 0))
+#define is_shrstring(o) ((o)->type == KTAP_TSHRSTR)
+#define is_string(o) (((o)->type & 0x0F) == KTAP_TSTRING)
+#define is_number(o) ((o)->type == KTAP_TNUMBER)
+#define is_table(o) ((o)->type == KTAP_TTABLE)
+#define is_ptable(o) ((o)->type == KTAP_TPTABLE)
+#define is_statdata(o) ((o)->type == KTAP_TSTATDATA)
+#define is_event(o) ((o)->type == KTAP_TEVENT)
+#define is_btrace(o) ((o)->type == KTAP_TBTRACE)
+#define is_needclone(o) is_btrace(o)
+#ifdef CONFIG_KTAP_FFI
+#define is_cdata(o) ((o)->type == KTAP_TCDATA)
+#endif
+
+
+#define set_nil(obj) \
+ { ktap_value *io = (obj); io->val.n = 0; settype(io, KTAP_TNIL); }
+
+#define set_boolean(obj, x) \
+ { ktap_value *io = (obj); io->val.b = (x); settype(io, KTAP_TBOOLEAN); }
+
+#define set_number(obj, x) \
+ { ktap_value *io = (obj); io->val.n = (x); settype(io, KTAP_TNUMBER); }
+
+#define set_statdata(obj, x) \
+ { ktap_value *io = (obj); \
+ io->val.p = (x); settype(io, KTAP_TSTATDATA); }
+
+#define set_string(obj, x) \
+ { ktap_value *io = (obj); \
+ ktap_string *x_ = (x); \
+ io->val.gc = (ktap_gcobject *)x_; settype(io, x_->tsv.tt); }
+
+#define set_closure(obj, x) \
+ { ktap_value *io = (obj); \
+ io->val.gc = (ktap_gcobject *)x; settype(io, KTAP_TCLOSURE); }
+
+#define set_cfunction(obj, x) \
+ { ktap_value *io = (obj); val_(io).f = (x); settype(io, KTAP_TCFUNCTION); }
+
+#define set_table(obj, x) \
+ { ktap_value *io = (obj); \
+ val_(io).gc = (ktap_gcobject *)(x); settype(io, KTAP_TTABLE); }
+
+#define set_ptable(obj, x) \
+ { ktap_value *io = (obj); \
+ val_(io).gc = (ktap_gcobject *)(x); settype(io, KTAP_TPTABLE); }
+
+#define set_thread(obj, x) \
+ { ktap_value *io = (obj); \
+ val_(io).gc = (ktap_gcobject *)(x); settype(io, KTAP_TTHREAD); }
+
+#define set_event(obj, x) \
+ { ktap_value *io = (obj); val_(io).p = (x); settype(io, KTAP_TEVENT); }
+
+#define set_btrace(obj, x) \
+ { ktap_value *io = (obj); \
+ val_(io).gc = (ktap_gcobject *)(x); settype(io, KTAP_TBTRACE); }
+
+#ifdef CONFIG_KTAP_FFI
+#define set_cdata(obj, x) \
+ { ktap_value *io=(obj); \
+ val_(io).gc = (ktap_gcobject *)(x); settype(io, KTAP_TCDATA); }
+#endif
+
+#define set_obj(obj1, obj2) \
+ { const ktap_value *io2 = (obj2); ktap_value *io1 = (obj1); \
+ io1->val = io2->val; io1->type = io2->type; }
+
+#define rawequalobj(t1, t2) \
+ (((t1)->type == (t2)->type) && kp_equalobjv(NULL, t1, t2))
+
+#define incr_top(ks) {ks->top++;}
+
+#define NUMADD(a, b) ((a) + (b))
+#define NUMSUB(a, b) ((a) - (b))
+#define NUMMUL(a, b) ((a) * (b))
+#define NUMDIV(a, b) ((a) / (b))
+#define NUMUNM(a) (-(a))
+#define NUMEQ(a, b) ((a) == (b))
+#define NUMLT(a, b) ((a) < (b))
+#define NUMLE(a, b) ((a) <= (b))
+#define NUMISNAN(a) (!NUMEQ((a), (a)))
+
+/* todo: floor and pow in kernel */
+#define NUMMOD(a, b) ((a) % (b))
+#define NUMPOW(a, b) (pow(a, b))
+
+#define ktap_assert(s)
+
+#define kp_realloc(ks, v, osize, nsize, t) \
+ ((v) = (t *)kp_reallocv(ks, v, osize * sizeof(t), nsize * sizeof(t)))
+
+#define kp_error(ks, args...) \
+ do { \
+ kp_printf(ks, "error: "args); \
+ G(ks)->error = 1; \
+ kp_exit(ks); \
+ } while(0)
+
+#ifdef __KERNEL__
+#define G(ks) (ks->g)
+
+void kp_printf(ktap_state *ks, const char *fmt, ...);
+extern void __kp_puts(ktap_state *ks, const char *str);
+extern void __kp_bputs(ktap_state *ks, const char *str);
+
+#define kp_puts(ks, str) ({ \
+ static const char *trace_printk_fmt \
+ __attribute__((section("__trace_printk_fmt"))) = \
+ __builtin_constant_p(str) ? str : NULL; \
+ \
+ if (__builtin_constant_p(str)) \
+ __kp_bputs(ks, trace_printk_fmt); \
+ else \
+ __kp_puts(ks, str); \
+})
+
+#else
+/*
+ * this is used for ktapc tstring operation, tstring need G(ks)->strt
+ * and G(ks)->seed, so ktapc need to init those field
+ */
+#define G(ks) (&dummy_global_state)
+extern ktap_global_state dummy_global_state;
+
+#define kp_printf(ks, args...) printf(args)
+#define kp_puts(ks, str) printf("%s", str)
+#define kp_exit(ks) exit(EXIT_FAILURE)
+
+#endif
+
+#define __maybe_unused __attribute__((unused))
+
+/*
+ * KTAP_QL describes how error messages quote program elements.
+ * CHANGE it if you want a different appearance.
+ */
+#define KTAP_QL(x) "'" x "'"
+#define KTAP_QS KTAP_QL("%s")
+
+#define STRINGIFY(type) #type
+
+#endif /* __KTAP_TYPES_H__ */
+
--- /dev/null
+++ b/drivers/staging/ktap/runtime/ffi/call_x86_64.S
@@ -0,0 +1,143 @@
+/*
+ * call_x86_64.S - assembly code to call C function and handle return value
+ *
+ * This file is part of ktap by Jovi Zhangwei
+ *
+ * Copyright (C) 2012-2013 Jovi Zhangwei <jovi.zhangwei@gmail.com>.
+ *
+ * ktap is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * ktap is distributed in the hope 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.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+#ifdef __x86_64
+
+ .file "call_x86_64.S"
+ .text
+
+/* ffi_call_assem_x86_64(void *stack, void *temp_stack,
+ * void *rvalue, void *func_addr, ffi_type rftype)
+ * @stack: base address of register values and new stack
+ * @temp_stack: stack to store temporary values
+ * @func_addr: Function address
+ * @rvalue: where to put return value
+ * @rftype: FFI type of return value
+ */
+ .align 2
+ .globl ffi_call_assem_x86_64
+ .type ffi_call_assem_x86_64,@function
+
+ffi_call_assem_x86_64:
+ movq (%rsp), %rax /* save return address */
+ /* move stuffs to temp memory region(void *temp_stack) */
+ movq %rcx, (%rsi) /* save pointer to return value */
+ movq %r8, 8(%rsi) /* save return_ffi_type */
+ movq %rbp, 16(%rsi) /* save %rbp */
+ movq %rax, 24(%rsi) /* save return address */
+ movq %rsp, 32(%rsi) /* save %rsp */
+ movq %rsi, %rbp /* point %rbp to temp memory region */
+
+ movq %rdx, %r11 /* move function address to %r11 */
+
+ movq %rdi, %r10 /* set %r10 point to register region */
+ movq (%r10), %rdi /* load registers */
+ movq 8(%r10), %rsi
+ movq 16(%r10), %rdx
+ movq 24(%r10), %rcx
+ movq 32(%r10), %r8
+ movq 40(%r10), %r9
+ xorq %rax, %rax
+
+ leaq 48(%r10), %rsp
+
+ callq *%r11
+
+ movq 32(%rbp), %rsp /* restore %rsp */
+ movq 24(%rbp), %rcx /* restore return address */
+ movq %rcx, (%rsp)
+
+ movq (%rbp), %rcx /* get pointer to return value */
+ movq 8(%rbp), %r8 /* get return_ffi_type */
+ movq 16(%rbp), %rbp /* restore rbp */
+
+ leaq .Lreturn_table(%rip), %r11 /* start address of return_table */
+ movslq (%r11, %r8, 8), %r11 /* fetch target address from table */
+ jmpq *%r11 /* jump according to value in table */
+
+ .align 8
+.Lreturn_table:
+ .quad .Lreturn_void /* FFI_VOID */
+ .quad .Lreturn_uint8 /* FFI_UINT8 */
+ .quad .Lreturn_int8 /* FFI_INT8 */
+ .quad .Lreturn_uint16 /* FFI_UINT16 */
+ .quad .Lreturn_int16 /* FFI_INT16 */
+ .quad .Lreturn_uint32 /* FFI_UINT32 */
+ .quad .Lreturn_int32 /* FFI_INT32 */
+ .quad .Lreturn_uint64 /* FFI_UINT64 */
+ .quad .Lreturn_int64 /* FFI_INT64 */
+ .quad .Lreturn_ptr /* FFI_PTR */
+ .quad .Lreturn_func /* FFI_FUNC */
+ .quad .Lreturn_struct /* FFI_STRUCT */
+ .quad .Lreturn_unknown /* FFI_UNKNOWN */
+
+ .align 8
+.Lreturn_void:
+.Lreturn_func:
+.Lreturn_unknown:
+ retq
+ .align 8
+.Lreturn_uint8:
+ movzbq %al, %rax
+ movq %rax, (%rcx)
+ retq
+ .align 8
+.Lreturn_int8:
+ movsbq %al, %rax
+ movq %rax, (%rcx)
+ retq
+ .align 8
+.Lreturn_uint16:
+ movzwq %ax, %rax
+ movq %rax, (%rcx)
+ retq
+ .align 8
+.Lreturn_int16:
+ movswq %ax, %rax
+ movq %rax, (%rcx)
+ retq
+ .align 8
+.Lreturn_uint32:
+ movl %eax, %eax
+ movq %rax, (%rcx)
+ retq
+ .align 8
+.Lreturn_int32:
+ movslq %eax, %rax
+ movq %rax, (%rcx)
+ retq
+ .align 8
+.Lreturn_uint64:
+.Lreturn_int64:
+.Lreturn_ptr:
+ movq %rax, (%rcx)
+ retq
+/* Struct type indicates that struct is put into at most two registers,
+ * and 16 bytes space is always available
+ */
+ .align 8
+.Lreturn_struct:
+ movq %rax, (%rcx)
+ movq %rdx, 8(%rcx)
+ retq
+
+#endif /* end for __x86_64 */
--- /dev/null
+++ b/drivers/staging/ktap/runtime/ffi/cdata.c
@@ -0,0 +1,67 @@
+/*
+ * cdata.c - support functions for ktap_cdata
+ *
+ * This file is part of ktap by Jovi Zhangwei
+ *
+ * Copyright (C) 2012-2013 Jovi Zhangwei <jovi.zhangwei@gmail.com>.
+ *
+ * ktap is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * ktap is distributed in the hope 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.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+#include "../../include/ktap_types.h"
+#include "../../include/ktap_ffi.h"
+#include "../kp_obj.h"
+
+ktap_cdata *kp_cdata_new(ktap_state *ks)
+{
+ ktap_cdata *cd;
+
+ cd = &kp_newobject(ks, KTAP_TCDATA, sizeof(ktap_cdata), NULL)->cd;
+
+ return cd;
+}
+
+ktap_cdata *kp_cdata_new_ptr(ktap_state *ks, void *addr, csymbol_id id)
+{
+ ktap_cdata *cd;
+
+ cd = kp_cdata_new(ks);
+ cd_set_csym_id(cd, id);
+ cd_ptr(cd) = addr;
+
+ return cd;
+}
+
+ktap_cdata *kp_cdata_new_struct(ktap_state *ks, void *val, csymbol_id id)
+{
+ ktap_cdata *cd;
+
+ cd = kp_cdata_new(ks);
+ cd_set_csym_id(cd, id);
+ cd_struct(cd) = val;
+
+ return cd;
+}
+
+void kp_cdata_dump(ktap_state *ks, ktap_cdata *cd)
+{
+ switch (cd_type(ks, cd)) {
+ case FFI_PTR:
+ kp_printf(ks, "pointer(%p)", cd_ptr(cd));
+ break;
+ default:
+ kp_printf(ks, "unsupported cdata type %d!\n", cd_type(ks, cd));
+ }
+}
--- /dev/null
+++ b/drivers/staging/ktap/runtime/ffi/ffi_call.c
@@ -0,0 +1,427 @@
+/*
+ * ffi_call.c - foreign function calling library support for ktap
+ *
+ * This file is part of ktap by Jovi Zhangwei.
+ *
+ * Copyright (C) 2012-2013 Jovi Zhangwei <jovi.zhangwei@gmail.com>.
+ *
+ * ktap is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * ktap is distributed in the hope 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.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/ctype.h>
+#include <linux/slab.h>
+#include "../../include/ktap_types.h"
+#include "../../include/ktap_ffi.h"
+#include "../ktap.h"
+#include "../kp_vm.h"
+#include "../kp_obj.h"
+
+static int ffi_type_check(ktap_state *ks, csymbol_func *csf, int idx)
+{
+ StkId arg;
+ csymbol *cs;
+ ffi_type type;
+
+ if (idx >= csymf_arg_nr(csf))
+ return 0;
+ arg = kp_arg(ks, idx + 1);
+ cs = csymf_arg(ks, csf, idx);
+ type = csym_type(cs);
+
+ if (type == FFI_FUNC)
+ goto error;
+
+ switch (ttypenv(arg)) {
+ case KTAP_TLIGHTUSERDATA:
+ if (type != FFI_PTR) goto error;
+ break;
+ case KTAP_TBOOLEAN:
+ case KTAP_TNUMBER:
+ if (type != FFI_UINT8 && type != FFI_INT8
+ && type != FFI_UINT16 && type != FFI_INT16
+ && type != FFI_UINT32 && type != FFI_INT32
+ && type != FFI_UINT64 && type != FFI_INT64)
+ goto error;
+ break;
+ case KTAP_TSTRING:
+ if (type != FFI_PTR && type != FFI_UINT8 && type != FFI_INT8)
+ goto error;
+ break;
+ case KTAP_TCDATA:
+ if (cs != cd_csym(ks, cdvalue(arg)))
+ goto error;
+ break;
+ default:
+ goto error;
+ }
+ return 0;
+
+ error:
+ kp_error(ks, "Error: Cannot convert to csymbol %s for arg %d\n",
+ csym_name(cs), idx);
+ return -1;
+}
+
+static csymbol *ffi_get_arg_csym(ktap_state *ks, csymbol_func *csf, int idx)
+{
+ StkId arg;
+ csymbol *cs;
+
+ if (idx < csymf_arg_nr(csf))
+ return csymf_arg(ks, csf, idx);
+
+ arg = kp_arg(ks, idx + 1);
+ cs = id_to_csym(ks, ffi_get_csym_id(ks, "void *"));
+ switch (ttypenv(arg)) {
+ case KTAP_TLIGHTUSERDATA:
+ case KTAP_TBOOLEAN:
+ case KTAP_TNUMBER:
+ case KTAP_TSTRING:
+ return cs;
+ case KTAP_TCDATA:
+ return cd_csym(ks, cdvalue(arg));
+ default:
+ kp_error(ks, "Error: Cannot get type for arg %d\n", idx);
+ return cs;
+ }
+}
+
+static void ffi_unpack(ktap_state *ks, csymbol_func *csf, int idx,
+ char *dst, int align)
+{
+ StkId arg = kp_arg(ks, idx + 1);
+ csymbol *cs = ffi_get_arg_csym(ks, csf, idx);
+ ffi_type type = csym_type(cs);
+ size_t size = csym_size(ks, cs);
+ void *p;
+ struct ktap_cdata *cd;
+
+ /* initialize the destination section */
+ memset(dst, 0, ALIGN(size, align));
+
+ switch (ttypenv(arg)) {
+ case KTAP_TBOOLEAN:
+ memcpy(dst, &bvalue(arg), sizeof(bool));
+ return;
+ case KTAP_TLIGHTUSERDATA:
+ memcpy(dst, pvalue(arg), size);
+ return;
+ case KTAP_TNUMBER:
+ memcpy(dst, &nvalue(arg), size < sizeof(ktap_number) ?
+ size : sizeof(ktap_number));
+ return;
+ case KTAP_TSTRING:
+ p = &rawtsvalue(arg)->tsv + 1;
+ memcpy(dst, &p, size);
+ return;
+ }
+
+ cd = cdvalue(arg);
+ switch (type) {
+ case FFI_VOID:
+ kp_error(ks, "Error: Cannot copy data from void type\n");
+ return;
+ case FFI_UINT8:
+ case FFI_INT8:
+ case FFI_UINT16:
+ case FFI_INT16:
+ case FFI_UINT32:
+ case FFI_INT32:
+ case FFI_UINT64:
+ case FFI_INT64:
+ memcpy(dst, &cd_int(cd), size);
+ return;
+ case FFI_PTR:
+ memcpy(dst, &cd_ptr(cd), size);
+ return;
+ case FFI_STRUCT:
+ memcpy(dst, cd_struct(cd), size);
+ return;
+ case FFI_FUNC:
+ case FFI_UNKNOWN:
+ kp_error(ks, "Error: internal error for csymbol %s\n",
+ csym_name(cs));
+ return;
+ }
+}
+
+#ifdef __x86_64
+
+enum arg_status {
+ IN_REGISTER,
+ IN_MEMORY,
+ IN_STACK,
+};
+
+#define ALIGN_STACK(v, a) ((void *)(ALIGN(((uint64_t)v), a)))
+#define STACK_ALIGNMENT 8
+#define REDZONE_SIZE 128
+#define GPR_SIZE (sizeof(void *))
+#define MAX_GPR 6
+#define MAX_GPR_SIZE (MAX_GPR * GPR_SIZE)
+#define NEWSTACK_SIZE 512
+
+#define ffi_call(ks, cf, rvalue) ffi_call_x86_64(ks, cf, rvalue)
+
+extern void ffi_call_assem_x86_64(void *stack, void *temp_stack,
+ void *func_addr, void *rvalue, ffi_type rtype);
+
+static void ffi_call_x86_64(ktap_state *ks, csymbol_func *csf, void *rvalue)
+{
+ int i;
+ int gpr_nr;
+ int arg_bytes; /* total bytes needed for exceeded args in stack */
+ int mem_bytes; /* total bytes needed for memory storage */
+ char *stack, *stack_p, *gpr_p, *arg_p, *mem_p, *tmp_p;
+ int arg_nr;
+ csymbol *rsym;
+ ffi_type rtype;
+ size_t rsize;
+ bool ret_in_memory;
+ /* New stack to call C function */
+ char space[NEWSTACK_SIZE];
+
+ arg_nr = kp_arg_nr(ks);
+ rsym = csymf_ret(ks, csf);
+ rtype = csym_type(rsym);
+ rsize = csym_size(ks, rsym);
+ ret_in_memory = false;
+ if (rtype == FFI_STRUCT) {
+ if (rsize > 16) {
+ rvalue = kp_malloc(ks, rsize);
+ rtype = FFI_VOID;
+ ret_in_memory = true;
+ } else {
+ /* much easier to always copy 16 bytes from registers */
+ rvalue = kp_malloc(ks, 16);
+ }
+ }
+
+ gpr_nr = 0;
+ arg_bytes = mem_bytes = 0;
+ if (ret_in_memory)
+ gpr_nr++;
+ /* calculate bytes needed for stack */
+ for (i = 0; i < arg_nr; i++) {
+ csymbol *cs = ffi_get_arg_csym(ks, csf, i);
+ size_t size = csym_size(ks, cs);
+ size_t align = csym_align(ks, cs);
+ enum arg_status st = IN_REGISTER;
+ int n_gpr_nr = 0;
+ if (size > 32) {
+ st = IN_MEMORY;
+ n_gpr_nr = 1;
+ } else if (size > 16)
+ st = IN_STACK;
+ else
+ n_gpr_nr = ALIGN(size, GPR_SIZE) / GPR_SIZE;
+
+ if (gpr_nr + n_gpr_nr > MAX_GPR) {
+ if (st == IN_MEMORY)
+ arg_bytes += GPR_SIZE;
+ else
+ st = IN_STACK;
+ } else
+ gpr_nr += n_gpr_nr;
+ if (st == IN_STACK) {
+ arg_bytes = ALIGN(arg_bytes, align);
+ arg_bytes += size;
+ arg_bytes = ALIGN(arg_bytes, STACK_ALIGNMENT);
+ }
+ if (st == IN_MEMORY) {
+ mem_bytes = ALIGN(mem_bytes, align);
+ mem_bytes += size;
+ mem_bytes = ALIGN(mem_bytes, STACK_ALIGNMENT);
+ }
+ }
+
+ /* apply space to fake stack for C function call */
+ if (16 + REDZONE_SIZE + MAX_GPR_SIZE + arg_bytes +
+ mem_bytes + 6 * 8 >= NEWSTACK_SIZE) {
+ kp_error(ks, "Unable to handle that many arguments by now\n");
+ return;
+ }
+ stack = space;
+ /* 128 bytes below %rsp is red zone */
+ /* stack should be 16-bytes aligned */
+ stack_p = ALIGN_STACK(stack + REDZONE_SIZE, 16);
+ /* save general purpose registers here */
+ gpr_p = stack_p;
+ memset(gpr_p, 0, MAX_GPR_SIZE);
+ /* save arguments in stack here */
+ arg_p = gpr_p + MAX_GPR_SIZE;
+ /* save arguments in memory here */
+ mem_p = arg_p + arg_bytes;
+ /* set additional space as temporary space */
+ tmp_p = mem_p + mem_bytes;
+
+ /* copy arguments here */
+ gpr_nr = 0;
+ if (ret_in_memory) {
+ memcpy(gpr_p, &rvalue, GPR_SIZE);
+ gpr_p += GPR_SIZE;
+ gpr_nr++;
+ }
+ for (i = 0; i < arg_nr; i++) {
+ csymbol *cs = ffi_get_arg_csym(ks, csf, i);
+ size_t size = csym_size(ks, cs);
+ size_t align = csym_align(ks, cs);
+ enum arg_status st = IN_REGISTER;
+ int n_gpr_nr = 0;
+ if (size > 32) {
+ st = IN_MEMORY;
+ n_gpr_nr = 1;
+ } else if (size > 16)
+ st = IN_STACK;
+ else
+ n_gpr_nr = ALIGN(size, GPR_SIZE) / GPR_SIZE;
+
+ if (st == IN_MEMORY)
+ mem_p = ALIGN_STACK(mem_p, align);
+ /* Tricky way about storing it above mem_p. It won't overflow
+ * because temp region can be temporarily used if necesseary. */
+ ffi_unpack(ks, csf, i, mem_p, GPR_SIZE);
+ if (gpr_nr + n_gpr_nr > MAX_GPR) {
+ if (st == IN_MEMORY) {
+ memcpy(arg_p, &mem_p, GPR_SIZE);
+ arg_p += GPR_SIZE;
+ } else
+ st = IN_STACK;
+ } else {
+ memcpy(gpr_p, mem_p, n_gpr_nr * GPR_SIZE);
+ gpr_p += n_gpr_nr * GPR_SIZE;
+ gpr_nr += n_gpr_nr;
+ }
+ if (st == IN_STACK) {
+ arg_p = ALIGN_STACK(arg_p, align);
+ memcpy(arg_p, mem_p, size);
+ arg_p += size;
+ arg_p = ALIGN_STACK(arg_p, STACK_ALIGNMENT);
+ }
+ if (st == IN_MEMORY) {
+ mem_p += size;
+ mem_p = ALIGN_STACK(mem_p, STACK_ALIGNMENT);
+ }
+ }
+
+ kp_verbose_printf(ks, "Stack location: %p -redzone- %p -general purpose "
+ "register used- %p -zero- %p -stack for argument- %p"
+ " -memory for argument- %p -temp stack-\n",
+ stack, stack_p, gpr_p, stack_p + MAX_GPR_SIZE,
+ arg_p, mem_p);
+ kp_verbose_printf(ks, "GPR number: %d; arg in stack: %d; "
+ "arg in mem: %d\n",
+ gpr_nr, arg_bytes, mem_bytes);
+ kp_verbose_printf(ks, "Return: address %p type %d\n", rvalue, rtype);
+ kp_verbose_printf(ks, "Number of register used: %d\n", gpr_nr);
+ kp_verbose_printf(ks, "Start FFI call on %p\n", csf->addr);
+ ffi_call_assem_x86_64(stack_p, tmp_p, csf->addr, rvalue, rtype);
+}
+
+#else /* non-supported platform */
+
+#define ffi_call(ks, cf, rvalue) ffi_call_unsupported(ks, cf, rvalue)
+
+static void ffi_call_unsupported(ktap_state *ks,
+ csymbol_func *csf, void *rvalue)
+{
+ kp_error(ks, "unsupported architecture.\n");
+}
+
+#endif /* end for platform-specific setting */
+
+
+static int ffi_set_return(ktap_state *ks, void *rvalue, csymbol_id ret_id)
+{
+ ktap_cdata *cd;
+ ffi_type type = csym_type(id_to_csym(ks, ret_id));
+
+ /* push return value to ktap stack */
+ switch (type) {
+ case FFI_VOID:
+ return 0;
+ case FFI_UINT8:
+ case FFI_INT8:
+ case FFI_UINT16:
+ case FFI_INT16:
+ case FFI_UINT32:
+ case FFI_INT32:
+ case FFI_UINT64:
+ case FFI_INT64:
+ set_number(ks->top, (ktap_number)rvalue);
+ break;
+ case FFI_PTR:
+ cd = kp_cdata_new_ptr(ks, rvalue, ret_id);
+ set_cdata(ks->top, cd);
+ break;
+ case FFI_STRUCT:
+ cd = kp_cdata_new_struct(ks, rvalue, ret_id);
+ set_cdata(ks->top, cd);
+ break;
+ case FFI_FUNC:
+ case FFI_UNKNOWN:
+ kp_error(ks, "Error: Have not support ffi_type %s\n",
+ ffi_type_name(type));
+ return 0;
+ }
+ incr_top(ks);
+ return 1;
+}
+
+/*
+ * Call C into function
+ * First argument should be function symbol address, argument types
+ * and return type.
+ * Left arguments should be arguments for calling the C function.
+ * Types between Ktap and C are converted automatically.
+ * Only support x86_64 function call by now
+ */
+int kp_ffi_call(ktap_state *ks, csymbol_func *csf)
+{
+ int i;
+ int expected_arg_nr, arg_nr;
+ ktap_closure *cl;
+ void *rvalue;
+
+ expected_arg_nr = csymf_arg_nr(csf);
+ arg_nr = kp_arg_nr(ks);
+
+ /* check stack status for C call */
+ if (!csf->has_var_arg && expected_arg_nr != arg_nr) {
+ kp_error(ks, "wrong argument number %d, which should be %d\n",
+ arg_nr, expected_arg_nr);
+ goto out;
+ }
+ if (csf->has_var_arg && expected_arg_nr > arg_nr) {
+ kp_error(ks, "argument number %d, which should be bigger than %d\n",
+ arg_nr, expected_arg_nr);
+ goto out;
+ }
+
+ /* maybe useful later, leave it here first */
+ cl = clvalue(kp_arg(ks, arg_nr + 1));
+
+ /* check the argument types */
+ for (i = 0; i < arg_nr; i++) {
+ if (ffi_type_check(ks, csf, i) < 0)
+ goto out;
+ }
+
+ /* platform-specific calling workflow */
+ ffi_call(ks, csf, &rvalue);
+ kp_verbose_printf(ks, "Finish FFI call\n");
+
+out:
+ return ffi_set_return(ks, rvalue, csymf_ret_id(csf));
+}
--- /dev/null
+++ b/drivers/staging/ktap/runtime/ffi/ffi_symbol.c
@@ -0,0 +1,174 @@
+/*
+ * ffi_symbol.c - ktapvm kernel module ffi symbol submodule
+ *
+ * This file is part of ktap by Jovi Zhangwei.
+ *
+ * Copyright (C) 2012-2013 Jovi Zhangwei <jovi.zhangwei@gmail.com>.
+ *
+ * ktap is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * ktap is distributed in the hope 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.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+#include "../../include/ktap_types.h"
+#include "../../include/ktap_ffi.h"
+#include "../ktap.h"
+#include "../kp_vm.h"
+#include "../kp_obj.h"
+#include "../kp_str.h"
+#include "../kp_tab.h"
+
+void setup_kp_ffi_symbol_table(ktap_state *ks);
+
+
+static inline csymbol *get_csym_arr(ktap_state *ks)
+{
+ return G(ks)->ffis.csym_arr;
+}
+
+static inline int get_csym_nr(ktap_state *ks)
+{
+ return G(ks)->ffis.csym_nr;
+}
+
+static inline void set_csym_arr(ktap_state *ks, csymbol *csym)
+{
+ G(ks)->ffis.csym_arr = csym;
+}
+
+static inline void set_csym_nr(ktap_state *ks, int nr)
+{
+ G(ks)->ffis.csym_nr = nr;
+}
+
+
+static inline ktap_tab *get_ffi_ctable(ktap_state *ks)
+{
+ return G(ks)->ffis.ctable;
+}
+
+static void setup_ffi_ctable(ktap_state *ks)
+{
+ ktap_value ffi_lib_name, ffi_mt;
+ ktap_tab *registry;
+ const ktap_value *gt;
+
+ gt = kp_tab_getint(hvalue(&G(ks)->registry), KTAP_RIDX_GLOBALS);
+
+ G(ks)->ffis.ctable = kp_tab_new(ks);
+
+ /* insert ffi C table to global table */
+ set_table(&ffi_mt, get_ffi_ctable(ks));
+ set_string(&ffi_lib_name, kp_tstring_new(ks, "C"));
+ registry = hvalue(gt);
+ kp_tab_setvalue(ks, registry, &ffi_lib_name, &ffi_mt);
+}
+
+void ffi_set_csym_arr(ktap_state *ks, int cs_nr, csymbol *new_arr)
+{
+ set_csym_nr(ks, cs_nr);
+ set_csym_arr(ks, new_arr);
+
+ if (!new_arr)
+ return;
+
+ setup_kp_ffi_symbol_table(ks);
+}
+
+inline csymbol *ffi_get_csym_by_id(ktap_state *ks, int id)
+{
+ return &(get_csym_arr(ks)[id]);
+}
+
+csymbol_id ffi_get_csym_id(ktap_state *ks, char *name)
+{
+ int i;
+
+ for (i = 0; i < get_csym_nr(ks); i++) {
+ if (!strcmp(name, csym_name(ffi_get_csym_by_id(ks, i)))) {
+ return i;
+ }
+ }
+
+ kp_error(ks, "Cannot find csymbol with name %s\n", name);
+ return 0;
+}
+
+static void add_ffi_func_to_ctable(ktap_state *ks, csymbol_id id)
+{
+ ktap_value func_name, fv;
+ ktap_cdata *cd;
+ csymbol *cs;
+
+ /* push cdata to ctable */
+ set_cdata(&fv, kp_newobject(ks, KTAP_TCDATA, sizeof(ktap_cdata), NULL));
+ cd = cdvalue(&fv);
+ cd_set_csym_id(cd, id);
+
+ cs = id_to_csym(ks, id);
+ set_string(&func_name, kp_tstring_new(ks, csym_name(cs)));
+ kp_tab_setvalue(ks, get_ffi_ctable(ks), &func_name, &fv);
+}
+
+void setup_kp_ffi_symbol_table(ktap_state *ks)
+{
+ int i;
+ csymbol *cs;
+
+ setup_ffi_ctable(ks);
+
+ /* push all functions to ctable */
+ for (i = 0; i < get_csym_nr(ks); i++) {
+ cs = &get_csym_arr(ks)[i];
+ switch (cs->type) {
+ case FFI_FUNC:
+ kp_verbose_printf(ks, "[%d] loading C function %s\n",
+ i, csym_name(cs));
+ add_ffi_func_to_ctable(ks, i);
+ kp_verbose_printf(ks, "%s loaded\n", csym_name(cs));
+ break;
+ case FFI_STRUCT:
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void kp_ffi_free_symbol(ktap_state *ks)
+{
+ int i;
+ csymbol_id *arg_ids;
+ csymbol *cs;
+
+ if (!get_csym_arr(ks))
+ return;
+
+ for (i = 0; i < get_csym_nr(ks); i++) {
+ cs = &get_csym_arr(ks)[i];
+ switch (csym_type(cs)) {
+ case FFI_FUNC:
+ arg_ids = csym_func_arg_ids(cs);
+ if (arg_ids)
+ kp_free(ks, arg_ids);
+ break;
+ case FFI_STRUCT:
+ /*@TODO finish this 20.11 2013 (houqp)*/
+ break;
+ default:
+ break;
+ }
+ }
+
+ kp_free(ks, get_csym_arr(ks));
+}
--- /dev/null
+++ b/drivers/staging/ktap/runtime/ffi/ffi_type.c
@@ -0,0 +1,51 @@
+#include "../../include/ktap_ffi.h"
+#ifdef __KERNEL__
+#include <linux/types.h>
+#else
+#include <stdint.h>
+#include <stddef.h>
+#endif
+
+#define CTYPE_MODE_HELPER(name, type) \
+struct _##name##_align { \
+ type t1; \
+ char c; \
+ type t2; \
+};
+
+#define CTYPE_MODE(name) \
+{ \
+ offsetof(struct _##name##_align, c), \
+ offsetof(struct _##name##_align, t2) - \
+ offsetof(struct _##name##_align, c), \
+ #name \
+}
+
+#define CTYPE_MODE_NAME(name) _##name##_mode
+
+/* ffi_ctype_mode should be corresponded to ffi_ctype */
+CTYPE_MODE_HELPER(uint8, uint8_t);
+CTYPE_MODE_HELPER(int8, int8_t);
+CTYPE_MODE_HELPER(uint16, uint16_t);
+CTYPE_MODE_HELPER(int16, int16_t);
+CTYPE_MODE_HELPER(uint32, uint32_t);
+CTYPE_MODE_HELPER(int32, int32_t);
+CTYPE_MODE_HELPER(uint64, uint64_t);
+CTYPE_MODE_HELPER(int64, int64_t);
+CTYPE_MODE_HELPER(pointer, void*);
+
+const ffi_mode ffi_type_modes[NUM_FFI_TYPE+1] = {
+ {0, 1, "void"},
+ CTYPE_MODE(uint8),
+ CTYPE_MODE(int8),
+ CTYPE_MODE(uint16),
+ CTYPE_MODE(int16),
+ CTYPE_MODE(uint32),
+ CTYPE_MODE(int32),
+ CTYPE_MODE(uint64),
+ CTYPE_MODE(int64),
+ CTYPE_MODE(pointer),
+ {0, 1, "function"},
+ {0, 1, "struct"},
+ {0, 1, "unknown"},
+};
--- /dev/null
+++ b/drivers/staging/ktap/runtime/ffi/ffi_util.c
@@ -0,0 +1,92 @@
+/*
+ * ffi_util.c - utility function for ffi module
+ *
+ * This file is part of ktap by Jovi Zhangwei.
+ *
+ * Copyright (C) 2012-2013 Jovi Zhangwei <jovi.zhangwei@gmail.com>.
+ *
+ * ktap is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * ktap is distributed in the hope 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.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+#include "../../include/ktap_types.h"
+#include "../../include/ktap_ffi.h"
+#include "../ktap.h"
+
+size_t csym_size(ktap_state *ks, csymbol *cs)
+{
+ ffi_type type = csym_type(cs);
+ switch(type) {
+ case FFI_STRUCT:
+ if (csym_struct(cs)->align == 0)
+ init_csym_struct(ks, csym_struct(cs));
+ return csym_struct(cs)->size;
+ default:
+ return ffi_type_size(type);
+ }
+}
+
+size_t csym_align(ktap_state *ks, csymbol *cs)
+{
+ ffi_type type = csym_type(cs);
+ switch(type) {
+ case FFI_STRUCT:
+ if (csym_struct(cs)->align == 0)
+ init_csym_struct(ks, csym_struct(cs));
+ return csym_struct(cs)->align;
+ default:
+ return ffi_type_align(type);
+ }
+}
+
+size_t csym_struct_offset(ktap_state *ks, csymbol_struct *csst, int idx)
+{
+ int nr = csymst_mb_nr(csst);
+ size_t off = 0;
+ size_t align = 1;
+ int i;
+
+ if (idx < 0 || idx > nr)
+ return -1;
+ for (i = 0; i < idx; i++) {
+ csymbol *var_cs = csymst_mb(ks, csst, i);
+ size_t var_size = csym_size(ks, var_cs);
+ size_t var_align = csym_align(ks, var_cs);
+ off = ALIGN(off, var_align);
+ off += var_size;
+ align = align > var_align ? align : var_align;
+ }
+ off = ALIGN(off, align);
+ return off;
+}
+
+void init_csym_struct(ktap_state *ks, csymbol_struct *csst)
+{
+ int nr = csymst_mb_nr(csst);
+ size_t size = 0;
+ size_t align = 1;
+ int i;
+
+ for (i = 0; i < nr; i++) {
+ csymbol *var_cs = csymst_mb(ks, csst, i);
+ size_t var_size = csym_size(ks, var_cs);
+ size_t var_align = csym_align(ks, var_cs);
+ size = ALIGN(size, var_align);
+ size += var_size;
+ align = align > var_align ? align : var_align;
+ }
+ size = ALIGN(size, align);
+ csst->size = size;
+ csst->align = align;
+}
--- /dev/null
+++ b/drivers/staging/ktap/runtime/kp_amalg.c
@@ -0,0 +1,43 @@
+/*
+ * kp_amalg.c - ktapvm kernel module amalgamation.
+ *
+ * This file is part of ktap by Jovi Zhangwei.
+ *
+ * Copyright (C) 2012-2013 Jovi Zhangwei <jovi.zhangwei@gmail.com>.
+ *
+ * ktap is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * ktap is distributed in the hope 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.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+#include "ktap.c"
+#include "kp_opcode.c"
+#include "kp_obj.c"
+#include "kp_load.c"
+#include "kp_str.c"
+#include "kp_tab.c"
+#include "kp_transport.c"
+#include "kp_vm.c"
+#include "lib_base.c"
+#include "lib_ansi.c"
+#include "lib_kdebug.c"
+#include "lib_timer.c"
+
+#ifdef CONFIG_KTAP_FFI
+#include "ffi/ffi_call.c"
+#include "ffi/ffi_type.c"
+#include "ffi/ffi_symbol.c"
+#include "ffi/cdata.c"
+#include "ffi/ffi_util.c"
+#include "lib_ffi.c"
+#endif
--- /dev/null
+++ b/drivers/staging/ktap/runtime/kp_load.c
@@ -0,0 +1,401 @@
+/*
+ * kp_load.c - loader for ktap bytecode chunk file
+ *
+ * This file is part of ktap by Jovi Zhangwei.
+ *
+ * Copyright (C) 2012-2013 Jovi Zhangwei <jovi.zhangwei@gmail.com>.
+ *
+ * Copyright (C) 1994-2013 Lua.org, PUC-Rio.
+ * - The part of code in this file is copied from lua initially.
+ * - lua's MIT license is compatible with GPL.
+ *
+ * ktap is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * ktap is distributed in the hope 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.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/slab.h>
+#include "../include/ktap_types.h"
+#include "../include/ktap_ffi.h"
+#include "ktap.h"
+#include "kp_load.h"
+#include "kp_obj.h"
+#include "kp_str.h"
+#include "kp_tab.h"
+#include "kp_vm.h"
+
+#define KTAPC_TAIL "\x19\x93\r\n\x1a\n"
+
+struct load_state {
+ unsigned char *buff;
+ int pos;
+ ktap_state *ks;
+};
+
+#define READ_CHAR(S) (S->buff[S->pos++])
+#define READ_BYTE(S) READ_CHAR(S)
+#define READ_INT(S) load_int(S)
+#define READ_NUMBER(S) load_number(S)
+#define READ_STRING(S) load_string(S)
+#define READ_VECTOR(S, dst, size) \
+ do { \
+ memcpy(dst, &S->buff[S->pos], size); \
+ S->pos += size; \
+ } while(0)
+
+#define NEW_VECTOR(S, size) kp_malloc(S->ks, size)
+#define FREE_VECTOR(S, v) kp_free(S->ks, v)
+#define GET_CURRENT(S) &S->buff[S->pos]
+#define ADD_POS(S, size) S->pos += size
+
+
+static int load_function(struct load_state *S, ktap_proto *f);
+
+
+static int load_int(struct load_state *S)
+{
+ int x;
+
+ READ_VECTOR(S, &x, sizeof(int));
+ return x;
+}
+
+static long load_number(struct load_state *S)
+{
+ long x;
+
+ READ_VECTOR(S, &x, sizeof(ktap_number));
+ return x;
+}
+
+static ktap_string *load_string(struct load_state *S)
+{
+ ktap_string *ts;
+ size_t size;
+
+ size = READ_INT(S);
+
+ if (!size)
+ return NULL;
+ else {
+ char *s = GET_CURRENT(S);
+ ADD_POS(S, size);
+ /* remove trailing '\0' */
+ ts = kp_tstring_newlstr(S->ks, s, size - 1);
+ return ts;
+ }
+}
+
+
+static int load_code(struct load_state *S, ktap_proto *f)
+{
+ int n = READ_INT(S);
+
+ f->sizecode = n;
+ f->code = NEW_VECTOR(S, n * sizeof(ktap_instruction));
+ READ_VECTOR(S, f->code, n * sizeof(ktap_instruction));
+
+ return 0;
+}
+
+static int load_constants(struct load_state *S, ktap_proto *f)
+{
+ int i,n;
+
+ n = READ_INT(S);
+
+ f->sizek = n;
+ f->k = NEW_VECTOR(S, n * sizeof(ktap_value));
+ for (i = 0; i < n; i++)
+ set_nil(&f->k[i]);
+
+ for (i=0; i < n; i++) {
+ ktap_value *o = &f->k[i];
+
+ int t = READ_CHAR(S);
+ switch (t) {
+ case KTAP_TNIL:
+ set_nil(o);
+ break;
+ case KTAP_TBOOLEAN:
+ set_boolean(o, READ_CHAR(S));
+ break;
+ case KTAP_TNUMBER:
+ /*
+ * todo: kernel not support fp, check double when
+ * loading
+ */
+ set_number(o, READ_NUMBER(S));
+ break;
+ case KTAP_TSTRING:
+ set_string(o, READ_STRING(S));
+ break;
+ default:
+ kp_error(S->ks, "ktap: load_constants: "
+ "unknow ktap_value\n");
+ return -1;
+
+ }
+ }
+
+ n = READ_INT(S);
+ f->p = NEW_VECTOR(S, n * sizeof(ktap_proto));
+ f->sizep = n;
+ for (i = 0; i < n; i++)
+ f->p[i] = NULL;
+ for (i = 0; i < n; i++) {
+ f->p[i] = kp_newproto(S->ks);
+ if (load_function(S, f->p[i]))
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int load_upvalues(struct load_state *S, ktap_proto *f)
+{
+ int i,n;
+
+ n = READ_INT(S);
+ f->upvalues = NEW_VECTOR(S, n * sizeof(ktap_upvaldesc));
+ f->sizeupvalues = n;
+
+ for (i = 0; i < n; i++)
+ f->upvalues[i].name = NULL;
+
+ for (i = 0; i < n; i++) {
+ f->upvalues[i].instack = READ_BYTE(S);
+ f->upvalues[i].idx = READ_BYTE(S);
+ }
+
+ return 0;
+}
+
+static int load_debuginfo(struct load_state *S, ktap_proto *f)
+{
+ int i,n;
+
+ f->source = READ_STRING(S);
+ n = READ_INT(S);
+ f->sizelineinfo = n;
+ f->lineinfo = NEW_VECTOR(S, n * sizeof(int));
+ READ_VECTOR(S, f->lineinfo, n * sizeof(int));
+ n = READ_INT(S);
+ f->locvars = NEW_VECTOR(S, n * sizeof(struct ktap_locvar));
+ f->sizelocvars = n;
+ for (i = 0; i < n; i++)
+ f->locvars[i].varname = NULL;
+ for (i = 0; i < n; i++) {
+ f->locvars[i].varname = READ_STRING(S);
+ f->locvars[i].startpc = READ_INT(S);
+ f->locvars[i].endpc = READ_INT(S);
+ }
+ n = READ_INT(S);
+ for (i = 0; i < n; i++)
+ f->upvalues[i].name = READ_STRING(S);
+
+ return 0;
+}
+
+static int load_function(struct load_state *S, ktap_proto *f)
+{
+ f->linedefined = READ_INT(S);
+ f->lastlinedefined = READ_INT(S);
+ f->numparams = READ_BYTE(S);
+ f->is_vararg = READ_BYTE(S);
+ f->maxstacksize = READ_BYTE(S);
+ if (load_code(S, f))
+ return -1;
+ if (load_constants(S, f))
+ return -1;
+ if (load_upvalues(S, f))
+ return -1;
+ if (load_debuginfo(S, f))
+ return -1;
+
+ return 0;
+}
+
+
+#define error(S, why) \
+ kp_error(S->ks, "load failed: %s precompiled chunk\n", why)
+
+#define N0 KTAPC_HEADERSIZE
+#define N1 (sizeof(KTAP_SIGNATURE) - sizeof(char))
+#define N2 N1 + 2
+#define N3 N2 + 6
+
+static int load_header(struct load_state *S)
+{
+ u8 h[KTAPC_HEADERSIZE];
+ u8 s[KTAPC_HEADERSIZE];
+
+ kp_header(h);
+ READ_VECTOR(S, s, KTAPC_HEADERSIZE);
+
+ if (memcmp(h, s, N0) == 0)
+ return 0;
+ if (memcmp(h, s, N1) != 0)
+ error(S, "not a");
+ else if (memcmp(h, s, N2) != 0)
+ error(S, "version mismatch in");
+ else if (memcmp(h, s, N3) != 0)
+ error(S, "incompatible");
+ else
+ error(S,"corrupted");
+
+ return -1;
+}
+
+#ifdef CONFIG_KTAP_FFI
+void ffi_set_csym_arr(ktap_state *ks, int cs_nr, csymbol *new_arr);
+
+static void load_csymbol_func(struct load_state *S, csymbol *cs)
+{
+ csymbol_func *csf = csym_func(cs);
+ int arg_nr = csymf_arg_nr(csf);
+
+ if (arg_nr > 0) {
+ csf->arg_ids = NEW_VECTOR(S, arg_nr*sizeof(int));
+ READ_VECTOR(S, csf->arg_ids, arg_nr*sizeof(int));
+ } else {
+ csf->arg_ids = NULL;
+ }
+}
+
+static void load_csymbol_struct(struct load_state *S, csymbol *cs)
+{
+ csymbol_struct *csst = csym_struct(cs);
+ int mb_nr = csymst_mb_nr(csst);
+
+ csst->members = NEW_VECTOR(S, mb_nr*sizeof(struct_member));
+ READ_VECTOR(S, csst->members, mb_nr*sizeof(struct_member));
+}
+
+static int load_csymbols(struct load_state *S)
+{
+ csymbol *cs_arr, *cs;
+ int i, csym_nr;
+
+ /* read number of csymbols */
+ csym_nr = READ_INT(S);
+ if (csym_nr <= 0) {
+ ffi_set_csym_arr(S->ks, 0, NULL);
+ return 0;
+ }
+
+ /* csymbol size safty check */
+ if (sizeof(csymbol) != READ_INT(S)) {
+ kp_error(S->ks, "invalid csymbol size in chunk\n");
+ return -1;
+ }
+
+ cs_arr = NEW_VECTOR(S, sizeof(csymbol)*csym_nr);
+ for (i = 0; i < csym_nr; i++) {
+ cs = &cs_arr[i];
+ READ_VECTOR(S, cs, sizeof(csymbol));
+ switch (cs->type) {
+ case FFI_FUNC:
+ load_csymbol_func(S, cs);
+ break;
+ case FFI_STRUCT:
+ load_csymbol_struct(S, cs);
+ break;
+ default:
+ break;
+ }
+ }
+
+ ffi_set_csym_arr(S->ks, csym_nr, cs_arr);
+
+ return 0;
+}
+#else
+static int load_csymbols(struct load_state *S)
+{
+ int csym_nr = READ_INT(S);
+
+ /* if FFI is disabled in ktapc, csym_nr should be 0 */
+ if (csym_nr != 0) {
+ /* skip corrupted csymbol chunk */
+ int cs_size = READ_INT(S);
+ ADD_POS(S, cs_size*csym_nr);
+ kp_error(S->ks, "VM compiled without FFI support!\n");
+ return -1;
+ }
+
+ return 0;
+}
+#endif
+
+static int verify_code(struct load_state *S, ktap_proto *f)
+{
+ /* not support now */
+ return 0;
+}
+
+
+ktap_closure *kp_load(ktap_state *ks, unsigned char *buff)
+{
+ struct load_state S;
+ ktap_closure *cl;
+ int ret, i;
+
+ S.ks = ks;
+ S.buff = buff;
+ S.pos = 0;
+
+ ret = load_header(&S);
+ if (ret)
+ return NULL;
+
+ ret = load_csymbols(&S);
+ if (ret)
+ return NULL;
+
+ cl = kp_newclosure(ks, 1);
+ if (!cl)
+ return cl;
+
+ /* put closure on the top, prepare to run with this closure */
+ set_closure(ks->top, cl);
+ incr_top(ks);
+
+ cl->p = kp_newproto(ks);
+ if (load_function(&S, cl->p))
+ return NULL;
+
+ if (cl->p->sizeupvalues != 1) {
+ ktap_proto *p = cl->p;
+ cl = kp_newclosure(ks, cl->p->sizeupvalues);
+ cl->p = p;
+ set_closure(ks->top - 1, cl);
+ }
+
+ for (i = 0; i < cl->nupvalues; i++) { /* initialize upvalues */
+ ktap_upval *up = kp_newupval(ks);
+ cl->upvals[i] = up;
+ }
+
+ /* set global table as 1st upvalue of 'f' */
+ if (cl->nupvalues == 1) {
+ ktap_tab *reg = hvalue(&G(ks)->registry);
+ const ktap_value *gt = kp_tab_getint(reg, KTAP_RIDX_GLOBALS);
+ set_obj(cl->upvals[0]->v, gt);
+ }
+
+ verify_code(&S, cl->p);
+
+ return cl;
+}
+
--- /dev/null
+++ b/drivers/staging/ktap/runtime/kp_load.h
@@ -0,0 +1,6 @@
+#ifndef __KTAP_LOAD_H__
+#define __KTAP_LOAD_H__
+
+ktap_closure *kp_load(ktap_state *ks, unsigned char *buff);
+
+#endif /* __KTAP_LOAD_H__ */
--- /dev/null
+++ b/drivers/staging/ktap/runtime/kp_obj.c
@@ -0,0 +1,478 @@
+/*
+ * kp_obj.c - ktap object generic operation
+ *
+ * This file is part of ktap by Jovi Zhangwei.
+ *
+ * Copyright (C) 2012-2013 Jovi Zhangwei <jovi.zhangwei@gmail.com>.
+ *
+ * Copyright (C) 1994-2013 Lua.org, PUC-Rio.
+ * - The part of code in this file is copied from lua initially.
+ * - lua's MIT license is compatible with GPL.
+ *
+ * ktap is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * ktap is distributed in the hope 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.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "../include/ktap_types.h"
+#include "../include/ktap_ffi.h"
+#include "kp_obj.h"
+#include "kp_str.h"
+#include "kp_tab.h"
+
+#ifdef __KERNEL__
+#include <linux/slab.h>
+#include "ktap.h"
+#include "kp_vm.h"
+#include "kp_transport.h"
+
+#define KTAP_ALLOC_FLAGS ((GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN) \
+ & ~__GFP_WAIT)
+
+void *kp_malloc(ktap_state *ks, int size)
+{
+ void *addr;
+
+ /*
+ * Normally we don't want to trace under memory pressure,
+ * so we use a simple rule to handle memory allocation failure:
+ *
+ * retry until allocation success, this will make caller don't need
+ * to handle the unlikely failure case, then ktap exit.
+ *
+ * In this approach, if user find there have memory allocation failure,
+ * user should re-run the ktap script, or fix the memory pressure
+ * issue, or figure out why the script need so many memory.
+ *
+ * Perhaps return pre-allocated stub memory trunk when allocate failed
+ * is a better approch?
+ */
+ addr = kmalloc(size, KTAP_ALLOC_FLAGS);
+ if (unlikely(!addr)) {
+ kp_error(ks, "kmalloc size %d failed, retry again\n", size);
+ printk("ktap kmalloc size %d failed, retry again\n", size);
+ dump_stack();
+ while (1) {
+ addr = kmalloc(size, KTAP_ALLOC_FLAGS);
+ if (addr)
+ break;
+ }
+ kp_printf(ks, "kmalloc retry success after failed, exit\n");
+ }
+
+ preempt_disable();
+ KTAP_STATS(ks)->nr_mem_allocate += 1;
+ KTAP_STATS(ks)->mem_allocated += size;
+ preempt_enable();
+
+ return addr;
+}
+
+void kp_free(ktap_state *ks, void *addr)
+{
+ preempt_disable();
+ KTAP_STATS(ks)->nr_mem_free += 1;
+ preempt_enable();
+
+ kfree(addr);
+}
+
+void *kp_reallocv(ktap_state *ks, void *addr, int oldsize, int newsize)
+{
+ void *new_addr;
+
+ new_addr = krealloc(addr, newsize, KTAP_ALLOC_FLAGS);
+ if (unlikely(!new_addr)) {
+ kp_error(ks, "krealloc size %d failed, retry again\n", newsize);
+ printk("ktap krealloc size %d failed, retry again\n", newsize);
+ dump_stack();
+ while (1) {
+ new_addr = krealloc(addr, newsize, KTAP_ALLOC_FLAGS);
+ if (new_addr)
+ break;
+ }
+ kp_printf(ks, "krealloc retry success after failed, exit\n");
+ }
+
+ preempt_disable();
+ if (oldsize == 0) {
+ KTAP_STATS(ks)->nr_mem_allocate += 1;
+ }
+ KTAP_STATS(ks)->mem_allocated += newsize - oldsize;
+ preempt_enable();
+
+ return new_addr;
+}
+
+void *kp_zalloc(ktap_state *ks, int size)
+{
+ void *addr;
+
+ addr = kzalloc(size, KTAP_ALLOC_FLAGS);
+ if (unlikely(!addr)) {
+ kp_error(ks, "kzalloc size %d failed, retry again\n", size);
+ printk("ktap kzalloc size %d failed, retry again\n", size);
+ dump_stack();
+ while (1) {
+ addr = kzalloc(size, KTAP_ALLOC_FLAGS);
+ if (addr)
+ break;
+ }
+ kp_printf(ks, "kzalloc retry success after failed, exit\n");
+ }
+
+ preempt_disable();
+ KTAP_STATS(ks)->nr_mem_allocate += 1;
+ KTAP_STATS(ks)->mem_allocated += size;
+ preempt_enable();
+
+ return addr;
+}
+#endif
+
+void kp_obj_dump(ktap_state *ks, const ktap_value *v)
+{
+ switch (ttype(v)) {
+ case KTAP_TNIL:
+ kp_puts(ks, "NIL");
+ break;
+ case KTAP_TNUMBER:
+ kp_printf(ks, "NUMBER %ld", nvalue(v));
+ break;
+ case KTAP_TBOOLEAN:
+ kp_printf(ks, "BOOLEAN %d", bvalue(v));
+ break;
+ case KTAP_TLIGHTUSERDATA:
+ kp_printf(ks, "LIGHTUSERDATA 0x%lx", (unsigned long)pvalue(v));
+ break;
+ case KTAP_TCFUNCTION:
+ kp_printf(ks, "LIGHTCFCUNTION 0x%lx", (unsigned long)fvalue(v));
+ break;
+ case KTAP_TSHRSTR:
+ case KTAP_TLNGSTR:
+ kp_printf(ks, "SHRSTR #%s", svalue(v));
+ break;
+ case KTAP_TTABLE:
+ kp_printf(ks, "TABLE 0x%lx", (unsigned long)hvalue(v));
+ break;
+ default:
+ kp_printf(ks, "GCVALUE 0x%lx", (unsigned long)gcvalue(v));
+ break;
+ }
+}
+
+#ifdef __KERNEL__
+#include <linux/stacktrace.h>
+#include <linux/module.h>
+#include <linux/kallsyms.h>
+
+static void kp_btrace_dump(ktap_state *ks, ktap_btrace *bt)
+{
+ char str[KSYM_SYMBOL_LEN];
+ unsigned long *entries = (unsigned long *)(bt + 1);
+ int i;
+
+ for (i = 0; i < bt->nr_entries; i++) {
+ unsigned long p = entries[i];
+
+ if (p == ULONG_MAX)
+ break;
+
+ SPRINT_SYMBOL(str, p);
+ kp_printf(ks, "%s\n", str);
+ }
+}
+
+static int kp_btrace_equal(ktap_btrace *bt1, ktap_btrace *bt2)
+{
+ unsigned long *entries1 = (unsigned long *)(bt1 + 1);
+ unsigned long *entries2 = (unsigned long *)(bt2 + 1);
+ int i;
+
+ if (bt1->nr_entries != bt2->nr_entries)
+ return 0;
+
+ for (i = 0; i < bt1->nr_entries; i++) {
+ if (entries1[i] != entries2[i])
+ return 0;
+ }
+
+ return 1;
+}
+#endif
+
+void kp_showobj(ktap_state *ks, const ktap_value *v)
+{
+ switch (ttype(v)) {
+ case KTAP_TNIL:
+ kp_puts(ks, "nil");
+ break;
+ case KTAP_TNUMBER:
+ kp_printf(ks, "%ld", nvalue(v));
+ break;
+ case KTAP_TBOOLEAN:
+ kp_puts(ks, (bvalue(v) == 1) ? "true" : "false");
+ break;
+ case KTAP_TLIGHTUSERDATA:
+ kp_printf(ks, "0x%lx", (unsigned long)pvalue(v));
+ break;
+ case KTAP_TCFUNCTION:
+ kp_printf(ks, "0x%lx", (unsigned long)fvalue(v));
+ break;
+ case KTAP_TSHRSTR:
+ case KTAP_TLNGSTR:
+ kp_puts(ks, svalue(v));
+ break;
+ case KTAP_TTABLE:
+ kp_tab_dump(ks, hvalue(v));
+ break;
+#ifdef __KERNEL__
+#ifdef CONFIG_KTAP_FFI
+ case KTAP_TCDATA:
+ kp_cdata_dump(ks, cdvalue(v));
+ break;
+#endif
+ case KTAP_TEVENT:
+ kp_transport_event_write(ks, evalue(v));
+ break;
+ case KTAP_TBTRACE:
+ kp_btrace_dump(ks, btvalue(v));
+ break;
+ case KTAP_TPTABLE:
+ kp_ptab_dump(ks, phvalue(v));
+ break;
+ case KTAP_TSTATDATA:
+ kp_statdata_dump(ks, sdvalue(v));
+ break;
+#endif
+ default:
+ kp_error(ks, "print unknown value type: %d\n", ttype(v));
+ break;
+ }
+}
+
+
+/*
+ * equality of ktap values. ks == NULL means raw equality
+ */
+int kp_equalobjv(ktap_state *ks, const ktap_value *t1, const ktap_value *t2)
+{
+ switch (ttype(t1)) {
+ case KTAP_TNIL:
+ return 1;
+ case KTAP_TNUMBER:
+ return nvalue(t1) == nvalue(t2);
+ case KTAP_TBOOLEAN:
+ return bvalue(t1) == bvalue(t2); /* true must be 1 !! */
+ case KTAP_TLIGHTUSERDATA:
+ return pvalue(t1) == pvalue(t2);
+ case KTAP_TCFUNCTION:
+ return fvalue(t1) == fvalue(t2);
+ case KTAP_TSHRSTR:
+ return eqshrstr(rawtsvalue(t1), rawtsvalue(t2));
+ case KTAP_TLNGSTR:
+ return kp_tstring_eqlngstr(rawtsvalue(t1), rawtsvalue(t2));
+ case KTAP_TTABLE:
+ if (hvalue(t1) == hvalue(t2))
+ return 1;
+ else if (ks == NULL)
+ return 0;
+#ifdef __KERNEL__
+ case KTAP_TBTRACE:
+ return kp_btrace_equal(btvalue(t1), btvalue(t2));
+#endif
+ default:
+ return gcvalue(t1) == gcvalue(t2);
+ }
+
+ return 0;
<