Revision: 947 Author: teawater Date: Fri Mar 2 05:50:56 2012 Log: Increase the speed of access to trace state variables. http://code.google.com/p/kgtp/source/detail?r=947 Modified: /trunk/UPDATE /trunk/gtp.c /trunk/gtp_for_review.patch ======================================= --- /trunk/UPDATE Wed Feb 29 04:28:19 2012 +++ /trunk/UPDATE Fri Mar 2 05:50:56 2012 @@ -2,6 +2,8 @@ * Fix bug with GDB RSP package sum check. +* Increase the speed of access to trace state variables. + *** 20120224 * https://lkml.org/lkml/2012/2/26/127 ======================================= --- /trunk/gtp.c Wed Feb 29 04:28:19 2012 +++ /trunk/gtp.c Fri Mar 2 05:50:56 2012 @@ -249,6 +249,13 @@ #define INT2CHAR(h) ((h) > 9 ? (h) + 'a' - 10 : (h) + '0') +#define OP_GETV_SPECIAL 0xfa +#define OP_SETV_SPECIAL 0xfb +#define OP_TRACEV_SPECIAL 0xfc +#define OP_TRACE_PRINTK 0xfd +#define OP_TRACE_QUICK_PRINTK 0xfe +#define OP_TRACEV_PRINTK 0xff + struct action_agent_exp { unsigned int size; uint8_t *buf; @@ -2523,30 +2530,32 @@ return ret; } -uint64_t -gtp_get_var(struct gtp_trace_s *gts, struct gtp_var *tve) -{ - switch (tve->num) { +static uint64_t +gtp_get_var_special(struct gtp_trace_s *gts, unsigned int num) +{ + uint64_t ret; + + switch (num) { case GTP_VAR_CURRENT_TASK_ID: if (gts->ri) - return (uint64_t)(CORE_ADDR)gts->ri->task; + ret = (uint64_t)(CORE_ADDR)gts->ri->task; else - return (uint64_t)(CORE_ADDR)get_current(); + ret = (uint64_t)(CORE_ADDR)get_current(); break; case GTP_VAR_CURRENT_TASK_PID_ID: if (gts->ri) - return (uint64_t)(CORE_ADDR)gts->ri->task->pid; + ret = (uint64_t)(CORE_ADDR)gts->ri->task->pid; else - return (uint64_t)(CORE_ADDR)get_current()->pid; + ret = (uint64_t)(CORE_ADDR)get_current()->pid; break; case GTP_VAR_CURRENT_THREAD_INFO_ID: - return (uint64_t)(CORE_ADDR)current_thread_info(); + ret = (uint64_t)(CORE_ADDR)current_thread_info(); break; case GTP_VAR_CLOCK_ID: - return (uint64_t)GTP_LOCAL_CLOCK; + ret = (uint64_t)GTP_LOCAL_CLOCK; break; case GTP_VAR_COOKED_CLOCK_ID: - return (uint64_t)(__get_cpu_var(local_clock_current) + ret = (uint64_t)(__get_cpu_var(local_clock_current) - __get_cpu_var(local_clock_offset)); break; #ifdef CONFIG_X86 @@ -2554,50 +2563,134 @@ { unsigned long long a; rdtscll(a); - return (uint64_t)a; + ret = (uint64_t)a; } break; case GTP_VAR_COOKED_RDTSC_ID: - return (uint64_t)(__get_cpu_var(rdtsc_current) + ret = (uint64_t)(__get_cpu_var(rdtsc_current) - __get_cpu_var(rdtsc_offset)); break; #endif case GTP_VAR_CPU_ID: - return (uint64_t)(CORE_ADDR)smp_processor_id(); + ret = (uint64_t)(CORE_ADDR)smp_processor_id(); break; case GTP_VAR_CPU_NUMBER_ID: - return (uint64_t)gtp_cpu_number; + ret = (uint64_t)gtp_cpu_number; break; case GTP_VAR_PRINTK_TMP_ID: - return gts->printk_tmp; + ret = gts->printk_tmp; break; case GTP_VAR_DUMP_STACK_ID: printk(KERN_NULL "gtp %d %p:", (int)gts->tpe->num, (void *)(CORE_ADDR)gts->tpe->addr); dump_stack(); - return 0; + ret = 0; break; case GTP_VAR_XTIME_SEC_ID: if (gts->xtime.tv_sec == 0 && gts->xtime.tv_nsec == 0) getnstimeofday(>s->xtime); - return (uint64_t)gts->xtime.tv_sec; + ret = (uint64_t)gts->xtime.tv_sec; break; case GTP_VAR_XTIME_NSEC_ID: if (gts->xtime.tv_sec == 0 && gts->xtime.tv_nsec == 0) getnstimeofday(>s->xtime); - return (uint64_t)gts->xtime.tv_nsec; + ret = (uint64_t)gts->xtime.tv_nsec; break; case GTP_VAR_HARDIRQ_COUNT_ID: - return (uint64_t)hardirq_count(); + ret = (uint64_t)hardirq_count(); break; case GTP_VAR_SOFTIRQ_COUNT_ID: - return (uint64_t)softirq_count(); + ret = (uint64_t)softirq_count(); break; case GTP_VAR_IRQ_COUNT_ID: - return (uint64_t)irq_count(); + ret = (uint64_t)irq_count(); break; + default: + ret = 0; + break; } + return ret; +} + +static void+gtp_set_var_special(struct gtp_trace_s *gts, unsigned int num, ULONGEST val)
+{ + switch (num) { + case GTP_VAR_PRINTK_TMP_ID: + gts->printk_tmp = val; + break; + case GTP_VAR_PRINTK_LEVEL_ID: + gts->printk_level = (unsigned int)val; + break; + case GTP_VAR_PRINTK_FORMAT_ID: + gts->printk_format = (unsigned int)val; + break; + case GTP_VAR_PC_PE_EN_ID: + gtp_pc_pe_en((int)val); + break; + } +} + +static int +gtp_collect_var_special(struct gtp_trace_s *gts, unsigned int num) +{ + struct gtp_frame_var *fvar; + char *tmp; +#ifdef GTP_FTRACE_RING_BUFFER + struct ring_buffer_event *rbe; +#endif + + if (gts->next == NULL) { + if (gtp_action_head(gts)) + return -1; + } + + if (GTP_VAR_AUTO_TRACEV(num)) + return 0; + +#ifdef GTP_FTRACE_RING_BUFFER + GTP_FRAME_RINGBUFFER_ALLOC(GTP_FRAME_VAR_SIZE); +#endif +#if defined(GTP_FRAME_SIMPLE) || defined(GTP_RB) +#ifdef GTP_RB + tmp = gtp_rb_alloc(gts->next, GTP_FRAME_VAR_SIZE, gts->id); +#endif +#ifdef GTP_FRAME_SIMPLE + tmp = gtp_frame_alloc(GTP_FRAME_VAR_SIZE); +#endif + if (!tmp) { + gts->tpe->reason = gtp_stop_frame_full; + return -1; + } +#ifdef GTP_FRAME_SIMPLE + *gts->next = tmp; +#endif +#endif + + FID(tmp) = FID_VAR; + tmp += FID_SIZE; + +#ifdef GTP_FRAME_SIMPLE + gts->next = (char **)tmp; + *gts->next = NULL; + tmp += sizeof(char *); +#endif + + fvar = (struct gtp_frame_var *) tmp; + fvar->num = num; + fvar->val = gtp_get_var_special(gts, num); + +#ifdef GTP_FTRACE_RING_BUFFER + ring_buffer_unlock_commit(gtp_frame, rbe); +#endif + + return 0; +} + +uint64_t +gtp_get_var(struct gtp_trace_s *gts, struct gtp_var *tve) +{ #ifdef GTP_PERF_EVENTS if (tve->ptid == pe_tv_val || tve->ptid == pe_tv_enabled || tve->ptid == pe_tv_running) { @@ -2702,42 +2795,20 @@ #define gtp_action_x_setv_pe #endif -#define gtp_action_x_setv \ - do { \ - switch (arg) { \ - case GTP_VAR_PRINTK_TMP_ID: \ - gts->printk_tmp = top; \ - break; \ - case GTP_VAR_PRINTK_LEVEL_ID: \ - gts->printk_level = (unsigned int)top; \ - break; \ - case GTP_VAR_PRINTK_FORMAT_ID: \ - gts->printk_format = (unsigned int)top; \ - break; \ - case GTP_VAR_PC_PE_EN_ID: \ - gtp_pc_pe_en((int)top); \ - break; \ - default: { \ - struct gtp_var *tve; \ - \ - tve = gtp_gtp_var_array_find(arg); \ - if (!tve) \ - goto code_error_out; \ - gtp_action_x_setv_pe; \ - /* Not check the other special \ - trace state variables. \ - Because set in tve->val doesn't \ - affect anything. */ \ - tve->val = (uint64_t)top; \ - } \ - break; \ - } \ +#define gtp_action_x_setv \ + do { \ + struct gtp_var *tve; \ + \ + tve = gtp_gtp_var_array_find(arg); \ + if (!tve) \ + goto code_error_out; \ + gtp_action_x_setv_pe; \ + tve->val = (uint64_t)top; \ } while (0) #define gtp_action_x_tracev \ do { \ - if (!gts->tpe->have_printk \ - || !GTP_VAR_AUTO_TRACEV(arg)) { \ + if (!gts->tpe->have_printk) { \ struct gtp_var *tve; \ \ tve = gtp_gtp_var_array_find(arg); \ @@ -2907,7 +2978,7 @@ top = stack[--sp]; break; /* trace_printk */ - case 0xfd: + case OP_TRACE_PRINTK: if (gtp_action_printk(gts, (ULONGEST)stack[--sp], (size_t) top)) @@ -2925,7 +2996,7 @@ pc++; break; /* trace_quick_printk */ - case 0xfe: + case OP_TRACE_QUICK_PRINTK: if (gtp_action_printk(gts, (ULONGEST) top, (size_t) ebuf[pc++])) goto out; @@ -3087,20 +3158,39 @@ arg = (arg << 8) + ebuf[pc++]; gtp_action_x_getv; break; + /* getv_sepecial */ + case OP_GETV_SPECIAL: + arg = ebuf[pc++]; + arg = (arg << 8) + ebuf[pc++]; + stack[sp++] = top; + top = gtp_get_var_special(gts, arg); + break; /* setv */ case 0x2d: arg = ebuf[pc++]; arg = (arg << 8) + ebuf[pc++]; gtp_action_x_setv; break; + /* setv_sepecial */ + case OP_SETV_SPECIAL: + arg = ebuf[pc++]; + arg = (arg << 8) + ebuf[pc++]; + gtp_set_var_special(gts, arg, top); + break; /* tracev */ case 0x2e: arg = ebuf[pc++]; arg = (arg << 8) + ebuf[pc++]; gtp_action_x_tracev; break; + /* tracev_special */ + case OP_TRACEV_SPECIAL: + arg = ebuf[pc++]; + arg = (arg << 8) + ebuf[pc++]; + gtp_collect_var_special(gts, arg); + break; /* tracev_printk */ - case 0xff: + case OP_TRACEV_PRINTK: arg = ebuf[pc++]; arg = (arg << 8) + ebuf[pc++]; gtp_action_x_tracev_printk; @@ -3432,18 +3522,37 @@ arg = (arg << 8) + ebuf[pc++]; gtp_action_x_getv; break; + /* getv_sepecial */ + case OP_GETV_SPECIAL: + arg = ebuf[pc++]; + arg = (arg << 8) + ebuf[pc++]; + stack[sp++] = top; + top = gtp_get_var_special(gts, arg); + break; /* setv */ case 0x2d: arg = ebuf[pc++]; arg = (arg << 8) + ebuf[pc++]; gtp_action_x_setv; break; + /* setv_sepecial */ + case OP_SETV_SPECIAL: + arg = ebuf[pc++]; + arg = (arg << 8) + ebuf[pc++]; + gtp_set_var_special(gts, arg, top); + break; /* tracev */ case 0x2e: arg = ebuf[pc++]; arg = (arg << 8) + ebuf[pc++]; gtp_action_x_tracev; break; + /* tracev_special */ + case OP_TRACEV_SPECIAL: + arg = ebuf[pc++]; + arg = (arg << 8) + ebuf[pc++]; + gtp_collect_var_special(gts, arg); + break; /* printf */ case 0x31: { arg = ebuf[pc++]; @@ -4701,25 +4810,26 @@ arg = ebuf[pc++]; arg = (arg << 8) + ebuf[pc++]; - if (arg == GTP_VAR_NO_SELF_TRACE_ID) { - tpe->no_self_trace = 1; - ret = 1; - goto release_out; - } - if (!GTP_VAR_IS_SPECIAL(arg)) { if (gtp_x_var_add(&vlist, arg, 1)) { ret = -ENOMEM; goto release_out; } - } - - if (arg == GTP_VAR_COOKED_CLOCK_ID) - gtp_access_cooked_clock = 1; + } else { + if (arg == GTP_VAR_NO_SELF_TRACE_ID) { + tpe->no_self_trace = 1; + ret = 1; + goto release_out; + } + + if (arg == GTP_VAR_COOKED_CLOCK_ID) + gtp_access_cooked_clock = 1; #ifdef CONFIG_X86 - else if (arg == GTP_VAR_COOKED_RDTSC_ID) - gtp_access_cooked_rdtsc = 1; + else if (arg == GTP_VAR_COOKED_RDTSC_ID) + gtp_access_cooked_rdtsc = 1; #endif + ebuf[pc - 3] = OP_GETV_SPECIAL; + } } if (ae->type == 'X') { sp++; @@ -4737,26 +4847,28 @@ arg = ebuf[pc++]; arg = (arg << 8) + ebuf[pc++]; - if (arg == GTP_VAR_NO_SELF_TRACE_ID) { - tpe->no_self_trace = 1; - ret = 1; - goto release_out; - } else if (arg == GTP_VAR_KRET_ID) { - /* XXX: still not set it - value to maxactive. */ - tpe->is_kretprobe = 1; - ret = 1; - goto release_out; - } - - if (arg == GTP_VAR_PRINTK_LEVEL_ID) - tpe->have_printk = 1; - if (!GTP_VAR_IS_SPECIAL(arg)) { if (gtp_x_var_add(&vlist, arg, 2)) { ret = -ENOMEM; goto release_out; } + } else { + if (arg == GTP_VAR_NO_SELF_TRACE_ID) { + tpe->no_self_trace = 1; + ret = 1; + goto release_out; + } else if (arg == GTP_VAR_KRET_ID) { + /* XXX: still not set it + value to maxactive. */ + tpe->is_kretprobe = 1; + ret = 1; + goto release_out; + } + + if (arg == GTP_VAR_PRINTK_LEVEL_ID) + tpe->have_printk = 1; + + ebuf[pc - 3] = OP_SETV_SPECIAL; } } break; @@ -4773,25 +4885,25 @@ arg = ebuf[pc++]; arg = (arg << 8) + ebuf[pc++]; - if (arg == GTP_VAR_NO_SELF_TRACE_ID) { - tpe->no_self_trace = 1; - ret = 1; - goto release_out; - } - if (!GTP_VAR_IS_SPECIAL(arg)) { if (gtp_x_var_add(&vlist, arg, 4)) { ret = -ENOMEM; goto release_out; } - } - - if (arg == GTP_VAR_COOKED_CLOCK_ID) - gtp_access_cooked_clock = 1; + } else { + if (arg == GTP_VAR_NO_SELF_TRACE_ID) { + tpe->no_self_trace = 1; + ret = 1; + goto release_out; + } + if (arg == GTP_VAR_COOKED_CLOCK_ID) + gtp_access_cooked_clock = 1; #ifdef CONFIG_X86 - else if (arg == GTP_VAR_COOKED_RDTSC_ID) - gtp_access_cooked_rdtsc = 1; + else if (arg == GTP_VAR_COOKED_RDTSC_ID) + gtp_access_cooked_rdtsc = 1; #endif + ebuf[pc - 3] = OP_TRACEV_SPECIAL; + } } break; @@ -4911,15 +5023,15 @@ switch (ebuf[last_trace_pc]) { /* trace */ case 0x0c: - ebuf[last_trace_pc] = 0xfd; + ebuf[last_trace_pc] = OP_TRACE_PRINTK; break; /* trace_quick */ case 0x0d: - ebuf[last_trace_pc] = 0xfe; + ebuf[last_trace_pc] = OP_TRACE_QUICK_PRINTK; break; /* tracev */ case 0x2e: - ebuf[last_trace_pc] = 0xff; + ebuf[last_trace_pc] = OP_TRACEV_PRINTK; break; } } ======================================= --- /trunk/gtp_for_review.patch Wed Feb 29 04:28:19 2012 +++ /trunk/gtp_for_review.patch Fri Mar 2 05:50:56 2012 @@ -8,12 +8,12 @@ kernel/events/core.c | 14 lib/Kconfig.debug | 10 lib/Makefile | 4- lib/gtp.c | 8608 +++++++++++++++++++++++++++++++++++++++ + lib/gtp.c | 8665 +++++++++++++++++++++++++++++++++++++++
lib/gtp_rb.c | 495 ++ scripts/gtp/add-ons/pe.py | 729 +++ scripts/gtp/getgtprsp.pl | 137 scripts/gtp/getmod.py | 132 - 14 files changed, 11948 insertions(+), 2 deletions(-) + 14 files changed, 12005 insertions(+), 2 deletions(-) --- /dev/null +++ b/Documentation/gtp/howto.txt @@ -1952,7 +1952,7 @@ +gtp.o: gtp_rb.c --- /dev/null +++ b/lib/gtp.c -@@ -0,0 +1,8608 @@ +@@ -0,0 +1,8665 @@ +/* + * Kernel GDB tracepoint module. + * @@ -2056,6 +2056,13 @@ + +#define INT2CHAR(h) ((h) > 9 ? (h) + 'a' - 10 : (h) + '0') + ++#define OP_GETV_SPECIAL 0xfa ++#define OP_SETV_SPECIAL 0xfb ++#define OP_TRACEV_SPECIAL 0xfc ++#define OP_TRACE_PRINTK 0xfd ++#define OP_TRACE_QUICK_PRINTK 0xfe ++#define OP_TRACEV_PRINTK 0xff ++ +struct action_agent_exp { + unsigned int size; + uint8_t *buf; @@ -4001,30 +4008,32 @@ + return ret; +} + -+uint64_t -+gtp_get_var(struct gtp_trace_s *gts, struct gtp_var *tve) ++static uint64_t ++gtp_get_var_special(struct gtp_trace_s *gts, unsigned int num) +{ -+ switch (tve->num) { ++ uint64_t ret; ++ ++ switch (num) { + case GTP_VAR_CURRENT_TASK_ID: + if (gts->ri) -+ return (uint64_t)(CORE_ADDR)gts->ri->task; ++ ret = (uint64_t)(CORE_ADDR)gts->ri->task; + else -+ return (uint64_t)(CORE_ADDR)get_current(); ++ ret = (uint64_t)(CORE_ADDR)get_current(); + break; + case GTP_VAR_CURRENT_TASK_PID_ID: + if (gts->ri) -+ return (uint64_t)(CORE_ADDR)gts->ri->task->pid; ++ ret = (uint64_t)(CORE_ADDR)gts->ri->task->pid; + else -+ return (uint64_t)(CORE_ADDR)get_current()->pid; ++ ret = (uint64_t)(CORE_ADDR)get_current()->pid; + break; + case GTP_VAR_CURRENT_THREAD_INFO_ID: -+ return (uint64_t)(CORE_ADDR)current_thread_info(); ++ ret = (uint64_t)(CORE_ADDR)current_thread_info(); + break; + case GTP_VAR_CLOCK_ID: -+ return (uint64_t)GTP_LOCAL_CLOCK; ++ ret = (uint64_t)GTP_LOCAL_CLOCK; + break; + case GTP_VAR_COOKED_CLOCK_ID: -+ return (uint64_t)(__get_cpu_var(local_clock_current) ++ ret = (uint64_t)(__get_cpu_var(local_clock_current) + - __get_cpu_var(local_clock_offset)); + break; +#ifdef CONFIG_X86 @@ -4032,78 +4041,77 @@ + { + unsigned long long a; + rdtscll(a); -+ return (uint64_t)a; ++ ret = (uint64_t)a; + } + break; + case GTP_VAR_COOKED_RDTSC_ID: -+ return (uint64_t)(__get_cpu_var(rdtsc_current) ++ ret = (uint64_t)(__get_cpu_var(rdtsc_current) + - __get_cpu_var(rdtsc_offset)); + break; +#endif + case GTP_VAR_CPU_ID: -+ return (uint64_t)(CORE_ADDR)smp_processor_id(); ++ ret = (uint64_t)(CORE_ADDR)smp_processor_id(); + break; + case GTP_VAR_CPU_NUMBER_ID: -+ return (uint64_t)gtp_cpu_number; ++ ret = (uint64_t)gtp_cpu_number; + break; + case GTP_VAR_PRINTK_TMP_ID: -+ return gts->printk_tmp; ++ ret = gts->printk_tmp; + break; + case GTP_VAR_DUMP_STACK_ID: + printk(KERN_NULL "gtp %d %p:", (int)gts->tpe->num, + (void *)(CORE_ADDR)gts->tpe->addr); + dump_stack(); -+ return 0; ++ ret = 0; + break; + case GTP_VAR_XTIME_SEC_ID: + if (gts->xtime.tv_sec == 0 && gts->xtime.tv_nsec == 0) + getnstimeofday(>s->xtime); -+ return (uint64_t)gts->xtime.tv_sec; ++ ret = (uint64_t)gts->xtime.tv_sec; + break; + case GTP_VAR_XTIME_NSEC_ID: + if (gts->xtime.tv_sec == 0 && gts->xtime.tv_nsec == 0) + getnstimeofday(>s->xtime); -+ return (uint64_t)gts->xtime.tv_nsec; ++ ret = (uint64_t)gts->xtime.tv_nsec; + break; + case GTP_VAR_HARDIRQ_COUNT_ID: -+ return (uint64_t)hardirq_count(); ++ ret = (uint64_t)hardirq_count(); + break; + case GTP_VAR_SOFTIRQ_COUNT_ID: -+ return (uint64_t)softirq_count(); ++ ret = (uint64_t)softirq_count(); + break; + case GTP_VAR_IRQ_COUNT_ID: -+ return (uint64_t)irq_count(); ++ ret = (uint64_t)irq_count(); + break; ++ default: ++ ret = 0; ++ break; + } + -+#ifdef CONFIG_PERF_EVENTS -+ if (tve->ptid == pe_tv_val || tve->ptid == pe_tv_enabled -+ || tve->ptid == pe_tv_running) { -+ tve->pts->val = perf_event_read_value(tve->pts->event, -+ &(tve->pts->enabled), -+ &(tve->pts->running)); -+ switch (tve->ptid) { -+ case pe_tv_val: -+ return (uint64_t)(tve->pts->val); -+ break; -+ case pe_tv_enabled: -+ return (uint64_t)(tve->pts->enabled); -+ break; -+ case pe_tv_running: -+ return (uint64_t)(tve->pts->running); -+ break; -+ default: -+ return 0; -+ break; -+ } -+ } -+#endif ++ return ret; ++} + -+ return tve->val; ++static void++gtp_set_var_special(struct gtp_trace_s *gts, unsigned int num, ULONGEST val)
++{ ++ switch (num) { ++ case GTP_VAR_PRINTK_TMP_ID: ++ gts->printk_tmp = val; ++ break; ++ case GTP_VAR_PRINTK_LEVEL_ID: ++ gts->printk_level = (unsigned int)val; ++ break; ++ case GTP_VAR_PRINTK_FORMAT_ID: ++ gts->printk_format = (unsigned int)val; ++ break; ++ case GTP_VAR_PC_PE_EN_ID: ++ gtp_pc_pe_en((int)val); ++ break; ++ } +} + +static int -+gtp_collect_var(struct gtp_trace_s *gts, struct gtp_var *tve) ++gtp_collect_var_special(struct gtp_trace_s *gts, unsigned int num) +{ + struct gtp_frame_var *fvar; + char *tmp; @@ -4115,6 +4123,9 @@ + if (gtp_action_head(gts)) + return -1; + } ++ ++ if (GTP_VAR_AUTO_TRACEV(num)) ++ return 0; + +#ifdef GTP_FTRACE_RING_BUFFER + GTP_FRAME_RINGBUFFER_ALLOC(GTP_FRAME_VAR_SIZE); @@ -4145,8 +4156,8 @@ +#endif + + fvar = (struct gtp_frame_var *) tmp; -+ fvar->num = tve->num; -+ fvar->val = gtp_get_var(gts, tve); ++ fvar->num = num; ++ fvar->val = gtp_get_var_special(gts, num); + +#ifdef GTP_FTRACE_RING_BUFFER + ring_buffer_unlock_commit(gtp_frame, rbe); @@ -4154,6 +4165,35 @@ + + return 0; +} ++ ++uint64_t ++gtp_get_var(struct gtp_trace_s *gts, struct gtp_var *tve) ++{ ++#ifdef GTP_PERF_EVENTS ++ if (tve->ptid == pe_tv_val || tve->ptid == pe_tv_enabled ++ || tve->ptid == pe_tv_running) { ++ tve->pts->val = perf_event_read_value(tve->pts->event, ++ &(tve->pts->enabled), ++ &(tve->pts->running)); ++ switch (tve->ptid) { ++ case pe_tv_val: ++ return (uint64_t)(tve->pts->val); ++ break; ++ case pe_tv_enabled: ++ return (uint64_t)(tve->pts->enabled); ++ break; ++ case pe_tv_running: ++ return (uint64_t)(tve->pts->running); ++ break; ++ default: ++ return 0; ++ break; ++ } ++ } ++#endif ++ ++ return tve->val; ++} + +#define gtp_action_x_getv \ + do { \ @@ -4180,42 +4220,20 @@ +#define gtp_action_x_setv_pe +#endif + -+#define gtp_action_x_setv \ -+ do { \ -+ switch (arg) { \ -+ case GTP_VAR_PRINTK_TMP_ID: \ -+ gts->printk_tmp = top; \ -+ break; \ -+ case GTP_VAR_PRINTK_LEVEL_ID: \ -+ gts->printk_level = (unsigned int)top; \ -+ break; \ -+ case GTP_VAR_PRINTK_FORMAT_ID: \ -+ gts->printk_format = (unsigned int)top; \ -+ break; \ -+ case GTP_VAR_PC_PE_EN_ID: \ -+ gtp_pc_pe_en((int)top); \ -+ break; \ -+ default: { \ -+ struct gtp_var *tve; \ -+ \ -+ tve = gtp_gtp_var_array_find(arg); \ -+ if (!tve) \ -+ goto code_error_out; \ -+ gtp_action_x_setv_pe; \ -+ /* Not check the other special \ -+ trace state variables. \ -+ Because set in tve->val doesn't \ -+ affect anything. */ \ -+ tve->val = (uint64_t)top; \ -+ } \ -+ break; \ -+ } \ ++#define gtp_action_x_setv \ ++ do { \ ++ struct gtp_var *tve; \ ++ \ ++ tve = gtp_gtp_var_array_find(arg); \ ++ if (!tve) \ ++ goto code_error_out; \ ++ gtp_action_x_setv_pe; \ ++ tve->val = (uint64_t)top; \ + } while (0) + +#define gtp_action_x_tracev \ + do { \ -+ if (!gts->tpe->have_printk \ -+ || !GTP_VAR_AUTO_TRACEV(arg)) { \ ++ if (!gts->tpe->have_printk) { \ + struct gtp_var *tve; \ + \ + tve = gtp_gtp_var_array_find(arg); \ @@ -4385,7 +4403,7 @@ + top = stack[--sp]; + break; + /* trace_printk */ -+ case 0xfd: ++ case OP_TRACE_PRINTK: + if (gtp_action_printk(gts, + (ULONGEST)stack[--sp], + (size_t) top)) @@ -4403,7 +4421,7 @@ + pc++; + break; + /* trace_quick_printk */ -+ case 0xfe: ++ case OP_TRACE_QUICK_PRINTK: + if (gtp_action_printk(gts, (ULONGEST) top, + (size_t) ebuf[pc++])) + goto out; @@ -4565,20 +4583,39 @@ + arg = (arg << 8) + ebuf[pc++]; + gtp_action_x_getv; + break; ++ /* getv_sepecial */ ++ case OP_GETV_SPECIAL: ++ arg = ebuf[pc++]; ++ arg = (arg << 8) + ebuf[pc++]; ++ stack[sp++] = top; ++ top = gtp_get_var_special(gts, arg); ++ break; + /* setv */ + case 0x2d: + arg = ebuf[pc++]; + arg = (arg << 8) + ebuf[pc++]; + gtp_action_x_setv; + break; ++ /* setv_sepecial */ ++ case OP_SETV_SPECIAL: ++ arg = ebuf[pc++]; ++ arg = (arg << 8) + ebuf[pc++]; ++ gtp_set_var_special(gts, arg, top); ++ break; + /* tracev */ + case 0x2e: + arg = ebuf[pc++]; + arg = (arg << 8) + ebuf[pc++]; + gtp_action_x_tracev; + break; ++ /* tracev_special */ ++ case OP_TRACEV_SPECIAL: ++ arg = ebuf[pc++]; ++ arg = (arg << 8) + ebuf[pc++]; ++ gtp_collect_var_special(gts, arg); ++ break; + /* tracev_printk */ -+ case 0xff: ++ case OP_TRACEV_PRINTK: + arg = ebuf[pc++]; + arg = (arg << 8) + ebuf[pc++]; + gtp_action_x_tracev_printk; @@ -4910,18 +4947,37 @@ + arg = (arg << 8) + ebuf[pc++]; + gtp_action_x_getv; + break; ++ /* getv_sepecial */ ++ case OP_GETV_SPECIAL: ++ arg = ebuf[pc++]; ++ arg = (arg << 8) + ebuf[pc++]; ++ stack[sp++] = top; ++ top = gtp_get_var_special(gts, arg); ++ break; + /* setv */ + case 0x2d: + arg = ebuf[pc++]; + arg = (arg << 8) + ebuf[pc++]; + gtp_action_x_setv; + break; ++ /* setv_sepecial */ ++ case OP_SETV_SPECIAL: ++ arg = ebuf[pc++]; ++ arg = (arg << 8) + ebuf[pc++]; ++ gtp_set_var_special(gts, arg, top); ++ break; + /* tracev */ + case 0x2e: + arg = ebuf[pc++]; + arg = (arg << 8) + ebuf[pc++]; + gtp_action_x_tracev; + break; ++ /* tracev_special */ ++ case OP_TRACEV_SPECIAL: ++ arg = ebuf[pc++]; ++ arg = (arg << 8) + ebuf[pc++]; ++ gtp_collect_var_special(gts, arg); ++ break; + /* printf */ + case 0x31: { + arg = ebuf[pc++]; @@ -6156,25 +6212,26 @@ + arg = ebuf[pc++]; + arg = (arg << 8) + ebuf[pc++]; + -+ if (arg == GTP_VAR_NO_SELF_TRACE_ID) { -+ tpe->no_self_trace = 1; -+ ret = 1; -+ goto release_out; -+ } -+ + if (!GTP_VAR_IS_SPECIAL(arg)) { + if (gtp_x_var_add(&vlist, arg, 1)) { + ret = -ENOMEM; + goto release_out; + } -+ } ++ } else { ++ if (arg == GTP_VAR_NO_SELF_TRACE_ID) { ++ tpe->no_self_trace = 1; ++ ret = 1; ++ goto release_out; ++ } + -+ if (arg == GTP_VAR_COOKED_CLOCK_ID) -+ gtp_access_cooked_clock = 1; ++ if (arg == GTP_VAR_COOKED_CLOCK_ID) ++ gtp_access_cooked_clock = 1; +#ifdef CONFIG_X86 -+ else if (arg == GTP_VAR_COOKED_RDTSC_ID) -+ gtp_access_cooked_rdtsc = 1; ++ else if (arg == GTP_VAR_COOKED_RDTSC_ID) ++ gtp_access_cooked_rdtsc = 1; +#endif ++ ebuf[pc - 3] = OP_GETV_SPECIAL; ++ } + } + if (ae->type == 'X') { + sp++; @@ -6229,25 +6286,25 @@ + arg = ebuf[pc++]; + arg = (arg << 8) + ebuf[pc++]; + -+ if (arg == GTP_VAR_NO_SELF_TRACE_ID) { -+ tpe->no_self_trace = 1; -+ ret = 1; -+ goto release_out; -+ } -+ + if (!GTP_VAR_IS_SPECIAL(arg)) { + if (gtp_x_var_add(&vlist, arg, 4)) { + ret = -ENOMEM; + goto release_out; + } -+ } -+ -+ if (arg == GTP_VAR_COOKED_CLOCK_ID) -+ gtp_access_cooked_clock = 1; ++ } else { ++ if (arg == GTP_VAR_NO_SELF_TRACE_ID) { ++ tpe->no_self_trace = 1; ++ ret = 1; ++ goto release_out; ++ } ++ if (arg == GTP_VAR_COOKED_CLOCK_ID) ++ gtp_access_cooked_clock = 1; +#ifdef CONFIG_X86 -+ else if (arg == GTP_VAR_COOKED_RDTSC_ID) -+ gtp_access_cooked_rdtsc = 1; ++ else if (arg == GTP_VAR_COOKED_RDTSC_ID) ++ gtp_access_cooked_rdtsc = 1; +#endif ++ ebuf[pc - 3] = OP_TRACEV_SPECIAL; ++ } + } + break; + @@ -6367,15 +6424,15 @@ + switch (ebuf[last_trace_pc]) { + /* trace */ + case 0x0c: -+ ebuf[last_trace_pc] = 0xfd; ++ ebuf[last_trace_pc] = OP_TRACE_PRINTK; + break; + /* trace_quick */ + case 0x0d: -+ ebuf[last_trace_pc] = 0xfe; ++ ebuf[last_trace_pc] = OP_TRACE_QUICK_PRINTK; + break; + /* tracev */ + case 0x2e: -+ ebuf[last_trace_pc] = 0xff; ++ ebuf[last_trace_pc] = OP_TRACEV_PRINTK; + break; + } + }