aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>2010-12-16 17:33:27 -0500
committerJeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>2011-07-18 18:43:26 -0400
commitc796f213a6934712ede728d9b53ef0e5066db23a (patch)
tree30fffcabfad42297b2d4b1f455a5f88ccf91091b
parentf04e2ee41d3dbeb6eeb3685d1b4c208b898e278f (diff)
xen/trace: add multicall tracing
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
-rw-r--r--arch/x86/include/asm/xen/hypercall.h22
-rw-r--r--arch/x86/include/asm/xen/trace_types.h18
-rw-r--r--arch/x86/xen/multicalls.c31
-rw-r--r--arch/x86/xen/multicalls.h3
-rw-r--r--arch/x86/xen/trace.c57
-rw-r--r--include/trace/events/xen.h118
6 files changed, 241 insertions, 8 deletions
diff --git a/arch/x86/include/asm/xen/hypercall.h b/arch/x86/include/asm/xen/hypercall.h
index d240ea950519..417777de5a40 100644
--- a/arch/x86/include/asm/xen/hypercall.h
+++ b/arch/x86/include/asm/xen/hypercall.h
@@ -39,6 +39,8 @@
39#include <linux/string.h> 39#include <linux/string.h>
40#include <linux/types.h> 40#include <linux/types.h>
41 41
42#include <trace/events/xen.h>
43
42#include <asm/page.h> 44#include <asm/page.h>
43#include <asm/pgtable.h> 45#include <asm/pgtable.h>
44 46
@@ -459,6 +461,8 @@ MULTI_fpu_taskswitch(struct multicall_entry *mcl, int set)
459{ 461{
460 mcl->op = __HYPERVISOR_fpu_taskswitch; 462 mcl->op = __HYPERVISOR_fpu_taskswitch;
461 mcl->args[0] = set; 463 mcl->args[0] = set;
464
465 trace_xen_mc_entry(mcl, 1);
462} 466}
463 467
464static inline void 468static inline void
@@ -475,6 +479,8 @@ MULTI_update_va_mapping(struct multicall_entry *mcl, unsigned long va,
475 mcl->args[2] = new_val.pte >> 32; 479 mcl->args[2] = new_val.pte >> 32;
476 mcl->args[3] = flags; 480 mcl->args[3] = flags;
477 } 481 }
482
483 trace_xen_mc_entry(mcl, sizeof(new_val) == sizeof(long) ? 3 : 4);
478} 484}
479 485
480static inline void 486static inline void
@@ -485,6 +491,8 @@ MULTI_grant_table_op(struct multicall_entry *mcl, unsigned int cmd,
485 mcl->args[0] = cmd; 491 mcl->args[0] = cmd;
486 mcl->args[1] = (unsigned long)uop; 492 mcl->args[1] = (unsigned long)uop;
487 mcl->args[2] = count; 493 mcl->args[2] = count;
494
495 trace_xen_mc_entry(mcl, 3);
488} 496}
489 497
490static inline void 498static inline void
@@ -504,6 +512,8 @@ MULTI_update_va_mapping_otherdomain(struct multicall_entry *mcl, unsigned long v
504 mcl->args[3] = flags; 512 mcl->args[3] = flags;
505 mcl->args[4] = domid; 513 mcl->args[4] = domid;
506 } 514 }
515
516 trace_xen_mc_entry(mcl, sizeof(new_val) == sizeof(long) ? 4 : 5);
507} 517}
508 518
509static inline void 519static inline void
@@ -520,6 +530,8 @@ MULTI_update_descriptor(struct multicall_entry *mcl, u64 maddr,
520 mcl->args[2] = desc.a; 530 mcl->args[2] = desc.a;
521 mcl->args[3] = desc.b; 531 mcl->args[3] = desc.b;
522 } 532 }
533
534 trace_xen_mc_entry(mcl, sizeof(maddr) == sizeof(long) ? 2 : 4);
523} 535}
524 536
525static inline void 537static inline void
@@ -528,6 +540,8 @@ MULTI_memory_op(struct multicall_entry *mcl, unsigned int cmd, void *arg)
528 mcl->op = __HYPERVISOR_memory_op; 540 mcl->op = __HYPERVISOR_memory_op;
529 mcl->args[0] = cmd; 541 mcl->args[0] = cmd;
530 mcl->args[1] = (unsigned long)arg; 542 mcl->args[1] = (unsigned long)arg;
543
544 trace_xen_mc_entry(mcl, 2);
531} 545}
532 546
533static inline void 547static inline void
@@ -539,6 +553,8 @@ MULTI_mmu_update(struct multicall_entry *mcl, struct mmu_update *req,
539 mcl->args[1] = count; 553 mcl->args[1] = count;
540 mcl->args[2] = (unsigned long)success_count; 554 mcl->args[2] = (unsigned long)success_count;
541 mcl->args[3] = domid; 555 mcl->args[3] = domid;
556
557 trace_xen_mc_entry(mcl, 4);
542} 558}
543 559
544static inline void 560static inline void
@@ -550,6 +566,8 @@ MULTI_mmuext_op(struct multicall_entry *mcl, struct mmuext_op *op, int count,
550 mcl->args[1] = count; 566 mcl->args[1] = count;
551 mcl->args[2] = (unsigned long)success_count; 567 mcl->args[2] = (unsigned long)success_count;
552 mcl->args[3] = domid; 568 mcl->args[3] = domid;
569
570 trace_xen_mc_entry(mcl, 4);
553} 571}
554 572
555static inline void 573static inline void
@@ -558,6 +576,8 @@ MULTI_set_gdt(struct multicall_entry *mcl, unsigned long *frames, int entries)
558 mcl->op = __HYPERVISOR_set_gdt; 576 mcl->op = __HYPERVISOR_set_gdt;
559 mcl->args[0] = (unsigned long)frames; 577 mcl->args[0] = (unsigned long)frames;
560 mcl->args[1] = entries; 578 mcl->args[1] = entries;
579
580 trace_xen_mc_entry(mcl, 2);
561} 581}
562 582
563static inline void 583static inline void
@@ -567,6 +587,8 @@ MULTI_stack_switch(struct multicall_entry *mcl,
567 mcl->op = __HYPERVISOR_stack_switch; 587 mcl->op = __HYPERVISOR_stack_switch;
568 mcl->args[0] = ss; 588 mcl->args[0] = ss;
569 mcl->args[1] = esp; 589 mcl->args[1] = esp;
590
591 trace_xen_mc_entry(mcl, 2);
570} 592}
571 593
572#endif /* _ASM_X86_XEN_HYPERCALL_H */ 594#endif /* _ASM_X86_XEN_HYPERCALL_H */
diff --git a/arch/x86/include/asm/xen/trace_types.h b/arch/x86/include/asm/xen/trace_types.h
new file mode 100644
index 000000000000..21e1874c0a0b
--- /dev/null
+++ b/arch/x86/include/asm/xen/trace_types.h
@@ -0,0 +1,18 @@
1#ifndef _ASM_XEN_TRACE_TYPES_H
2#define _ASM_XEN_TRACE_TYPES_H
3
4enum xen_mc_flush_reason {
5 XEN_MC_FL_NONE, /* explicit flush */
6 XEN_MC_FL_BATCH, /* out of hypercall space */
7 XEN_MC_FL_ARGS, /* out of argument space */
8 XEN_MC_FL_CALLBACK, /* out of callback space */
9};
10
11enum xen_mc_extend_args {
12 XEN_MC_XE_OK,
13 XEN_MC_XE_BAD_OP,
14 XEN_MC_XE_NO_SPACE
15};
16typedef void (*xen_mc_callback_fn_t)(void *);
17
18#endif /* _ASM_XEN_TRACE_TYPES_H */
diff --git a/arch/x86/xen/multicalls.c b/arch/x86/xen/multicalls.c
index b9bf19884bc5..7074c7ebfff2 100644
--- a/arch/x86/xen/multicalls.c
+++ b/arch/x86/xen/multicalls.c
@@ -65,6 +65,8 @@ void xen_mc_flush(void)
65 something in the middle */ 65 something in the middle */
66 local_irq_save(flags); 66 local_irq_save(flags);
67 67
68 trace_xen_mc_flush(b->mcidx, b->argidx, b->cbidx);
69
68 if (b->mcidx) { 70 if (b->mcidx) {
69#if MC_DEBUG 71#if MC_DEBUG
70 memcpy(b->debug, b->entries, 72 memcpy(b->debug, b->entries,
@@ -116,11 +118,15 @@ struct multicall_space __xen_mc_entry(size_t args)
116 struct multicall_space ret; 118 struct multicall_space ret;
117 unsigned argidx = roundup(b->argidx, sizeof(u64)); 119 unsigned argidx = roundup(b->argidx, sizeof(u64));
118 120
121 trace_xen_mc_entry_alloc(args);
122
119 BUG_ON(preemptible()); 123 BUG_ON(preemptible());
120 BUG_ON(b->argidx >= MC_ARGS); 124 BUG_ON(b->argidx >= MC_ARGS);
121 125
122 if (b->mcidx == MC_BATCH || 126 if (b->mcidx == MC_BATCH ||
123 (argidx + args) >= MC_ARGS) { 127 (argidx + args) >= MC_ARGS) {
128 trace_xen_mc_flush_reason((b->mcidx == MC_BATCH) ?
129 XEN_MC_FL_BATCH : XEN_MC_FL_ARGS);
124 xen_mc_flush(); 130 xen_mc_flush();
125 argidx = roundup(b->argidx, sizeof(u64)); 131 argidx = roundup(b->argidx, sizeof(u64));
126 } 132 }
@@ -145,20 +151,25 @@ struct multicall_space xen_mc_extend_args(unsigned long op, size_t size)
145 BUG_ON(preemptible()); 151 BUG_ON(preemptible());
146 BUG_ON(b->argidx >= MC_ARGS); 152 BUG_ON(b->argidx >= MC_ARGS);
147 153
148 if (b->mcidx == 0) 154 if (unlikely(b->mcidx == 0 ||
149 return ret; 155 b->entries[b->mcidx - 1].op != op)) {
150 156 trace_xen_mc_extend_args(op, size, XEN_MC_XE_BAD_OP);
151 if (b->entries[b->mcidx - 1].op != op) 157 goto out;
152 return ret; 158 }
153 159
154 if ((b->argidx + size) >= MC_ARGS) 160 if (unlikely((b->argidx + size) >= MC_ARGS)) {
155 return ret; 161 trace_xen_mc_extend_args(op, size, XEN_MC_XE_NO_SPACE);
162 goto out;
163 }
156 164
157 ret.mc = &b->entries[b->mcidx - 1]; 165 ret.mc = &b->entries[b->mcidx - 1];
158 ret.args = &b->args[b->argidx]; 166 ret.args = &b->args[b->argidx];
159 b->argidx += size; 167 b->argidx += size;
160 168
161 BUG_ON(b->argidx >= MC_ARGS); 169 BUG_ON(b->argidx >= MC_ARGS);
170
171 trace_xen_mc_extend_args(op, size, XEN_MC_XE_OK);
172out:
162 return ret; 173 return ret;
163} 174}
164 175
@@ -167,8 +178,12 @@ void xen_mc_callback(void (*fn)(void *), void *data)
167 struct mc_buffer *b = &__get_cpu_var(mc_buffer); 178 struct mc_buffer *b = &__get_cpu_var(mc_buffer);
168 struct callback *cb; 179 struct callback *cb;
169 180
170 if (b->cbidx == MC_BATCH) 181 if (b->cbidx == MC_BATCH) {
182 trace_xen_mc_flush_reason(XEN_MC_FL_CALLBACK);
171 xen_mc_flush(); 183 xen_mc_flush();
184 }
185
186 trace_xen_mc_callback(fn, data);
172 187
173 cb = &b->callbacks[b->cbidx++]; 188 cb = &b->callbacks[b->cbidx++];
174 cb->fn = fn; 189 cb->fn = fn;
diff --git a/arch/x86/xen/multicalls.h b/arch/x86/xen/multicalls.h
index fa7b8af759ee..dee79b78a90f 100644
--- a/arch/x86/xen/multicalls.h
+++ b/arch/x86/xen/multicalls.h
@@ -25,6 +25,7 @@ static inline void xen_mc_batch(void)
25 25
26 /* need to disable interrupts until this entry is complete */ 26 /* need to disable interrupts until this entry is complete */
27 local_irq_save(flags); 27 local_irq_save(flags);
28 trace_xen_mc_batch(paravirt_get_lazy_mode());
28 __this_cpu_write(xen_mc_irq_flags, flags); 29 __this_cpu_write(xen_mc_irq_flags, flags);
29} 30}
30 31
@@ -40,6 +41,8 @@ void xen_mc_flush(void);
40/* Issue a multicall if we're not in a lazy mode */ 41/* Issue a multicall if we're not in a lazy mode */
41static inline void xen_mc_issue(unsigned mode) 42static inline void xen_mc_issue(unsigned mode)
42{ 43{
44 trace_xen_mc_issue(mode);
45
43 if ((paravirt_get_lazy_mode() & mode) == 0) 46 if ((paravirt_get_lazy_mode() & mode) == 0)
44 xen_mc_flush(); 47 xen_mc_flush();
45 48
diff --git a/arch/x86/xen/trace.c b/arch/x86/xen/trace.c
index 8cca61640226..734beba2a08c 100644
--- a/arch/x86/xen/trace.c
+++ b/arch/x86/xen/trace.c
@@ -1,4 +1,61 @@
1#include <linux/ftrace.h> 1#include <linux/ftrace.h>
2 2
3#define N(x) [__HYPERVISOR_##x] = "("#x")"
4static const char *xen_hypercall_names[] = {
5 N(set_trap_table),
6 N(mmu_update),
7 N(set_gdt),
8 N(stack_switch),
9 N(set_callbacks),
10 N(fpu_taskswitch),
11 N(sched_op_compat),
12 N(dom0_op),
13 N(set_debugreg),
14 N(get_debugreg),
15 N(update_descriptor),
16 N(memory_op),
17 N(multicall),
18 N(update_va_mapping),
19 N(set_timer_op),
20 N(event_channel_op_compat),
21 N(xen_version),
22 N(console_io),
23 N(physdev_op_compat),
24 N(grant_table_op),
25 N(vm_assist),
26 N(update_va_mapping_otherdomain),
27 N(iret),
28 N(vcpu_op),
29 N(set_segment_base),
30 N(mmuext_op),
31 N(acm_op),
32 N(nmi_op),
33 N(sched_op),
34 N(callback_op),
35 N(xenoprof_op),
36 N(event_channel_op),
37 N(physdev_op),
38 N(hvm_op),
39
40/* Architecture-specific hypercall definitions. */
41 N(arch_0),
42 N(arch_1),
43 N(arch_2),
44 N(arch_3),
45 N(arch_4),
46 N(arch_5),
47 N(arch_6),
48 N(arch_7),
49};
50#undef N
51
52static const char *xen_hypercall_name(unsigned op)
53{
54 if (op < ARRAY_SIZE(xen_hypercall_names) && xen_hypercall_names[op] != NULL)
55 return xen_hypercall_names[op];
56
57 return "";
58}
59
3#define CREATE_TRACE_POINTS 60#define CREATE_TRACE_POINTS
4#include <trace/events/xen.h> 61#include <trace/events/xen.h>
diff --git a/include/trace/events/xen.h b/include/trace/events/xen.h
index 46c170c75d4e..330848269bc1 100644
--- a/include/trace/events/xen.h
+++ b/include/trace/events/xen.h
@@ -6,7 +6,125 @@
6 6
7#include <linux/tracepoint.h> 7#include <linux/tracepoint.h>
8#include <asm/paravirt_types.h> 8#include <asm/paravirt_types.h>
9#include <asm/xen/trace_types.h>
9 10
11/* Multicalls */
12
13TRACE_EVENT(xen_mc_batch,
14 TP_PROTO(enum paravirt_lazy_mode mode),
15 TP_ARGS(mode),
16 TP_STRUCT__entry(
17 __field(enum paravirt_lazy_mode, mode)
18 ),
19 TP_fast_assign(__entry->mode = mode),
20 TP_printk("start batch LAZY_%s",
21 (__entry->mode == PARAVIRT_LAZY_MMU) ? "MMU" :
22 (__entry->mode == PARAVIRT_LAZY_CPU) ? "CPU" : "NONE")
23 );
24
25TRACE_EVENT(xen_mc_issue,
26 TP_PROTO(enum paravirt_lazy_mode mode),
27 TP_ARGS(mode),
28 TP_STRUCT__entry(
29 __field(enum paravirt_lazy_mode, mode)
30 ),
31 TP_fast_assign(__entry->mode = mode),
32 TP_printk("issue mode LAZY_%s",
33 (__entry->mode == PARAVIRT_LAZY_MMU) ? "MMU" :
34 (__entry->mode == PARAVIRT_LAZY_CPU) ? "CPU" : "NONE")
35 );
36
37TRACE_EVENT(xen_mc_entry,
38 TP_PROTO(struct multicall_entry *mc, unsigned nargs),
39 TP_ARGS(mc, nargs),
40 TP_STRUCT__entry(
41 __field(unsigned int, op)
42 __field(unsigned int, nargs)
43 __array(unsigned long, args, 6)
44 ),
45 TP_fast_assign(__entry->op = mc->op;
46 __entry->nargs = nargs;
47 memcpy(__entry->args, mc->args, sizeof(unsigned long) * nargs);
48 memset(__entry->args + nargs, 0, sizeof(unsigned long) * (6 - nargs));
49 ),
50 TP_printk("op %u%s args [%lx, %lx, %lx, %lx, %lx, %lx]",
51 __entry->op, xen_hypercall_name(__entry->op),
52 __entry->args[0], __entry->args[1], __entry->args[2],
53 __entry->args[3], __entry->args[4], __entry->args[5])
54 );
55
56TRACE_EVENT(xen_mc_entry_alloc,
57 TP_PROTO(size_t args),
58 TP_ARGS(args),
59 TP_STRUCT__entry(
60 __field(size_t, args)
61 ),
62 TP_fast_assign(__entry->args = args),
63 TP_printk("alloc entry %zu arg bytes", __entry->args)
64 );
65
66TRACE_EVENT(xen_mc_callback,
67 TP_PROTO(xen_mc_callback_fn_t fn, void *data),
68 TP_ARGS(fn, data),
69 TP_STRUCT__entry(
70 __field(xen_mc_callback_fn_t, fn)
71 __field(void *, data)
72 ),
73 TP_fast_assign(
74 __entry->fn = fn;
75 __entry->data = data;
76 ),
77 TP_printk("callback %pf, data %p",
78 __entry->fn, __entry->data)
79 );
80
81TRACE_EVENT(xen_mc_flush_reason,
82 TP_PROTO(enum xen_mc_flush_reason reason),
83 TP_ARGS(reason),
84 TP_STRUCT__entry(
85 __field(enum xen_mc_flush_reason, reason)
86 ),
87 TP_fast_assign(__entry->reason = reason),
88 TP_printk("flush reason %s",
89 (__entry->reason == XEN_MC_FL_NONE) ? "NONE" :
90 (__entry->reason == XEN_MC_FL_BATCH) ? "BATCH" :
91 (__entry->reason == XEN_MC_FL_ARGS) ? "ARGS" :
92 (__entry->reason == XEN_MC_FL_CALLBACK) ? "CALLBACK" : "??")
93 );
94
95TRACE_EVENT(xen_mc_flush,
96 TP_PROTO(unsigned mcidx, unsigned argidx, unsigned cbidx),
97 TP_ARGS(mcidx, argidx, cbidx),
98 TP_STRUCT__entry(
99 __field(unsigned, mcidx)
100 __field(unsigned, argidx)
101 __field(unsigned, cbidx)
102 ),
103 TP_fast_assign(__entry->mcidx = mcidx;
104 __entry->argidx = argidx;
105 __entry->cbidx = cbidx),
106 TP_printk("flushing %u hypercalls, %u arg bytes, %u callbacks",
107 __entry->mcidx, __entry->argidx, __entry->cbidx)
108 );
109
110TRACE_EVENT(xen_mc_extend_args,
111 TP_PROTO(unsigned long op, size_t args, enum xen_mc_extend_args res),
112 TP_ARGS(op, args, res),
113 TP_STRUCT__entry(
114 __field(unsigned int, op)
115 __field(size_t, args)
116 __field(enum xen_mc_extend_args, res)
117 ),
118 TP_fast_assign(__entry->op = op;
119 __entry->args = args;
120 __entry->res = res),
121 TP_printk("extending op %u%s by %zu bytes res %s",
122 __entry->op, xen_hypercall_name(__entry->op),
123 __entry->args,
124 __entry->res == XEN_MC_XE_OK ? "OK" :
125 __entry->res == XEN_MC_XE_BAD_OP ? "BAD_OP" :
126 __entry->res == XEN_MC_XE_NO_SPACE ? "NO_SPACE" : "???")
127 );
10#endif /* _TRACE_XEN_H */ 128#endif /* _TRACE_XEN_H */
11 129
12/* This part must be outside protection */ 130/* This part must be outside protection */