aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/ia64/kvm/Kconfig3
-rw-r--r--arch/powerpc/kvm/Kconfig11
-rw-r--r--arch/powerpc/kvm/Makefile2
-rw-r--r--arch/s390/kvm/Kconfig3
-rw-r--r--arch/x86/kvm/Kconfig12
-rw-r--r--arch/x86/kvm/Makefile1
-rw-r--r--include/linux/kvm.h31
-rw-r--r--include/linux/kvm_host.h31
-rw-r--r--virt/kvm/kvm_main.c3
-rw-r--r--virt/kvm/kvm_trace.c285
10 files changed, 2 insertions, 380 deletions
diff --git a/arch/ia64/kvm/Kconfig b/arch/ia64/kvm/Kconfig
index cbadd8a65233..ef3e7be29caf 100644
--- a/arch/ia64/kvm/Kconfig
+++ b/arch/ia64/kvm/Kconfig
@@ -47,9 +47,6 @@ config KVM_INTEL
47 Provides support for KVM on Itanium 2 processors equipped with the VT 47 Provides support for KVM on Itanium 2 processors equipped with the VT
48 extensions. 48 extensions.
49 49
50config KVM_TRACE
51 bool
52
53source drivers/virtio/Kconfig 50source drivers/virtio/Kconfig
54 51
55endif # VIRTUALIZATION 52endif # VIRTUALIZATION
diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig
index 46019dccce1c..c29926846613 100644
--- a/arch/powerpc/kvm/Kconfig
+++ b/arch/powerpc/kvm/Kconfig
@@ -58,17 +58,6 @@ config KVM_E500
58 58
59 If unsure, say N. 59 If unsure, say N.
60 60
61config KVM_TRACE
62 bool "KVM trace support"
63 depends on KVM && MARKERS && SYSFS
64 select RELAY
65 select DEBUG_FS
66 default n
67 ---help---
68 This option allows reading a trace of kvm-related events through
69 relayfs. Note the ABI is not considered stable and will be
70 modified in future updates.
71
72source drivers/virtio/Kconfig 61source drivers/virtio/Kconfig
73 62
74endif # VIRTUALIZATION 63endif # VIRTUALIZATION
diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile
index 4f407f2662f7..37655fe19f2f 100644
--- a/arch/powerpc/kvm/Makefile
+++ b/arch/powerpc/kvm/Makefile
@@ -8,8 +8,6 @@ EXTRA_CFLAGS += -Ivirt/kvm -Iarch/powerpc/kvm
8 8
9common-objs-y = $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o) 9common-objs-y = $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o)
10 10
11common-objs-$(CONFIG_KVM_TRACE) += $(addprefix ../../../virt/kvm/, kvm_trace.o)
12
13CFLAGS_44x_tlb.o := -I. 11CFLAGS_44x_tlb.o := -I.
14CFLAGS_e500_tlb.o := -I. 12CFLAGS_e500_tlb.o := -I.
15CFLAGS_emulate.o := -I. 13CFLAGS_emulate.o := -I.
diff --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig
index ad75ce33be12..bf164fc21864 100644
--- a/arch/s390/kvm/Kconfig
+++ b/arch/s390/kvm/Kconfig
@@ -34,9 +34,6 @@ config KVM
34 34
35 If unsure, say N. 35 If unsure, say N.
36 36
37config KVM_TRACE
38 bool
39
40# OK, it's a little counter-intuitive to do this, but it puts it neatly under 37# OK, it's a little counter-intuitive to do this, but it puts it neatly under
41# the virtualization menu. 38# the virtualization menu.
42source drivers/virtio/Kconfig 39source drivers/virtio/Kconfig
diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig
index 7fbedfd34d6c..b84e571f4175 100644
--- a/arch/x86/kvm/Kconfig
+++ b/arch/x86/kvm/Kconfig
@@ -62,18 +62,6 @@ config KVM_AMD
62 To compile this as a module, choose M here: the module 62 To compile this as a module, choose M here: the module
63 will be called kvm-amd. 63 will be called kvm-amd.
64 64
65config KVM_TRACE
66 bool "KVM trace support"
67 depends on KVM && SYSFS
68 select MARKERS
69 select RELAY
70 select DEBUG_FS
71 default n
72 ---help---
73 This option allows reading a trace of kvm-related events through
74 relayfs. Note the ABI is not considered stable and will be
75 modified in future updates.
76
77# OK, it's a little counter-intuitive to do this, but it puts it neatly under 65# OK, it's a little counter-intuitive to do this, but it puts it neatly under
78# the virtualization menu. 66# the virtualization menu.
79source drivers/lguest/Kconfig 67source drivers/lguest/Kconfig
diff --git a/arch/x86/kvm/Makefile b/arch/x86/kvm/Makefile
index 7c56850b82cb..afaaa7627d95 100644
--- a/arch/x86/kvm/Makefile
+++ b/arch/x86/kvm/Makefile
@@ -7,7 +7,6 @@ CFLAGS_vmx.o := -I.
7 7
8kvm-y += $(addprefix ../../../virt/kvm/, kvm_main.o ioapic.o \ 8kvm-y += $(addprefix ../../../virt/kvm/, kvm_main.o ioapic.o \
9 coalesced_mmio.o irq_comm.o eventfd.o) 9 coalesced_mmio.o irq_comm.o eventfd.o)
10kvm-$(CONFIG_KVM_TRACE) += $(addprefix ../../../virt/kvm/, kvm_trace.o)
11kvm-$(CONFIG_IOMMU_API) += $(addprefix ../../../virt/kvm/, iommu.o) 10kvm-$(CONFIG_IOMMU_API) += $(addprefix ../../../virt/kvm/, iommu.o)
12 11
13kvm-y += x86.o mmu.o x86_emulate.o i8259.o irq.o lapic.o \ 12kvm-y += x86.o mmu.o x86_emulate.o i8259.o irq.o lapic.o \
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index 671051829da6..76c640834ea6 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -14,7 +14,7 @@
14 14
15#define KVM_API_VERSION 12 15#define KVM_API_VERSION 12
16 16
17/* for KVM_TRACE_ENABLE */ 17/* for KVM_TRACE_ENABLE, deprecated */
18struct kvm_user_trace_setup { 18struct kvm_user_trace_setup {
19 __u32 buf_size; /* sub_buffer size of each per-cpu */ 19 __u32 buf_size; /* sub_buffer size of each per-cpu */
20 __u32 buf_nr; /* the number of sub_buffers of each per-cpu */ 20 __u32 buf_nr; /* the number of sub_buffers of each per-cpu */
@@ -325,35 +325,6 @@ struct kvm_guest_debug {
325#define KVM_TRC_CYCLE_SIZE 8 325#define KVM_TRC_CYCLE_SIZE 8
326#define KVM_TRC_EXTRA_MAX 7 326#define KVM_TRC_EXTRA_MAX 7
327 327
328/* This structure represents a single trace buffer record. */
329struct kvm_trace_rec {
330 /* variable rec_val
331 * is split into:
332 * bits 0 - 27 -> event id
333 * bits 28 -30 -> number of extra data args of size u32
334 * bits 31 -> binary indicator for if tsc is in record
335 */
336 __u32 rec_val;
337 __u32 pid;
338 __u32 vcpu_id;
339 union {
340 struct {
341 __u64 timestamp;
342 __u32 extra_u32[KVM_TRC_EXTRA_MAX];
343 } __attribute__((packed)) timestamp;
344 struct {
345 __u32 extra_u32[KVM_TRC_EXTRA_MAX];
346 } notimestamp;
347 } u;
348};
349
350#define TRACE_REC_EVENT_ID(val) \
351 (0x0fffffff & (val))
352#define TRACE_REC_NUM_DATA_ARGS(val) \
353 (0x70000000 & ((val) << 28))
354#define TRACE_REC_TCS(val) \
355 (0x80000000 & ((val) << 31))
356
357#define KVMIO 0xAE 328#define KVMIO 0xAE
358 329
359/* 330/*
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 06af936a250a..0604d56f6eed 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -482,37 +482,6 @@ struct kvm_stats_debugfs_item {
482extern struct kvm_stats_debugfs_item debugfs_entries[]; 482extern struct kvm_stats_debugfs_item debugfs_entries[];
483extern struct dentry *kvm_debugfs_dir; 483extern struct dentry *kvm_debugfs_dir;
484 484
485#define KVMTRACE_5D(evt, vcpu, d1, d2, d3, d4, d5, name) \
486 trace_mark(kvm_trace_##name, "%u %p %u %u %u %u %u %u", KVM_TRC_##evt, \
487 vcpu, 5, d1, d2, d3, d4, d5)
488#define KVMTRACE_4D(evt, vcpu, d1, d2, d3, d4, name) \
489 trace_mark(kvm_trace_##name, "%u %p %u %u %u %u %u %u", KVM_TRC_##evt, \
490 vcpu, 4, d1, d2, d3, d4, 0)
491#define KVMTRACE_3D(evt, vcpu, d1, d2, d3, name) \
492 trace_mark(kvm_trace_##name, "%u %p %u %u %u %u %u %u", KVM_TRC_##evt, \
493 vcpu, 3, d1, d2, d3, 0, 0)
494#define KVMTRACE_2D(evt, vcpu, d1, d2, name) \
495 trace_mark(kvm_trace_##name, "%u %p %u %u %u %u %u %u", KVM_TRC_##evt, \
496 vcpu, 2, d1, d2, 0, 0, 0)
497#define KVMTRACE_1D(evt, vcpu, d1, name) \
498 trace_mark(kvm_trace_##name, "%u %p %u %u %u %u %u %u", KVM_TRC_##evt, \
499 vcpu, 1, d1, 0, 0, 0, 0)
500#define KVMTRACE_0D(evt, vcpu, name) \
501 trace_mark(kvm_trace_##name, "%u %p %u %u %u %u %u %u", KVM_TRC_##evt, \
502 vcpu, 0, 0, 0, 0, 0, 0)
503
504#ifdef CONFIG_KVM_TRACE
505int kvm_trace_ioctl(unsigned int ioctl, unsigned long arg);
506void kvm_trace_cleanup(void);
507#else
508static inline
509int kvm_trace_ioctl(unsigned int ioctl, unsigned long arg)
510{
511 return -EINVAL;
512}
513#define kvm_trace_cleanup() ((void)0)
514#endif
515
516#ifdef KVM_ARCH_WANT_MMU_NOTIFIER 485#ifdef KVM_ARCH_WANT_MMU_NOTIFIER
517static inline int mmu_notifier_retry(struct kvm_vcpu *vcpu, unsigned long mmu_seq) 486static inline int mmu_notifier_retry(struct kvm_vcpu *vcpu, unsigned long mmu_seq)
518{ 487{
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index f1e2e8c373c6..bbb4029d7c4d 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -2398,7 +2398,7 @@ static long kvm_dev_ioctl(struct file *filp,
2398 case KVM_TRACE_ENABLE: 2398 case KVM_TRACE_ENABLE:
2399 case KVM_TRACE_PAUSE: 2399 case KVM_TRACE_PAUSE:
2400 case KVM_TRACE_DISABLE: 2400 case KVM_TRACE_DISABLE:
2401 r = kvm_trace_ioctl(ioctl, arg); 2401 r = -EOPNOTSUPP;
2402 break; 2402 break;
2403 default: 2403 default:
2404 return kvm_arch_dev_ioctl(filp, ioctl, arg); 2404 return kvm_arch_dev_ioctl(filp, ioctl, arg);
@@ -2748,7 +2748,6 @@ EXPORT_SYMBOL_GPL(kvm_init);
2748 2748
2749void kvm_exit(void) 2749void kvm_exit(void)
2750{ 2750{
2751 kvm_trace_cleanup();
2752 tracepoint_synchronize_unregister(); 2751 tracepoint_synchronize_unregister();
2753 misc_deregister(&kvm_dev); 2752 misc_deregister(&kvm_dev);
2754 kmem_cache_destroy(kvm_vcpu_cache); 2753 kmem_cache_destroy(kvm_vcpu_cache);
diff --git a/virt/kvm/kvm_trace.c b/virt/kvm/kvm_trace.c
deleted file mode 100644
index f59874446440..000000000000
--- a/virt/kvm/kvm_trace.c
+++ /dev/null
@@ -1,285 +0,0 @@
1/*
2 * kvm trace
3 *
4 * It is designed to allow debugging traces of kvm to be generated
5 * on UP / SMP machines. Each trace entry can be timestamped so that
6 * it's possible to reconstruct a chronological record of trace events.
7 * The implementation refers to blktrace kernel support.
8 *
9 * Copyright (c) 2008 Intel Corporation
10 * Copyright (C) 2006 Jens Axboe <axboe@kernel.dk>
11 *
12 * Authors: Feng(Eric) Liu, eric.e.liu@intel.com
13 *
14 * Date: Feb 2008
15 */
16
17#include <linux/module.h>
18#include <linux/relay.h>
19#include <linux/debugfs.h>
20#include <linux/ktime.h>
21
22#include <linux/kvm_host.h>
23
24#define KVM_TRACE_STATE_RUNNING (1 << 0)
25#define KVM_TRACE_STATE_PAUSE (1 << 1)
26#define KVM_TRACE_STATE_CLEARUP (1 << 2)
27
28struct kvm_trace {
29 int trace_state;
30 struct rchan *rchan;
31 struct dentry *lost_file;
32 atomic_t lost_records;
33};
34static struct kvm_trace *kvm_trace;
35
36struct kvm_trace_probe {
37 const char *name;
38 const char *format;
39 u32 timestamp_in;
40 marker_probe_func *probe_func;
41};
42
43static inline int calc_rec_size(int timestamp, int extra)
44{
45 int rec_size = KVM_TRC_HEAD_SIZE;
46
47 rec_size += extra;
48 return timestamp ? rec_size += KVM_TRC_CYCLE_SIZE : rec_size;
49}
50
51static void kvm_add_trace(void *probe_private, void *call_data,
52 const char *format, va_list *args)
53{
54 struct kvm_trace_probe *p = probe_private;
55 struct kvm_trace *kt = kvm_trace;
56 struct kvm_trace_rec rec;
57 struct kvm_vcpu *vcpu;
58 int i, size;
59 u32 extra;
60
61 if (unlikely(kt->trace_state != KVM_TRACE_STATE_RUNNING))
62 return;
63
64 rec.rec_val = TRACE_REC_EVENT_ID(va_arg(*args, u32));
65 vcpu = va_arg(*args, struct kvm_vcpu *);
66 rec.pid = current->tgid;
67 rec.vcpu_id = vcpu->vcpu_id;
68
69 extra = va_arg(*args, u32);
70 WARN_ON(!(extra <= KVM_TRC_EXTRA_MAX));
71 extra = min_t(u32, extra, KVM_TRC_EXTRA_MAX);
72
73 rec.rec_val |= TRACE_REC_TCS(p->timestamp_in)
74 | TRACE_REC_NUM_DATA_ARGS(extra);
75
76 if (p->timestamp_in) {
77 rec.u.timestamp.timestamp = ktime_to_ns(ktime_get());
78
79 for (i = 0; i < extra; i++)
80 rec.u.timestamp.extra_u32[i] = va_arg(*args, u32);
81 } else {
82 for (i = 0; i < extra; i++)
83 rec.u.notimestamp.extra_u32[i] = va_arg(*args, u32);
84 }
85
86 size = calc_rec_size(p->timestamp_in, extra * sizeof(u32));
87 relay_write(kt->rchan, &rec, size);
88}
89
90static struct kvm_trace_probe kvm_trace_probes[] = {
91 { "kvm_trace_entryexit", "%u %p %u %u %u %u %u %u", 1, kvm_add_trace },
92 { "kvm_trace_handler", "%u %p %u %u %u %u %u %u", 0, kvm_add_trace },
93};
94
95static int lost_records_get(void *data, u64 *val)
96{
97 struct kvm_trace *kt = data;
98
99 *val = atomic_read(&kt->lost_records);
100 return 0;
101}
102
103DEFINE_SIMPLE_ATTRIBUTE(kvm_trace_lost_ops, lost_records_get, NULL, "%llu\n");
104
105/*
106 * The relay channel is used in "no-overwrite" mode, it keeps trace of how
107 * many times we encountered a full subbuffer, to tell user space app the
108 * lost records there were.
109 */
110static int kvm_subbuf_start_callback(struct rchan_buf *buf, void *subbuf,
111 void *prev_subbuf, size_t prev_padding)
112{
113 struct kvm_trace *kt;
114
115 if (!relay_buf_full(buf)) {
116 if (!prev_subbuf) {
117 /*
118 * executed only once when the channel is opened
119 * save metadata as first record
120 */
121 subbuf_start_reserve(buf, sizeof(u32));
122 *(u32 *)subbuf = 0x12345678;
123 }
124
125 return 1;
126 }
127
128 kt = buf->chan->private_data;
129 atomic_inc(&kt->lost_records);
130
131 return 0;
132}
133
134static struct dentry *kvm_create_buf_file_callack(const char *filename,
135 struct dentry *parent,
136 int mode,
137 struct rchan_buf *buf,
138 int *is_global)
139{
140 return debugfs_create_file(filename, mode, parent, buf,
141 &relay_file_operations);
142}
143
144static int kvm_remove_buf_file_callback(struct dentry *dentry)
145{
146 debugfs_remove(dentry);
147 return 0;
148}
149
150static struct rchan_callbacks kvm_relay_callbacks = {
151 .subbuf_start = kvm_subbuf_start_callback,
152 .create_buf_file = kvm_create_buf_file_callack,
153 .remove_buf_file = kvm_remove_buf_file_callback,
154};
155
156static int do_kvm_trace_enable(struct kvm_user_trace_setup *kuts)
157{
158 struct kvm_trace *kt;
159 int i, r = -ENOMEM;
160
161 if (!kuts->buf_size || !kuts->buf_nr)
162 return -EINVAL;
163
164 kt = kzalloc(sizeof(*kt), GFP_KERNEL);
165 if (!kt)
166 goto err;
167
168 r = -EIO;
169 atomic_set(&kt->lost_records, 0);
170 kt->lost_file = debugfs_create_file("lost_records", 0444, kvm_debugfs_dir,
171 kt, &kvm_trace_lost_ops);
172 if (!kt->lost_file)
173 goto err;
174
175 kt->rchan = relay_open("trace", kvm_debugfs_dir, kuts->buf_size,
176 kuts->buf_nr, &kvm_relay_callbacks, kt);
177 if (!kt->rchan)
178 goto err;
179
180 kvm_trace = kt;
181
182 for (i = 0; i < ARRAY_SIZE(kvm_trace_probes); i++) {
183 struct kvm_trace_probe *p = &kvm_trace_probes[i];
184
185 r = marker_probe_register(p->name, p->format, p->probe_func, p);
186 if (r)
187 printk(KERN_INFO "Unable to register probe %s\n",
188 p->name);
189 }
190
191 kvm_trace->trace_state = KVM_TRACE_STATE_RUNNING;
192
193 return 0;
194err:
195 if (kt) {
196 if (kt->lost_file)
197 debugfs_remove(kt->lost_file);
198 if (kt->rchan)
199 relay_close(kt->rchan);
200 kfree(kt);
201 }
202 return r;
203}
204
205static int kvm_trace_enable(char __user *arg)
206{
207 struct kvm_user_trace_setup kuts;
208 int ret;
209
210 ret = copy_from_user(&kuts, arg, sizeof(kuts));
211 if (ret)
212 return -EFAULT;
213
214 ret = do_kvm_trace_enable(&kuts);
215 if (ret)
216 return ret;
217
218 return 0;
219}
220
221static int kvm_trace_pause(void)
222{
223 struct kvm_trace *kt = kvm_trace;
224 int r = -EINVAL;
225
226 if (kt == NULL)
227 return r;
228
229 if (kt->trace_state == KVM_TRACE_STATE_RUNNING) {
230 kt->trace_state = KVM_TRACE_STATE_PAUSE;
231 relay_flush(kt->rchan);
232 r = 0;
233 }
234
235 return r;
236}
237
238void kvm_trace_cleanup(void)
239{
240 struct kvm_trace *kt = kvm_trace;
241 int i;
242
243 if (kt == NULL)
244 return;
245
246 if (kt->trace_state == KVM_TRACE_STATE_RUNNING ||
247 kt->trace_state == KVM_TRACE_STATE_PAUSE) {
248
249 kt->trace_state = KVM_TRACE_STATE_CLEARUP;
250
251 for (i = 0; i < ARRAY_SIZE(kvm_trace_probes); i++) {
252 struct kvm_trace_probe *p = &kvm_trace_probes[i];
253 marker_probe_unregister(p->name, p->probe_func, p);
254 }
255 marker_synchronize_unregister();
256
257 relay_close(kt->rchan);
258 debugfs_remove(kt->lost_file);
259 kfree(kt);
260 }
261}
262
263int kvm_trace_ioctl(unsigned int ioctl, unsigned long arg)
264{
265 void __user *argp = (void __user *)arg;
266 long r = -EINVAL;
267
268 if (!capable(CAP_SYS_ADMIN))
269 return -EPERM;
270
271 switch (ioctl) {
272 case KVM_TRACE_ENABLE:
273 r = kvm_trace_enable(argp);
274 break;
275 case KVM_TRACE_PAUSE:
276 r = kvm_trace_pause();
277 break;
278 case KVM_TRACE_DISABLE:
279 r = 0;
280 kvm_trace_cleanup();
281 break;
282 }
283
284 return r;
285}