hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I7P697
Add wperf support for openeuler. This patch is from https://github.com/OSUSysLab/wPerf.git
Signed-off-by: Xiongfeng Wang wangxiongfeng2@huawei.com --- drivers/perf/Kconfig | 6 + drivers/perf/Makefile | 1 + drivers/perf/wperf.c | 2082 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 2089 insertions(+) create mode 100644 drivers/perf/wperf.c
diff --git a/drivers/perf/Kconfig b/drivers/perf/Kconfig index 1e82ab01e75f..ae7b398ab6e0 100644 --- a/drivers/perf/Kconfig +++ b/drivers/perf/Kconfig @@ -130,6 +130,12 @@ config ARM_SPE_PMU Extension, which provides periodic sampling of operations in the CPU pipeline and reports this via the perf AUX interface.
+config WPERF + tristate "Enable support for wPerf" + depends on ARM64 + help + Enable support for wPerf + source "drivers/perf/hisilicon/Kconfig"
endmenu diff --git a/drivers/perf/Makefile b/drivers/perf/Makefile index 5365fd56f88f..5afa723fe2d7 100644 --- a/drivers/perf/Makefile +++ b/drivers/perf/Makefile @@ -13,3 +13,4 @@ obj-$(CONFIG_QCOM_L3_PMU) += qcom_l3_pmu.o obj-$(CONFIG_THUNDERX2_PMU) += thunderx2_pmu.o obj-$(CONFIG_XGENE_PMU) += xgene_pmu.o obj-$(CONFIG_ARM_SPE_PMU) += arm_spe_pmu.o +obj-$(CONFIG_WPERF) += wperf.o diff --git a/drivers/perf/wperf.c b/drivers/perf/wperf.c new file mode 100644 index 000000000000..33ba6ff3e2b5 --- /dev/null +++ b/drivers/perf/wperf.c @@ -0,0 +1,2082 @@ +#include <linux/init.h> +//#include <linux/highmem.h> +#include <linux/export.h> +//#include <linux/swap.h> /* for totalram_pages */ +#include <linux/kprobes.h> +//#include <linux/bootmem.h> +#include <linux/interrupt.h> + +#include <linux/slab.h> +#include <linux/file.h> +#include <linux/syscalls.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/mm.h> +#include <linux/sched.h> +#include <linux/fs.h> // required for various structures related to files liked fops. +#include <linux/semaphore.h> +#include <linux/cdev.h> +#include <linux/vmalloc.h> +#include <linux/futex.h> +#include <linux/stop_machine.h> +#include <linux/genhd.h> +#include <linux/uio.h> +#include <asm/uaccess.h> +#include <asm/processor.h> +#include "ioctl_perf.h" + +#define BMAXBYTE 500 +#define BSIZEBYTE (BMAXBYTE-50) +#define BMAX (BMAXBYTE * 1024 * 1024) +#define BSIZE (BSIZEBYTE * 1024 * 1024) + +static int Major; +volatile int tag = -1; +volatile int step = -1; + +struct task_struct *p = NULL; + +unsigned long pid = -1; +unsigned long gdbpid = -1; +int ret; + +struct task_struct *ptmp; +struct task_struct *ttmp; +struct task_struct *t; + +char *switch_result; +char *switch_result_bak; +char *switch_result_tmp; +char *futex_result; +char *futex_result_bak; +char *futex_result_tmp; +char *state_result; +char *state_result_bak; +char *state_result_tmp; + +char *wait_result; +char *wait_result_bak; +char *wait_result_tmp; + +//New Added for missing event solution +volatile int ipnum = 0; +volatile int fnum = 0; +volatile int wnum = 0; +long switch_pos = 0; +long state_pos = 0; +long futex_pos = 0; +long wait_pos = 0; +int state_total = 0; +int futex_total = 0; +long tmpip; + +//For softirq events +u64 stime[NR_CPUS]; + +spinlock_t switch_lock; +spinlock_t state_lock; +spinlock_t futex_lock; +spinlock_t wait_lock; + +struct wperf_struct *perf_struct; + +struct task_struct *(*fang_curr_task)(int); +int (*fang_get_futex_key)(u32 __user *, int, union futex_key *, int); +struct futex_hash_bucket *(*fang_hash_futex)(union futex_key *); +static const struct futex_q futex_q_init = { + /* list gets initialized in queue_me()*/ + .key = FUTEX_KEY_INIT, + .bitset = FUTEX_BITSET_MATCH_ANY +}; +int (*fang_futex_wait_setup)(u32 __user *, u32, unsigned int, struct futex_q *, struct futex_hash_bucket **); +long (fang_futex_wait_restart)(struct restart_block *); +//For kernel version larger than 4.8 +//#ifdef NEWKERNEL +//u64 (*local_clock)(void); +//#endif + +long firstsec, firstusec, lastsec, lastusec; + +//Fang newly added +volatile int softirq[NR_CPUS]; +volatile int softirq1[NR_CPUS]; +#define HARDIRQ_SIZE 900 +volatile short hardirq[NR_CPUS][HARDIRQ_SIZE+1]; +volatile short hardirq_pos[NR_CPUS]; +volatile int irq[NR_CPUS]; +volatile int target[PIDNUM]; +volatile int aiotag[NR_CPUS]; +#define NETSEND_SIZE 655350 +long netsend[NETSEND_SIZE+1]; +//long futextag[65535]; +//long futexsum[65535]; +//long futexstart[65535]; +struct fang_result spin_result[NR_CPUS]; + +//Only for test +//volatile short dump_check[100000]; +//volatile short dump_cpu_check[32]; + +volatile long futex_to = 0; +volatile long futex_noto = 0; + +//static long disk_work = 0; + +int dnum; +char dname[200][200]; +long disk_work[200]; + +/*static __inline__ unsigned long long tsc_now(void) +{ + unsigned hi, lo; + __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi)); + return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 ); +}*/ + +inline u64 fang_clock(void) { + struct timespec64 now; + u64 ret = 0; + + //getnstimeofday64(&now); + //get_monotonic_boottime(&now); + + //ret = now.tv_sec*1000000000+now.tv_nsec; + + //ret = tsc_now(); + ret = ktime_get(); + //printk(KERN_INFO "current time = %lu\n", ret); + return ret; +} + +inline u64 wperfclock(void) { + //struct timespec64 now; + //u64 ret = 0; + + //getrawmonotonic(&now); + //ret = now.tv_sec*1000000000+now.tv_nsec; + + //return ret; + //return local_clock(); + return ktime_get(); +} + +//We'll check target ID & jbd thread & ksoftirq threads +int containOfPID(int core, int pid) { + int i = 0; + for (i = 0; i < PIDNUM; i++) { + if (target[i] == 0) break; + if (target[i] == pid) + return 1; + } + //if (target[0] == pid) { + // return 1; + //} + //if (target[1] == pid) { + // return 1; + //} + //if (target[2+core] == pid) { + // return 1; + //} + return 0; +} + +__visible __notrace_funcgraph int j___switch_to(struct kprobe *p, struct pt_regs *regs) { + //struct timeval start; + struct task_struct *prev_p = regs->regs[0]; + struct task_struct *next_p = regs->regs[1]; + struct fang_result fresult; + struct futex_result furesult; + char *chartmp; + int cpu = 0; + u64 ts; + + if (step == 1) { + cpu = smp_processor_id(); + if (containOfPID(cpu, prev_p->tgid)||containOfPID(cpu, next_p->tgid)) { + ts = fang_clock(); + fresult.type = 0; + fresult.ts = ts; + fresult.perfts = wperfclock(); + fresult.core = cpu; + fresult.pid1 = prev_p->pid; + fresult.pid2 = next_p->pid; + trace_printk("switch to prev %s next %s\n", prev_p->comm, next_p->comm); + + if (in_irq()) { + //fresult.irq = hardirq[cpu][hardirq_pos[cpu]]; + fresult.irq = HARDIRQ; + } + else if (in_serving_softirq()) { + fresult.irq = softirq[cpu]; + } + else { + fresult.irq = 0; + } + fresult.pid1state = prev_p->state; + fresult.pid2state = next_p->state; + + //if (prev_p->pid == 18183) { + // printk(KERN_INFO "pid1 = %d, pid2 = %d, pid1state = %d, pid2state = %d\n", prev_p->pid, next_p->pid, prev_p->state, next_p->state); + //} + + spin_lock(&switch_lock); + chartmp = (char *)(switch_result + switch_pos); + memcpy(chartmp, &fresult, sizeof(fresult)); + switch_pos+=sizeof(fresult); + if (switch_pos >= BSIZE) + pr_info("fresult exceed !!!!!!!!!\n"); + spin_unlock(&switch_lock); + + //if (futextag[next_p->pid] == 1) { + // futexstart[next_p->pid] = ts; + // //printk(KERN_INFO "pid=%d, ts=%ld\n", next_p->pid, futexstart[prev_p->pid]); + //} + //if (futextag[prev_p->pid] == 1 && futexstart[prev_p->pid] > 0) { + // futexsum[prev_p->pid] += ts - futexstart[prev_p->pid]; + + // if (prev_p->state>0) { + // spin_lock(&state_lock); + // chartmp = (char *)(state_result + state_pos); + // furesult.pid = prev_p->pid; + // furesult.time = futexsum[prev_p->pid]; + // memcpy(chartmp, &furesult, sizeof(furesult)); + // state_pos+=sizeof(furesult); + // futexsum[prev_p->pid] = 0; + // futextag[prev_p->pid] = 0; + // futexstart[prev_p->pid] = 0; + // spin_unlock(&state_lock); + // } + //} + } + } + //return 0; + return 0; +} + +/* We need this jprobe by both steps + * First, we need to record the time entry in the first step. + * Second, we need to record the last state for GDB stack. + * */ + +static int j_try_to_wake_up(struct kprobe *kp, struct pt_regs *regs) { + struct task_struct *p = regs->regs[0]; + unsigned int state = regs->regs[1]; + int wake_flags = regs->regs[2]; + char tmp[200]; + //struct timeval start; + struct fang_result fresult; + char *chartmp = NULL; + int cpu = 0; + int i = 0; + u64 ts; + + if (step == 1) { + //if (p->pid==p->tgid+8) { + // printk(KERN_INFO "Thread %d wakes up IO thread\n", current->pid); + // dump_stack(); + // if (aiotag[cpu] == 1) { + // aiotag = 0; + // printk(KERN_INFO "Thread %d is waken up by aio_complete\n", p->pid); + // } + //} + //if (p->tgid == target[1]) { + // if (in_serving_softirq()) { + // printk(KERN_INFO "It's in softirq context\n"); + // } + // else { + // printk(KERN_INFO "It's NOT in softirq context\n"); + // dump_stack(); + // printk(KERN_INFO "------------------------\n"); + // } + //} + //if (current->pid == 4145 && p->pid == 4144) dump_stack(); + //if (p->pid == 4145) dump_stack(); + cpu = smp_processor_id(); + //if (containOfPID(cpu, p->tgid) ) { + //if (current->pid == 2381) dump_stack(); + if (containOfPID(cpu, p->tgid)) { + // Check if in hardirq context + //if (in_irq() && hardirq_pos[cpu]<=0) { + // printk(KERN_INFO "[cpu %d][hardirq_pos = %d] hardirq missing, %d wakes up %d\n", cpu, hardirq_pos[cpu], current->pid, p->pid); + // dump_stack(); + //} + //else if (in_serving_softirq() && softirq1[cpu] == 0) { + // printk(KERN_INFO "softirq missing, %d wakes up %d\n", current->pid, p->pid); + // dump_stack(); + //} + + //if (current->pid == target[cpu+2] && p->pid == 376) { + // dump_stack(); + //} + + if ((p->state & state)) { + //if (current->pid != 0 && current->tgid != target[0] && p->pid == 1935) { + //printk(KERN_INFO "%d [parent %d] wakes up %d\n", current->pid, current->tgid, p->pid); + //} + //if (aiotag[cpu] == 1) { + // aiotag[p->pid] = 1; + // aiotag[cpu] = 0; + //} + + ts = fang_clock(); + + fresult.type = 1; + fresult.ts = ts; + fresult.perfts = wperfclock(); + fresult.core = cpu; + fresult.pid1 = current->pid; + fresult.pid2 = p->pid; + trace_printk("try to wakeup cur %s next %s\n", current->comm, p->comm); + if (in_irq()) { + fresult.irq = HARDIRQ; + //dump_check[p->pid] ++; + //if (dump_check[p->pid] == 10) { + // dump_cpu_check[cpu] = p->pid; + // dump_check[p->pid]=0; + //} + } + else if (in_serving_softirq()) { + fresult.irq = softirq[cpu]; + //if (softirq[cpu] == -2 && p->pid == 4145) dump_stack(); + } + else { + fresult.irq = 0; + // Added for futex Result + //futextag[p->pid] = 1; + } + + fresult.pid1state = current->state; + fresult.pid2state = p->state; + + spin_lock(&switch_lock); + chartmp = (char *)(switch_result + switch_pos); + memcpy(chartmp, &fresult, sizeof(fresult)); + switch_pos+=sizeof(fresult); + if (switch_pos >= BSIZE) + pr_info("fresult2 exceed !!!!!!!!!\n"); + spin_unlock(&switch_lock); + } + } + } + +// return 0; + return 0; +} + +static int j_tasklet_hi_action(struct kprobe *p, struct pt_regs *regs) { + struct softirq_action *a = regs->regs[0]; + int cpu = 0; + if (step == 1) { + cpu = smp_processor_id(); + softirq[cpu] = TASKLET_HI; + } + //return 0; + return 0; +} + +static int j_run_timer_softirq(struct kprobe *p, struct pt_regs *regs) { + struct softirq_action *a = regs->regs[0]; + int cpu = 0; + if (step == 1) { + cpu = smp_processor_id(); + softirq[cpu] = TIMER; + } + //return 0; + return 0; +} + +static int j_net_tx_action(struct kprobe *p, struct pt_regs *regs) { + struct softirq_action *a = regs->regs[0]; + int cpu = 0; + if (step == 1) { + cpu = smp_processor_id(); + softirq[cpu] = NET_TX; + } + //return 0; + return 0; +} + +static int j_net_rx_action(struct kprobe *p, struct pt_regs *regs) { + struct softirq_action *a = regs->regs[0]; + int cpu = 0; + if (step == 1) { + cpu = smp_processor_id(); + softirq[cpu] = NET_RX; + //if (cpu == 7) { + // printk(KERN_INFO "[%d]softirq[cpu] = %d\n", cpu, softirq[cpu]); + //} + } + //return 0; + return 0; +} + +static int j_blk_done_softirq(struct kprobe *p, struct pt_regs *regs) { + struct softirq_action *a = regs->regs[0]; + int cpu = 0; + if (step == 1) { + cpu = smp_processor_id(); + softirq[cpu] = BLK_DONE; + } + //return 0; + return 0; +} + +static int j_blk_iopoll_softirq(struct kprobe *p, struct pt_regs *regs) { + struct softirq_action *a = regs->regs[0]; + int cpu = 0; + if (step == 1) { + cpu = smp_processor_id(); + softirq[cpu] = BLK_IOPOLL; + } + //return 0; + return 0; +} + +static int j_tasklet_action(struct kprobe *p, struct pt_regs *regs) { + struct softirq_action *a = regs->regs[0]; + int cpu = 0; + if (step == 1) { + cpu = smp_processor_id(); + softirq[cpu] = TASKLET; + } + //return 0; + return 0; +} + +static int j_run_rebalance_domains(struct kprobe *p, struct pt_regs *regs) { + struct softirq_action *a = regs->regs[0]; + int cpu = 0; + if (step == 1) { + cpu = smp_processor_id(); + softirq[cpu] = SCHED; + } + //return 0; + return 0; +} + +static int j_run_hrtimer_softirq(struct kprobe *p, struct pt_regs *regs) { + struct softirq_action *a = regs->regs[0]; + int cpu = 0; + if (step == 1) { + cpu = smp_processor_id(); + softirq[cpu] = HRTIMER; + } + //return 0; + return 0; +} + +//rcu moved from softirq to kthread +static int j_rcu_process_callbacks(struct kprobe *p, struct pt_regs *regs) { + struct softirq_action *a = regs->regs[0]; + int cpu = 0; + if (step == 1) { + cpu = smp_processor_id(); + softirq[cpu] = RCU; + } + //return 0; + return 0; +} + +//void j_hrtimer_interrupt(void) { +int j_local_apic_timer_interrupt(struct kprobe *p, struct pt_regs *regs) { + int cpu = 0; + int vector = 0; + if (step == 1) { + // Get information for do_IRQ + vector = APICTIMER; + cpu = smp_processor_id(); + + hardirq[cpu][hardirq_pos[cpu]] = vector; + hardirq_pos[cpu]+=1; + //printk(KERN_INFO "[%d] local_apic_timer starts\n", cpu); + //printk(KERN_INFO "hardirq[%d] = %d, hardirq_pos[%d] = %d\n", cpu, hardirq[cpu][hardirq_pos[cpu]], cpu, hardirq_pos[cpu]); + } + return 0; +} + +int j_do_IRQ(struct kprobe *p, struct pt_regs *regs) { + int cpu = 0; + int vector = 0; + if (step == 1) { + // Get information for do_IRQ +// vector = ~regs->orig_ax; + cpu = smp_processor_id(); + + hardirq[cpu][hardirq_pos[cpu]] = vector; + hardirq_pos[cpu]+=1; + //printk(KERN_INFO "[%d] local_apic_timer starts\n", cpu); + //printk(KERN_INFO "hardirq[%d] = %d, hardirq_pos[%d] = %d\n", cpu, hardirq[cpu][hardirq_pos[cpu]], cpu, hardirq_pos[cpu]); + } + return 0; + return 0; +} + +int j__handle_domain_irq(struct kprobe *p, struct pt_regs *regs) { + int cpu = 0; + int vector = 0; + unsigned int hwirq = regs->regs[1]; + if (step == 1) { + // Get information for do_IRQ +// vector = ~regs->orig_ax; + cpu = smp_processor_id(); + + hardirq[cpu][hardirq_pos[cpu]] = hwirq; + hardirq_pos[cpu]+=1; + if (hardirq_pos[cpu] >= HARDIRQ_SIZE) + pr_info("hardirq pos overflow !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); + //printk(KERN_INFO "[%d] local_apic_timer starts\n", cpu); + //printk(KERN_INFO "hardirq[%d] = %d, hardirq_pos[%d] = %d\n", cpu, hardirq[cpu][hardirq_pos[cpu]], cpu, hardirq_pos[cpu]); + } + return 0; + return 0; +} + +int j_do_handle_IPI(struct kprobe *p, struct pt_regs *regs) { + int cpu = 0; + int vector = 0; + int ipinr = regs->regs[0]; + if (step == 1) { + // Get information for do_IRQ +// vector = ~regs->orig_ax; + cpu = smp_processor_id(); + + hardirq[cpu][hardirq_pos[cpu]] = ipinr; + hardirq_pos[cpu]+=1; + if (hardirq_pos[cpu] >= HARDIRQ_SIZE) + pr_info("hardirq pos overflow !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); + //printk(KERN_INFO "[%d] local_apic_timer starts\n", cpu); + //printk(KERN_INFO "hardirq[%d] = %d, hardirq_pos[%d] = %d\n", cpu, hardirq[cpu][hardirq_pos[cpu]], cpu, hardirq_pos[cpu]); + } + return 0; + return 0; +} + +static int j_aio_complete(struct kprobe *p, struct pt_regs *regs) { + int cpu = smp_processor_id(); + aiotag[cpu] = 1; + //return 0; + return 0; +} + +static int j_wakeup_softirqd(struct kprobe *p, struct pt_regs *regs) { + int cpu = 0; + if (step == 1) { + cpu = smp_processor_id(); + softirq[cpu] = KSOFTIRQ; + } + //return 0; + return 0; +} + +static struct kprobe jp1 = { + .pre_handler = j___switch_to, + .symbol_name = "__switch_to", +}; + +static struct kprobe jp2 = { + .pre_handler = j_try_to_wake_up, + .symbol_name = "try_to_wake_up", +}; + +static struct kprobe jp3 = { + .pre_handler = j_tasklet_hi_action, + .symbol_name = "tasklet_hi_action", +}; + +static struct kprobe jp4 = { + .pre_handler = j_run_timer_softirq, + .symbol_name = "run_timer_softirq", +}; + +static struct kprobe jp5 = { + .pre_handler = j_net_tx_action, + .symbol_name = "net_tx_action", +}; + +static struct kprobe jp6 = { + .pre_handler = j_net_rx_action, + .symbol_name = "net_rx_action", +}; + +static struct kprobe jp7 = { + .pre_handler = j_blk_done_softirq, + .symbol_name = "blk_done_softirq", +}; + +static struct kprobe jp8 = { + .pre_handler = j_blk_iopoll_softirq, + .symbol_name = "irq_poll_softirq", +}; + +static struct kprobe jp9 = { + .pre_handler = j_tasklet_action, + .symbol_name = "tasklet_action", +}; + +static struct kprobe jp10 = { + .pre_handler = j_run_rebalance_domains, + .symbol_name = "run_rebalance_domains", +}; + +static struct kprobe jp11 = { + .pre_handler = j_run_hrtimer_softirq, + .symbol_name = "run_hrtimer_softirq", +}; + +static struct kprobe jp12 = { + .pre_handler = j_rcu_process_callbacks, + .symbol_name = "rcu_process_callbacks", +}; + +// For Local APIC Timer Interrupt +/*static struct kprobe jp13 = { + .pre_handler = j_local_apic_timer_interrupt, + .symbol_name = "local_apic_timer_interrupt", +}; + +// For HardIRQ +static struct kprobe jp14 = { + .pre_handler = j_do_IRQ, + .symbol_name = "do_IRQ", +};*/ + +static struct kprobe jp13 = { + .pre_handler = j__handle_domain_irq, + .symbol_name = "__handle_domain_irq", +}; + +// For HardIRQ +static struct kprobe jp14 = { + .pre_handler = j_do_handle_IPI, + .symbol_name = "do_handle_IPI", +}; +//static struct kprobe jp15 = { +// .pre_handler = j_aio_complete, +// .kp = { +// .symbol_name = "aio_complete", +// }, +//}; +// For ksoftirq waking up +//static struct kprobe jp15 = { +// .pre_handler = j_wakeup_softirqd, +// .kp = { +// .symbol_name = "wakeup_softirqd", +// }, +//}; + + +// Add it temporarily for do_softirq +static int j___do_softirq(struct kprobe *p, struct pt_regs *regs) { + int cpu = 0; + u64 ts; + char *chartmp; + struct softirq_result sr; + if (step == 1) { + cpu = smp_processor_id(); + ts = fang_clock(); + spin_lock(&futex_lock); + stime[cpu] = ts; + spin_unlock(&futex_lock); + } + //return 0; + return 0; +} + +static struct kprobe jp16 = { + .pre_handler = j___do_softirq, + .symbol_name = "__do_softirq", +}; + +int j_add_interrupt_randomness(struct kprobe *p, struct pt_regs *regs) { + int cpu = 0; + int vector = 0; + if (step == 1) { + cpu = smp_processor_id(); + + hardirq[cpu][hardirq_pos[cpu]] = RANDOM; + hardirq_pos[cpu]+=1; + if (hardirq_pos[cpu] >= HARDIRQ_SIZE) + pr_info("hardirq pos overflow !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); + //printk(KERN_INFO "[%d] local_apic_timer starts\n", cpu); + //printk(KERN_INFO "hardirq[%d] = %d, hardirq_pos[%d] = %d\n", cpu, hardirq[cpu][hardirq_pos[cpu]], cpu, hardirq_pos[cpu]); + } + return 0; +} + +// Special case for add_interrupt_randomness +static struct kprobe jp17 = { + .pre_handler = j_add_interrupt_randomness, + .symbol_name = "add_interrupt_randomness", +}; + + +inline int compareDisk(const char *dname_tmp) { + int i = 0; + for (; i < dnum; i++) { + if (strcmp(dname_tmp, dname[i]) == 0) { + return i; + } + } + return -1; +} + +#ifdef NEWKERNEL +static int j_part_round_stats(struct kprobe *p, struct pt_regs *regs) { + //return 0; + return 0; +} +#else +static void old_part_round_stats_single(struct hd_struct *part, unsigned long now) { + int inflight; + const char *dname_tmp = NULL; + struct device *ddev = NULL; + int pos = 0; + + ddev = part_to_dev(part); + dname_tmp = dev_name(ddev); + + pos = compareDisk(dname_tmp); + + if (pos >= 0) { + if (now == part->stamp) { + } + else { + inflight = part_in_flight(part); + if (inflight) { + disk_work[pos] += now - part->stamp; + } + } + } +} + +static void j_part_round_stats(int cpu, struct hd_struct *part) { + unsigned long now = jiffies; + + if (step == 1) { + if (part->partno) { + old_part_round_stats_single(&part_to_disk(part)->part0, now); + } + old_part_round_stats_single(part, now); + } + return 0; +} +#endif +/* +static void j_part_round_stats_single(int cpu, struct hd_struct *part, unsigned long now) { + int inflight; + const char *dname_tmp = NULL; + struct device *ddev = NULL; + int pos = 0; + + if (step == 1) { + ddev = part_to_dev(part); + dname_tmp = dev_name(ddev); + + pos = compareDisk(dname_tmp); + if (pos >= 0) { + if (now == part->stamp) { + } + else { + #ifndef NEWKERNEL + inflight = part_in_flight(part); + #endif + if (inflight) { + disk_work[pos] += now - part->stamp; + //spin_lock(&futex_lock); + //sr.type = 1; + //sr.stime = part->stamp; + //sr.etime = now; + //sr.core = cpu; + //chartmp = (char *)(futex_result + futex_pos); + //memcpy(chartmp, &sr, sizeof(sr)); + //futex_pos+=sizeof(sr); + //spin_unlock(&futex_lock); + } + } + } + } + return 0; +} +*/ +static struct kprobe jp18 = { + .pre_handler = j_part_round_stats, + .symbol_name = "part_round_stats", +}; + +static int j_futex_wait_queue_me(struct kprobe *p, struct pt_regs *regs) { + struct futex_hash_bucket *hb = regs->regs[0]; + struct futex_q *q = regs->regs[1]; + struct hrtimer_sleeper *timeout = regs->regs[2]; + struct fang_uds fuds; + char *chartmp = NULL; + if (step == 1) { + if (current->tgid==target[0]) { + fuds.ts = fang_clock(); + fuds.pid = current->pid; + fuds.type = 1; + + spin_lock(&wait_lock); + chartmp = (char *)(wait_result + wait_pos); + memcpy(chartmp, &fuds, sizeof(fuds)); + wait_pos+=sizeof(fuds); + spin_unlock(&wait_lock); + } + } + //return 0; + return 0; +} + +static struct kprobe jp19 = { + .pre_handler = j_futex_wait_queue_me, + .symbol_name = "futex_wait_queue_me", +}; + +static int j_journal_end_buffer_io_sync(struct kprobe *p, struct pt_regs *regs) { + printk(KERN_INFO "I/O sync is happended in softirq context? %s", in_serving_softirq()>0?"True":"False"); + return 0; + //return 0; +} + +static struct kprobe jp20 = { + .pre_handler = j_journal_end_buffer_io_sync, + .symbol_name = "journal_end_buffer_io_sync", +}; + +int j_wake_up_new_task(struct kprobe *kp, struct pt_regs *regs) { + struct task_struct *p = regs->regs[0]; + if (step == 1) { + if (p->tgid == target[0]) { + u64 ts = fang_clock(); + int cpu = smp_processor_id(); + struct fang_result fresult; + char *chartmp = NULL; + fresult.type = 2; + fresult.ts = ts; + fresult.perfts = wperfclock(); + fresult.core = cpu; + fresult.pid1 = current->pid; + fresult.pid2 = p->pid; + fresult.pid1state = current->state; + fresult.pid2state = p->state; + trace_printk("wake up new cur %s next %s\n", current->comm, p->comm); + + spin_lock(&switch_lock); + chartmp = (char *)(switch_result + switch_pos); + memcpy(chartmp, &fresult, sizeof(fresult)); + switch_pos+=sizeof(fresult); + spin_unlock(&switch_lock); + + printk(KERN_INFO "[Create] Thread %d creates thread %d time %lld\n", current->pid, p->pid, ts); + trace_printk("create cur %s p %s\n", current->comm, p->comm); + } + } + return 0; +} + +static struct kprobe jp21 = { + .pre_handler = j_wake_up_new_task, + .symbol_name = "wake_up_new_task", +}; + +int j_do_exit(struct kprobe *p, struct pt_regs *regs) { + if (step == 1) { + if (current->tgid == target[0]) { + u64 ts = fang_clock(); + int cpu = smp_processor_id(); + char *chartmp = NULL; + struct fang_result fresult; + fresult.type = 3; + fresult.ts = ts; + fresult.perfts = wperfclock(); + fresult.core = cpu; + fresult.pid1 = current->pid; + fresult.pid2 = 0; + fresult.pid1state = current->state; + fresult.pid2state = 0; + + spin_lock(&switch_lock); + chartmp = (char *)(switch_result + switch_pos); + memcpy(chartmp, &fresult, sizeof(fresult)); + switch_pos+=sizeof(fresult); + spin_unlock(&switch_lock); + + printk(KERN_INFO "[Finish] Thread %d finishes time %lld\n", current->pid, ts); + } + } + return 0; +} + +static struct kprobe jp22 = { + .pre_handler = j_do_exit, + .symbol_name = "do_exit", +}; + +int j_tcp_sendmsg(struct kprobe *p, struct pt_regs *regs) { + struct sock *sk = regs->regs[0]; + struct msghdr *msg = regs->regs[1]; + if (step == 1) { + if (containOfPID(0, current->tgid)) { + if (current->pid >= NETSEND_SIZE) + pr_info("netsend overflow !!!!!!!!!!!!!!!!!!!!!!!!!!\n"); + netsend[current->pid] += (&msg->msg_iter)->count; + } + } + return 0; + return 0; +} + +static struct kprobe jp26 = { + .pre_handler = j_tcp_sendmsg, + .symbol_name = "tcp_sendmsg", +}; + + +int j_udp_sendmsg(struct kprobe *p, struct pt_regs *regs) { + struct sock *sk = regs->regs[0]; + struct msghdr *msg = regs->regs[1]; + if (step == 1) { + if (containOfPID(0, current->tgid)) { + if (current->pid >= NETSEND_SIZE) + pr_info("netsend overflow !!!!!!!!!!!!!!!!!!!!!!!!!!\n"); + netsend[current->pid] += (&msg->msg_iter)->count; + } + } + return 0; + return 0; +} + +static struct kprobe jp27 = { + .pre_handler = j_udp_sendmsg, + .symbol_name = "udp_sendmsg", +}; + +int j_tcp_sendpage(struct kprobe *p, struct pt_regs *regs) { + struct sock *sk = regs->regs[0]; + struct page *page = regs->regs[1]; + int offset = regs->regs[2]; + size_t size = regs->regs[3]; + if (step == 1) { + if (containOfPID(0, current->tgid)) { + if (current->pid >= NETSEND_SIZE) + pr_info("netsend overflow !!!!!!!!!!!!!!!!!!!!!!!!!!\n"); + netsend[current->pid] += size; + } + } + return 0; + return 0; +} + +static struct kprobe jp28 = { + .pre_handler = j_tcp_sendpage, + .symbol_name = "tcp_sendpage", +}; + +int j_udp_sendpage(struct kprobe *p, struct pt_regs *regs) { + struct sock *sk = regs->regs[0]; + struct page *page = regs->regs[1]; + int offset = regs->regs[2]; + size_t size = regs->regs[3]; + if (step == 1) { + if (containOfPID(0, current->tgid)) { + if (current->tgid >= NETSEND_SIZE) + pr_info("netsend overflow !!!!!!!!!!!!!!!!!!!!!!!!!!\n"); + netsend[current->pid] += size; + } + } + return 0; + return 0; +} + +static struct kprobe jp29 = { + .pre_handler = j_udp_sendpage, + .symbol_name = "udp_sendpage", +}; + + +int j_sock_sendmsg(struct kprobe *p, struct pt_regs *regs) { + struct socket *sock = regs->regs[0]; + struct msghdr *msg = regs->regs[1]; + //struct fang_uds fuds; + //char *chartmp = NULL; + if (step == 1) { + if (containOfPID(0, current->tgid)) { + if (current->pid >= NETSEND_SIZE) + pr_info("netsend overflow !!!!!!!!!!!!!!!!!!!!!!!!!!\n"); + netsend[current->pid] += (&msg->msg_iter)->count; + + //fuds.ts = fang_clock(); + //fuds.pid = current->pid; + //fuds.type = 2; + + //spin_lock(&wait_lock); + //chartmp = (char *)(wait_result + wait_pos); + //memcpy(chartmp, &fuds, sizeof(fuds)); + //wait_pos+=sizeof(fuds); + //spin_unlock(&wait_lock); + } + } + return 0; + return 0; +} + +static struct kprobe jp23 = { + .pre_handler = j_sock_sendmsg, + .symbol_name = "sock_sendmsg", +}; + +static long j_futex_wait_restart(struct kprobe *p, struct pt_regs *regs) { + if (step == 1) { + printk(KERN_INFO "Core %d Thread %d futex_wait_restart Time %llu\n", smp_processor_id(), current->pid, fang_clock()); + } + return 0; + return 0; +} + +int j_do_futex(struct kprobe *p, struct pt_regs *regs) { +// u32 __user *uaddr, int op, u32 val, ktime_t *timeout, +// u32 __user *uaddr2, u32 val2, u32 val3) { +//static int j_futex_wake(u32 __user *uaddr, unsigned int flags, int nr_wake, u32 bitset) { + struct fang_uds fuds; + char *chartmp = NULL; + if (step == 1) { + if (current->tgid==target[0]) { + fuds.ts = fang_clock(); + fuds.pid = current->pid; + fuds.type = 1; + + spin_lock(&wait_lock); + chartmp = (char *)(wait_result + wait_pos); + memcpy(chartmp, &fuds, sizeof(fuds)); + wait_pos+=sizeof(fuds); + spin_unlock(&wait_lock); + } + } + return 0; + return 0; +} + +static struct kprobe jp24 = { + //.pre_handler = j_futex_wake, + .pre_handler = j_do_futex, + .symbol_name = "do_futex", + //.addr = (kprobe_opcode_t *) kallsyms_lookup_name("futex_wait_restart"), +}; + +static int j___lock_sock(struct kprobe *p, struct pt_regs *regs) { + struct fang_uds fuds; + char *chartmp = NULL; + if (step == 1) { + if (current->tgid==target[0]) { + fuds.ts = fang_clock(); + fuds.pid = current->pid; + fuds.type = 3; + + spin_lock(&wait_lock); + chartmp = (char *)(wait_result + wait_pos); + memcpy(chartmp, &fuds, sizeof(fuds)); + wait_pos+=sizeof(fuds); + spin_unlock(&wait_lock); + } + } + return 0; +} +static struct kprobe jp25 = { + //.pre_handler = j_futex_wake, + .pre_handler = j___lock_sock, + .symbol_name = "__lock_sock", + //.addr = (kprobe_opcode_t *) kallsyms_lookup_name("futex_wait_restart"), +}; + + + + +int open(struct inode *inode, struct file *filp) +{ + trace_printk("inside open\n"); + printk(KERN_INFO "Inside open %llu\n", fang_clock()); + return 0; +} + +int release(struct inode *inode, struct file *filp) { + int i = 0; + printk (KERN_INFO "Inside close %llu\n", fang_clock()); + for (i = 0; i < dnum; i++) { + printk(KERN_INFO "Disk %s work time: %ld\n", dname[i], disk_work[i]); + } + for (i = 0; i < NETSEND_SIZE; i++) { + if (netsend[i] != 0) { + printk(KERN_INFO "Thread %d sends bytes: %ld\n",i, netsend[i]); + } + } + +// printk(KERN_INFO "futex with timeout: %ld\n", futex_to); +// printk(KERN_INFO "futex without timeout: %ld\n", futex_noto); + + return 0; +} + +static int tasklet_hi_return(struct kretprobe_instance *ri, struct pt_regs *regs) +{ + int cpu = 0; + if (step == 1) { + cpu = smp_processor_id(); + softirq[cpu] = 0; + } + return 0; +} + +static struct kretprobe kret3 = { + .handler = tasklet_hi_return, + .maxactive = NR_CPUS, + .kp = { .symbol_name = "tasklet_hi_action", }, + //.maxactive = MAX_CPU_NR, +}; + +static int timer_return(struct kretprobe_instance *ri, struct pt_regs *regs) +{ + int cpu = 0; + if (step == 1) { + cpu = smp_processor_id(); + softirq[cpu] = 0; + } + return 0; +} + +static struct kretprobe kret4 = { + .handler = timer_return, + .maxactive = NR_CPUS, + .kp = { .symbol_name = "run_timer_softirq", }, + //.maxactive = MAX_CPU_NR, +}; + +static int net_tx_return(struct kretprobe_instance *ri, struct pt_regs *regs) +{ + int cpu = 0; + if (step == 1) { + cpu = smp_processor_id(); + softirq[cpu] = 0; + } + return 0; +} + +static struct kretprobe kret5 = { + .handler = net_tx_return, + .maxactive = NR_CPUS, + .kp = { .symbol_name = "net_tx_action", }, + //.maxactive = MAX_CPU_NR, +}; + +static int net_rx_return(struct kretprobe_instance *ri, struct pt_regs *regs) +{ + int cpu = 0; + if (step == 1) { + cpu = smp_processor_id(); + softirq[cpu] = 0; + //if (cpu == 7) { + // printk(KERN_INFO "[%d]softirq[cpu] = %d\n", cpu, softirq[cpu]); + //} + } + return 0; +} + +static struct kretprobe kret6 = { + .handler = net_rx_return, + .maxactive = NR_CPUS, + .kp = { .symbol_name = "net_rx_action", }, + //.maxactive = MAX_CPU_NR, +}; + +static int blk_done_return(struct kretprobe_instance *ri, struct pt_regs *regs) +{ + int cpu = 0; + if (step == 1) { + cpu = smp_processor_id(); + softirq[cpu] = 0; + } + return 0; +} + +static struct kretprobe kret7 = { + .handler = blk_done_return, + .maxactive = NR_CPUS, + .kp = { .symbol_name = "blk_done_softirq", }, + //.maxactive = MAX_CPU_NR, +}; + +static int blk_iopoll_return(struct kretprobe_instance *ri, struct pt_regs *regs) +{ + int cpu = 0; + if (step == 1) { + cpu = smp_processor_id(); + softirq[cpu] = 0; + } + return 0; +} + +static struct kretprobe kret8 = { + .handler = blk_iopoll_return, + .maxactive = NR_CPUS, + .kp = { .symbol_name = "irq_poll_softirq", }, + //.maxactive = MAX_CPU_NR, +}; + +static int tasklet_return(struct kretprobe_instance *ri, struct pt_regs *regs) +{ + int cpu = 0; + if (step == 1) { + cpu = smp_processor_id(); + softirq[cpu] = 0; + } + return 0; +} + +static struct kretprobe kret9 = { + .handler = tasklet_return, + .maxactive = NR_CPUS, + .kp = { .symbol_name = "tasklet_action", }, + //.maxactive = MAX_CPU_NR, +}; + +static int sched_return(struct kretprobe_instance *ri, struct pt_regs *regs) +{ + int cpu = 0; + if (step == 1) { + cpu = smp_processor_id(); + softirq[cpu] = 0; + } + return 0; +} + +static struct kretprobe kret10 = { + .handler = sched_return, + .maxactive = NR_CPUS, + .kp = { .symbol_name = "run_rebalance_domains", }, + //.maxactive = MAX_CPU_NR, +}; + +static int hrtimer_return(struct kretprobe_instance *ri, struct pt_regs *regs) +{ + int cpu = 0; + if (step == 1) { + cpu = smp_processor_id(); + softirq[cpu] = 0; + } + return 0; +} + +static struct kretprobe kret11 = { + .handler = hrtimer_return, + .maxactive = NR_CPUS, + .kp = { .symbol_name = "run_hrtimer_softirq", }, + //.maxactive = MAX_CPU_NR, +}; + +static int rcu_return(struct kretprobe_instance *ri, struct pt_regs *regs) +{ + int cpu = 0; + if (step == 1) { + cpu = smp_processor_id(); + softirq[cpu] = 0; + } + return 0; +} + +static struct kretprobe kret12 = { + .handler = rcu_return, + .maxactive = NR_CPUS, + .kp = { .symbol_name = "rcu_process_callbacks", }, + //.maxactive = MAX_CPU_NR, +}; + +static int handle_domain_irq_return(struct kretprobe_instance *ri, struct pt_regs *regs) +{ + int cpu = 0; + if (step == 1) { + cpu = smp_processor_id(); + if (hardirq_pos[cpu] != 0) hardirq_pos[cpu]-=1; + //printk(KERN_INFO "[%d] local_apic_timer ends\n", cpu); + //printk(KERN_INFO "hardirq_pos[%d] = %d\n", cpu, hardirq_pos[cpu]); + } + return 0; +} + +static struct kretprobe kret13 = { + .handler = handle_domain_irq_return, + .maxactive = NR_CPUS, + .kp = { .symbol_name = "__handle_domain_irq", }, + //.maxactive = 1024, +}; + +static int do_handle_IPI_return(struct kretprobe_instance *ri, struct pt_regs *regs) +{ + int cpu = 0; + if (step == 1) { + cpu = smp_processor_id(); + if (hardirq_pos[cpu] != 0) hardirq_pos[cpu]-=1; + //printk(KERN_INFO "[%d] local_apic_timer ends\n", cpu); + //printk(KERN_INFO "hardirq_pos[%d] = %d\n", cpu, hardirq_pos[cpu]); + } + return 0; +} + +static struct kretprobe kret14 = { + .handler = do_handle_IPI_return, + .maxactive = NR_CPUS, + .kp = { .symbol_name = "do_handle_IPI", }, + //.maxactive = 1024, +}; + +static int KSOFTIRQ_return(struct kretprobe_instance *ri, struct pt_regs *regs) +{ + int cpu = 0; + if (step == 1) { + cpu = smp_processor_id(); + softirq[cpu] = 0; + } + return 0; +} + +//static struct kretprobe kret15 = { +// .handler = KSOFTIRQ_return, +// .maxactive = NR_CPUS, +// .kp = { .symbol_name = "wakeup_softirqd", }, +// //.maxactive = MAX_CPU_NR, +//}; + +static int SOFTIRQ_return(struct kretprobe_instance *ri, struct pt_regs *regs) +{ + int cpu = 0; + u64 ts; + char *chartmp; + struct softirq_result sr; + if (step == 1) { + cpu = smp_processor_id(); + ts = fang_clock(); + spin_lock(&futex_lock); + sr.type = 0; + sr.stime = stime[cpu]; + sr.etime = ts; + sr.core = cpu; + chartmp = (char *)(futex_result + futex_pos); + memcpy(chartmp, &sr, sizeof(sr)); + futex_pos+=sizeof(sr); + spin_unlock(&futex_lock); + } + return 0; +} + +static struct kretprobe kret16 = { + .handler = SOFTIRQ_return, + .maxactive = NR_CPUS, + .kp = { .symbol_name = "__do_softirq", }, + //.maxactive = MAX_CPU_NR, +}; + +// Special for random generator in do_IRQ +static int RANDOM_return(struct kretprobe_instance *ri, struct pt_regs *regs) +{ + int cpu = 0; + if (step == 1) { + cpu = smp_processor_id(); + if (hardirq_pos[cpu] != 0) hardirq_pos[cpu]-=1; + } + return 0; +} + +static struct kretprobe kret17 = { + .handler = RANDOM_return, + .maxactive = NR_CPUS, + .kp = { .symbol_name = "add_interrupt_randomness", }, + //.maxactive = MAX_CPU_NR, +}; + +static int switch_return(struct kretprobe_instance *ri, struct pt_regs *regs) +{ + int cpu = 0; + if (step == 1) { + cpu=smp_processor_id(); + //if (dump_cpu_check[cpu]>0) { + //printk(KERN_INFO "threadID = %d\n", dump_cpu_check[cpu]); + //dump_stack(); + //dump_cpu_check[cpu]=0; + //} + } + return 0; +} + +static struct kretprobe kret18 = { + .handler = switch_return, + .maxactive = NR_CPUS, + .kp = { .symbol_name = "finish_task_switch", }, + //.maxactive = MAX_CPU_NR, +}; + +static int futex_wait_return(struct kretprobe_instance *ri, struct pt_regs *regs) +{ + struct fang_uds fuds; + char *chartmp = NULL; + if (step == 1) { + //int retval = regs_return_value(regs); + //int cpu = smp_processor_id(); + if (current->tgid==target[0]) { + fuds.ts = fang_clock(); + fuds.pid = current->pid; + fuds.type = 4; + + spin_lock(&wait_lock); + chartmp = (char *)(wait_result + wait_pos); + memcpy(chartmp, &fuds, sizeof(fuds)); + wait_pos+=sizeof(fuds); + spin_unlock(&wait_lock); + } + + /* + if (containOfPID(cpu, current->tgid) && retval < 0) { + + //printk(KERN_INFO "Core %d Thread %d RetValue %d Time %llu\n", smp_processor_id(), current->pid, retval, fang_clock()); + fuds.ts = fang_clock(); + fuds.pid = current->pid; + fuds.type = (short)retval; + + spin_lock(&wait_lock); + chartmp = (char *)(wait_result + wait_pos); + memcpy(chartmp, &fuds, sizeof(fuds)); + wait_pos+=sizeof(fuds); + spin_unlock(&wait_lock); + } + */ + } + return 0; +} + +static struct kretprobe kret19 = { + .handler = futex_wait_return, + .maxactive = NR_CPUS, + .kp = { .symbol_name = "futex_wait", }, + //.maxactive = MAX_CPU_NR, +}; + +long ioctl_funcs(struct file *filp,unsigned int cmd, unsigned long arg) +{ + + unsigned long ret = 0; + int tres; + char tmp[200]; + char *chartmp = NULL; + //struct timeval start; + unsigned long start; + struct fang_uds fuds; + struct fang_spin_uds spin_uds; + struct uds_spin_res spin_res; + int i = 0, cpu = 0; + + switch(cmd) { + case IOCTL_ADDWAIT: + if (step == 1) { + fuds.ts = fang_clock(); + fuds.pid = current->pid; + fuds.type = (short)arg; + spin_lock(&wait_lock); + chartmp = (char *)(wait_result + wait_pos); + memcpy(chartmp, &fuds, sizeof(fuds)); + wait_pos+=sizeof(fuds); + spin_unlock(&wait_lock); + } + break; + case IOCTL_ADDUDS: + if (step == 1) { + spin_uds.ts = fang_clock(); + spin_uds.pid = current->pid; + copy_from_user(&spin_res, (void*)arg, 12); + spin_uds.lock = spin_res.addr; + spin_uds.type = spin_res.type; + //fuds.ts = fang_clock(); + //fuds.pid = current->pid; + //fuds.type = (short)arg; + spin_lock(&state_lock); + //chartmp = (char *)(state_result + state_pos); + chartmp = (char *)(state_result + state_pos); + memcpy(chartmp, &spin_uds, sizeof(spin_uds)); + state_pos+=sizeof(spin_uds); + spin_unlock(&state_lock); + } + break; + case IOCTL_PID: + //printk(KERN_INFO "Setting PID = %d\n", (int)pid); + //for_each_process(p) { + // if (task_pid_nr(p)==pid) break; + //} + //target[0] = pid; + switch_pos = 0; + futex_pos = 0; + state_pos = 0; + wait_pos = 0; + + for (i=0;i<20;i++){ + disk_work[i] = 0; + } + + for (i=0; i<NETSEND_SIZE; i++) { + netsend[i] = 0; + //futextag[i] = 0; + //futexstart[i] = 0; + //futexsum[i] = 0; + } + + for (i = 0; i < PIDNUM; i++) { + target[i] = 0; + } + + dnum = 0; + + futex_to = 0; + futex_noto = 0; + + readTarget(); + + step = 1; + break; + + case IOCTL_INIT: + step = -1; + break; + + case IOCTL_COPYSWITCH: + spin_lock(&switch_lock); + ret = switch_pos; + switch_pos = 0; + switch_result_tmp = switch_result; + switch_result = switch_result_bak; + spin_unlock(&switch_lock); + switch_result_bak = switch_result_tmp; + tres = copy_to_user((void*)arg, switch_result_bak, ret); + break; + + case IOCTL_COPYWAIT: + spin_lock(&wait_lock); + ret = wait_pos; + wait_pos = 0; + wait_result_tmp = wait_result; + wait_result = wait_result_bak; + spin_unlock(&wait_lock); + wait_result_bak = wait_result_tmp; + tres = copy_to_user((void*)arg, wait_result_bak, ret); + break; + + case IOCTL_STATE_BEGIN: + sprintf(tmp, "Sample %d\n", state_total); + spin_lock(&switch_lock); + chartmp = (char *)(switch_result + switch_pos); + memcpy(chartmp, tmp, strlen(tmp)); + switch_pos+=strlen(tmp); + spin_unlock(&switch_lock); + step = 2; + state_total++; + break; + + case IOCTL_STATE_END: + step = -1; + + if (switch_pos > BSIZE) { + ret = 1; + } + else { + ret = 0; + } + //ret = 1; + break; + case IOCTL_FUTEX: + spin_lock(&futex_lock); + tag = 0; + fnum = 0; + wnum = 0; + chartmp = (char *)(futex_result + futex_pos); + memcpy(chartmp, tmp, strlen(tmp)); + futex_pos+=strlen(tmp); + futex_total++; + spin_unlock(&futex_lock); + break; + + case IOCTL_JPROBE: + break; + + case IOCTL_UNJPROBE: + break; + case IOCTL_JSWITCH: + break; + case IOCTL_COPYSTATE: + spin_lock(&state_lock); + ret = state_pos; + state_pos = 0; + state_result_tmp = state_result; + state_result = state_result_bak; + spin_unlock(&state_lock); + state_result_bak = state_result_tmp; + tres = copy_to_user((void*)arg, state_result_bak, ret); + //printk(KERN_INFO "state_pos = %d\n", state_pos); + break; + case IOCTL_COPYFUTEX: + spin_lock(&futex_lock); + ret = futex_pos; + futex_pos = 0; + futex_result_tmp = futex_result; + futex_result = futex_result_bak; + spin_unlock(&futex_lock); + futex_result_bak = futex_result_tmp; + tres = copy_to_user((void*)arg, futex_result_bak, ret); + break; + case IOCTL_COPYBUFFER: + break; + case IOCTL_GETENTRY: + spin_lock(&switch_lock); + ret = copy_to_user((void*)arg, switch_result, switch_pos); + ret = switch_pos; + switch_pos = 0; + spin_unlock(&switch_lock); + break; + case IOCTL_STEP1_BEGIN: + switch_pos = 0; + state_pos = 0; + futex_pos = 0; + wait_pos = 0; + spin_lock(&switch_lock); + t = p; + ptmp = p; + do { + start = ktime_get_ns(); + //do_gettimeofday(&start); + } while_each_thread(ptmp, t); + + printk(KERN_INFO "start time: sec = %ld usec = %ld\n", start/NSEC_PER_SEC, (start%NSEC_PER_SEC)/1000); + //step = 1; + spin_unlock(&switch_lock); + break; + case IOCTL_STEP1_END: + spin_lock(&switch_lock); + start = ktime_get_ns(); + //do_gettimeofday(&start); + lastsec = start/NSEC_PER_SEC;//start.tv_sec; + lastusec = (start%NSEC_PER_SEC)/1000;//start.tv_usec; + printk(KERN_INFO "end time: sec = %ld usec = %ld\n", lastsec, lastusec); + step = -1; + spin_unlock(&switch_lock); + break; + case IOCTL_USER_STACK: + //for_each_process(p) { + // if (task_pid_nr(p)==pid) break; + //} + //struct pt_regs *regs = task_pt_regs(p); + //printk(KERN_INFO "IP=%ld, BP=%ld\n", regs->ip, regs->bp); + //long currbp = regs->bp; + //int currpos = 0; + //while(currbp!=0 || currpos > 10) { + // copy_from_user(&currbp, currbp, 8); + // printk(KERN_INFO "Next BP = %ld", currbp); + //} + break; + case IOCTL_DNAME: + tres = copy_from_user(&dname[dnum], (void*)arg, 20); + printk(KERN_INFO "Monitored Disk: %s\n", dname[dnum]); + dnum++; + break; + case IOCTL_SPINLOCK: + cpu = smp_processor_id(); + spin_result[cpu].type = (short)arg; + spin_result[cpu].core = cpu; + spin_result[cpu].ts = fang_clock(); + spin_result[cpu].pid1 = current->pid; + spin_lock(&switch_lock); + chartmp = (char *)(switch_result + switch_pos); + memcpy(chartmp, &spin_result[cpu], sizeof(spin_result[cpu])); + switch_pos+=sizeof(spin_result[cpu]); + spin_unlock(&switch_lock); + break; + case IOCTL_TIME: + printk(KERN_INFO "now = %llu\n", ktime_get()); + break; + } + return ret; +} + +struct file_operations fops = { + open: open, + unlocked_ioctl: ioctl_funcs, + release: release +}; + +struct cdev *kernel_cdev; +dev_t dev_no, dev; + + +#include <asm/uaccess.h> +#include <asm/processor.h> + +//Fang added +int readTarget(void) { + //mm_segment_t fs; + struct file *filp = NULL; + char buf[10240] = { 0}; + int tmppos= 0; + int pidpos = 0; + char buftmp[64] = {0 }; + char* buftmp1; + int i = 0; + int ret; + + //fs = get_fs(); + //set_fs(KERNEL_DS); + trace_printk("in read target\n"); + + filp = filp_open("/tmp/target", O_RDONLY, 0); + if (filp==NULL) { + printk(KERN_ERR "Error: something wrong with the pid target file!\n"); + return -1; + } + //pr_info("filp %lx\n", filp); +#ifdef NEWKERNEL + ret = kernel_read(filp, buf, 10240, &filp->f_pos); + trace_printk("kernel read return %d\n", ret); + //kernel_read(filp, &filp->f_pos, buf, 10240); +#else + vfs_read(filp, buf, 10240, &filp->f_pos); +#endif + //filp->f_op->read(filp, buf, 1024, &filp->f_pos); + filp_close(filp,NULL); + //set_fs(fs); + //pr_info("buf %x\n", buf); + + i=0; + tmppos= 0; + + while(buf[i]) { + if (buf[i]=='\n') { + buftmp[tmppos]='\0'; + //printk(KERN_INFO "%d\n", simple_strtol(buftmp, &buftmp1, 10)); + target[pidpos] = simple_strtol(buftmp, &buftmp1, 10); + //trace_printk("target %d\n", target[pidpos]); + pidpos++; + tmppos = 0; + if (pidpos >= PIDNUM) + pr_info("pidpos exceed !!!!!!!!!\n"); + } + else { + buftmp[tmppos] = buf[i]; + tmppos++; + if (tmppos >= 64) { + pr_info("tmp pos exceedd!!!!!!!!!!\n"); + return 0; + } + } + i++; + if (i >= 10240) + pr_info("i exceed !!!!!!!!!!!!!!\n"); + } + return 0; +} + +int char_arr_init (void) { + int ret = 0; + int i = 0; + + for (i= 0;i<PIDNUM;i++) { + target[i] = 0; + } + + for (i= 0;i<NR_CPUS;i++) { + softirq[i] = 0; + hardirq_pos[i] = 0; + aiotag[i] = 0; + } + + for (i=0; i<NETSEND_SIZE; i++) { + netsend[i] = 0; + //futextag[i] = 0; + //futexstart[i] = 0; + //futexsum[i] = 0; + } + + readTarget(); + + //Check dname + //if (strcmp(dname, "") == 0) { + // printk(KERN_ERR "Error: no device name!\n"); + // return 1; + //} + //else { + // printk(KERN_INFO "Device name: %s\n", dname); + //} + //Init the file read + //fang_curr_task = (struct task_struct *(*)(int))0xffffffff870d0180; + //fang_curr_task = (struct task_struct *(*)(int))kallsyms_lookup_name("curr_task"); + //fang_get_futex_key = (int (*)(u32 __user *, int, union futex_key *, int))kallsyms_lookup_name("get_futex_key"); + //fang_hash_futex = (struct futex_hash_bucket *(*)(union futex_key *))kallsyms_lookup_name("hash_futex"); + //fang_futex_wait_setup = (int (*)(u32 __user *, u32, unsigned int, struct futex_q *, struct futex_hash_bucket **))kallsyms_lookup_name("futex_wait_setup"); + //fang_futex_wait_restart = (long (*)(struct restart_block *)kallsyms_lookup_name("futex_wait_restart"); + //For kernel version larger than 4.8 + //#ifdef NEWKERNEL + //local_clock = (u64 (*)(void))kallsyms_lookup_name("local_clock"); + //#endif + + //printk(KERN_INFO "curr_task = %lx\n", kallsyms_lookup_name("curr_task")); + //printk(KERN_INFO "get_futex_key = %lx\n", kallsyms_lookup_name("get_futex_key")); + //printk(KERN_INFO "hash_futex = %lx\n", kallsyms_lookup_name("hash_futex")); + //printk(KERN_INFO "futex_wait_setup = %lx\n", kallsyms_lookup_name("futex_wait_setup")); + + ret = alloc_chrdev_region(&dev, 0, 1, "wperf"); + if (ret) + pr_info("alloc chrdev failed\n"); + + kernel_cdev = cdev_alloc(); + kernel_cdev->ops = &fops; + kernel_cdev->owner = THIS_MODULE; + printk (" Inside init module\n"); + + ret = cdev_add( kernel_cdev,dev,1); + + if(ret < 0 ) + { + printk(KERN_INFO "Unable to allocate cdev"); + return ret; + } + + Major = MAJOR(dev); + //dev = MKDEV(Major,0); + printk (" The major number for your device is %d\n", Major); + + state_result = (char*)vmalloc(BMAX*sizeof(char)); + state_result_bak = (char*)vmalloc(BMAX*sizeof(char)); + futex_result = (char*)vmalloc(BMAX*sizeof(char)); + futex_result_bak = (char*)vmalloc(BMAX*sizeof(char)); + switch_result = (char*)vmalloc(BMAX*sizeof(char)); + switch_result_bak = (char*)vmalloc(BMAX*sizeof(char)); + + wait_result = (char*)vmalloc(BMAX*sizeof(char)); + wait_result_bak = (char*)vmalloc(BMAX*sizeof(char)); + + spin_lock_init(&switch_lock); + spin_lock_init(&state_lock); + spin_lock_init(&futex_lock); + spin_lock_init(&wait_lock); + + ret = register_kprobe(&jp1); + if (ret ) + printk(KERN_INFO "register_kprobe failed, returned %d\n", ret); + else + pr_info("register kprobe success\n"); + ret = register_kprobe(&jp2); + if (ret) { + printk(KERN_INFO "register_kprobe failed, returned %d\n", ret); + //return ret; + } + ret = register_kprobe(&jp3); + if (ret) + pr_info("register kprobe failed1\n"); + ret = register_kprobe(&jp4); + if (ret) + pr_info("register kprobe failed2\n"); + ret = register_kprobe(&jp5); + if (ret) + pr_info("register kprobe failed3\n"); + if (register_kprobe(&jp6)) { + printk(KERN_INFO "register net_rx jprobe failed!\n"); + } + ret = register_kprobe(&jp7); + if (ret) + pr_info("register kprobe failed4\n"); + ret = register_kprobe(&jp8); + if (ret) + pr_info("register kprobe failed5\n"); + ret = register_kprobe(&jp9); + if (ret) + pr_info("register kprobe failed6\n"); + ret = register_kprobe(&jp10); + if (ret) + pr_info("register kprobe failed7\n"); + //register_kprobe(&jp11); + ret = register_kprobe(&jp12); + if (ret) + pr_info("register kprobe rcu_process_callbacks failed8\n"); + //if (register_kprobe(&jp13)) { + // printk(KERN_INFO "register apic jprobe failed!%d\n"); + //} + + //register_kprobe(&jp14); + //register_kprobe(&jp15); + ret = register_kprobe(&jp16); + if (ret) + pr_info("register kprobe failed9\n"); + //register_kprobe(&jp17); + ret = register_kprobe(&jp18); + if (ret) + pr_info("register kprobe part_round_stats failed0\n"); + //register_kprobe(&jp19); + //register_kprobe(&jp20); + ret = register_kprobe(&jp21); + if (ret) + pr_info("register kprobe failed12\n"); + ret = register_kprobe(&jp22); + if (ret) + pr_info("register kprobe failed13\n"); + //register_kprobe(&jp23); + //jp24.kp.addr = (kprobe_opcode_t *) kallsyms_lookup_name("futex_wait_restart"), + //register_kprobe(&jp24); + //register_kprobe(&jp25); + ret = register_kprobe(&jp26); + if (ret) + pr_info("register kprobe failed14\n"); + ret = register_kprobe(&jp27); + if (ret) + pr_info("register kprobe failed15\n"); + ret = register_kprobe(&jp28); + if (ret) + pr_info("register kprobe failed16\n"); + ret = register_kprobe(&jp29); + if (ret) + pr_info("register kprobe failed17\n"); + + + /*kret3.kp.addr = (kprobe_opcode_t *) kallsyms_lookup_name("tasklet_hi_action"); + kret4.kp.addr = (kprobe_opcode_t *) kallsyms_lookup_name("run_timer_softirq"); + kret5.kp.addr = (kprobe_opcode_t *) kallsyms_lookup_name("net_tx_action"); + kret6.kp.addr = (kprobe_opcode_t *) kallsyms_lookup_name("net_rx_action"); + kret7.kp.addr = (kprobe_opcode_t *) kallsyms_lookup_name("blk_done_softirq"); + kret8.kp.addr = (kprobe_opcode_t *) kallsyms_lookup_name("irq_poll_softirq"); + kret9.kp.addr = (kprobe_opcode_t *) kallsyms_lookup_name("tasklet_action"); + kret10.kp.addr = (kprobe_opcode_t *) kallsyms_lookup_name("run_rebalance_domains"); + kret11.kp.addr = (kprobe_opcode_t *) kallsyms_lookup_name("run_hrtimer_softirq"); + kret12.kp.addr = (kprobe_opcode_t *) kallsyms_lookup_name("rcu_process_callbacks"); + kret13.kp.addr = (kprobe_opcode_t *) kallsyms_lookup_name("local_apic_timer_interrupt"); + kret14.kp.addr = (kprobe_opcode_t *) kallsyms_lookup_name("do_IRQ"); +// kret15.kp.addr = (kprobe_opcode_t *) kallsyms_lookup_name("wakeup_softirqd"); + kret16.kp.addr = (kprobe_opcode_t *) kallsyms_lookup_name("__do_softirq"); + kret17.kp.addr = (kprobe_opcode_t *) kallsyms_lookup_name("add_interrupt_randomness"); + //kret18.kp.addr = (kprobe_opcode_t *) kallsyms_lookup_name("finish_task_switch"); + //kret19.kp.addr = (kprobe_opcode_t *) kallsyms_lookup_name("futex_wait"); + //kret19.kp.addr = (kprobe_opcode_t *) kallsyms_lookup_name("__lock_sock"); +*/ + + ret = register_kretprobe(&kret3); + if (ret) { + printk(KERN_INFO "register_kretprobe failed, returned %d\n", ret); + //return ret; + } else + pr_info("register kretprobe success\n"); + ret = register_kretprobe(&kret4); + if (ret) { + printk(KERN_INFO "register_kretprobe2 failed, returned %d\n", ret); + //return ret; + } + ret = register_kretprobe(&kret5); + if (ret) + pr_info("register kretprobe failed1\n"); + ret = register_kretprobe(&kret6); + if (ret) + pr_info("register kretprobe failed2\n"); + ret = register_kretprobe(&kret7); + if (ret) + pr_info("register kretprobe failed3\n"); + ret = register_kretprobe(&kret8); + if (ret) + pr_info("register kretprobe failed4\n"); + ret = register_kretprobe(&kret9); + if (ret) + pr_info("register kretprobe failed5\n"); + ret = register_kretprobe(&kret10); + if (ret) + pr_info("register kretprobe failed6\n"); + //register_kretprobe(&kret11); + ret = register_kretprobe(&kret12); + if (ret) + pr_info("register kretprobe rcu_process_callbacks failed7\n"); + //register_kretprobe(&kret13); + //register_kretprobe(&kret14); + ret = register_kretprobe(&kret16); + if (ret) + pr_info("register kretprobe failed8\n"); + //register_kretprobe(&kret17); + //register_kretprobe(&kret18); + //register_kretprobe(&kret19); + + return 0; +} + +void char_arr_cleanup(void) { + //cdev_del(kernel_cdev); + + unregister_kprobe(&jp1); + + unregister_kprobe(&jp2); + unregister_kprobe(&jp3); + unregister_kprobe(&jp4); + unregister_kprobe(&jp5); + unregister_kprobe(&jp6); + unregister_kprobe(&jp7); + unregister_kprobe(&jp8); + unregister_kprobe(&jp9); + unregister_kprobe(&jp10); + //unregister_kprobe(&jp11); + unregister_kprobe(&jp12); + //unregister_kprobe(&jp13); + //unregister_kprobe(&jp14); + //unregister_kprobe(&jp15); + unregister_kprobe(&jp16); + //unregister_kprobe(&jp17); + unregister_kprobe(&jp18); + //unregister_kprobe(&jp19); + //unregister_kprobe(&jp20); + unregister_kprobe(&jp21); + unregister_kprobe(&jp22); + //unregister_kprobe(&jp23); + //unregister_kprobe(&jp24); + //unregister_kprobe(&jp25); + unregister_kprobe(&jp26); + unregister_kprobe(&jp27); + unregister_kprobe(&jp28); + unregister_kprobe(&jp29); + + + //unregister_kretprobe(&futex_return); + //unregister_kretprobe(&sleep_return); + //unregister_kretprobe(&signal_return); + //unregister_kretprobe(&aio_return); + + unregister_kretprobe(&kret3); + unregister_kretprobe(&kret4); + unregister_kretprobe(&kret5); + unregister_kretprobe(&kret6); + unregister_kretprobe(&kret7); + unregister_kretprobe(&kret8); + unregister_kretprobe(&kret9); + unregister_kretprobe(&kret10); + //unregister_kretprobe(&kret11); + unregister_kretprobe(&kret12); + //unregister_kretprobe(&kret13); + //unregister_kretprobe(&kret14); + unregister_kretprobe(&kret16); + //unregister_kretprobe(&kret17); + //unregister_kretprobe(&kret18); + //unregister_kretprobe(&kret19); + + /* nmissed > 0 suggests that maxactive was set too low. */ + //printk("Missed probing %d instances of %s\n", + // futex_return.nmissed, "do_futex return"); + + unregister_chrdev_region(MKDEV(Major, 0), 1); + cdev_del(kernel_cdev); + + vfree(switch_result); + vfree(switch_result_bak); + vfree(state_result); + vfree(state_result_bak); + vfree(futex_result); + vfree(futex_result_bak); + + vfree(wait_result); + vfree(wait_result_bak); + + printk(KERN_INFO " Inside cleanup_module\n"); +} +MODULE_LICENSE("GPL"); +module_init(char_arr_init); +module_exit(char_arr_cleanup);