diff options
-rw-r--r-- | include/linux/kvm.h | 17 | ||||
-rw-r--r-- | virt/kvm/kvm_trace.c | 17 |
2 files changed, 23 insertions, 11 deletions
diff --git a/include/linux/kvm.h b/include/linux/kvm.h index 8a3ceadb136..8a16b083df2 100644 --- a/include/linux/kvm.h +++ b/include/linux/kvm.h | |||
@@ -311,9 +311,13 @@ struct kvm_s390_interrupt { | |||
311 | 311 | ||
312 | /* This structure represents a single trace buffer record. */ | 312 | /* This structure represents a single trace buffer record. */ |
313 | struct kvm_trace_rec { | 313 | struct kvm_trace_rec { |
314 | __u32 event:28; | 314 | /* variable rec_val |
315 | __u32 extra_u32:3; | 315 | * is split into: |
316 | __u32 cycle_in:1; | 316 | * bits 0 - 27 -> event id |
317 | * bits 28 -30 -> number of extra data args of size u32 | ||
318 | * bits 31 -> binary indicator for if tsc is in record | ||
319 | */ | ||
320 | __u32 rec_val; | ||
317 | __u32 pid; | 321 | __u32 pid; |
318 | __u32 vcpu_id; | 322 | __u32 vcpu_id; |
319 | union { | 323 | union { |
@@ -327,6 +331,13 @@ struct kvm_trace_rec { | |||
327 | } u; | 331 | } u; |
328 | }; | 332 | }; |
329 | 333 | ||
334 | #define TRACE_REC_EVENT_ID(val) \ | ||
335 | (0x0fffffff & (val)) | ||
336 | #define TRACE_REC_NUM_DATA_ARGS(val) \ | ||
337 | (0x70000000 & ((val) << 28)) | ||
338 | #define TRACE_REC_TCS(val) \ | ||
339 | (0x80000000 & ((val) << 31)) | ||
340 | |||
330 | #define KVMIO 0xAE | 341 | #define KVMIO 0xAE |
331 | 342 | ||
332 | /* | 343 | /* |
diff --git a/virt/kvm/kvm_trace.c b/virt/kvm/kvm_trace.c index 58141f31ea8..9acb78b3cc9 100644 --- a/virt/kvm/kvm_trace.c +++ b/virt/kvm/kvm_trace.c | |||
@@ -54,12 +54,13 @@ static void kvm_add_trace(void *probe_private, void *call_data, | |||
54 | struct kvm_trace *kt = kvm_trace; | 54 | struct kvm_trace *kt = kvm_trace; |
55 | struct kvm_trace_rec rec; | 55 | struct kvm_trace_rec rec; |
56 | struct kvm_vcpu *vcpu; | 56 | struct kvm_vcpu *vcpu; |
57 | int i, extra, size; | 57 | int i, size; |
58 | u32 extra; | ||
58 | 59 | ||
59 | if (unlikely(kt->trace_state != KVM_TRACE_STATE_RUNNING)) | 60 | if (unlikely(kt->trace_state != KVM_TRACE_STATE_RUNNING)) |
60 | return; | 61 | return; |
61 | 62 | ||
62 | rec.event = va_arg(*args, u32); | 63 | rec.rec_val = TRACE_REC_EVENT_ID(va_arg(*args, u32)); |
63 | vcpu = va_arg(*args, struct kvm_vcpu *); | 64 | vcpu = va_arg(*args, struct kvm_vcpu *); |
64 | rec.pid = current->tgid; | 65 | rec.pid = current->tgid; |
65 | rec.vcpu_id = vcpu->vcpu_id; | 66 | rec.vcpu_id = vcpu->vcpu_id; |
@@ -67,21 +68,21 @@ static void kvm_add_trace(void *probe_private, void *call_data, | |||
67 | extra = va_arg(*args, u32); | 68 | extra = va_arg(*args, u32); |
68 | WARN_ON(!(extra <= KVM_TRC_EXTRA_MAX)); | 69 | WARN_ON(!(extra <= KVM_TRC_EXTRA_MAX)); |
69 | extra = min_t(u32, extra, KVM_TRC_EXTRA_MAX); | 70 | extra = min_t(u32, extra, KVM_TRC_EXTRA_MAX); |
70 | rec.extra_u32 = extra; | ||
71 | 71 | ||
72 | rec.cycle_in = p->cycle_in; | 72 | rec.rec_val |= TRACE_REC_TCS(p->cycle_in) |
73 | | TRACE_REC_NUM_DATA_ARGS(extra); | ||
73 | 74 | ||
74 | if (rec.cycle_in) { | 75 | if (p->cycle_in) { |
75 | rec.u.cycle.cycle_u64 = get_cycles(); | 76 | rec.u.cycle.cycle_u64 = get_cycles(); |
76 | 77 | ||
77 | for (i = 0; i < rec.extra_u32; i++) | 78 | for (i = 0; i < extra; i++) |
78 | rec.u.cycle.extra_u32[i] = va_arg(*args, u32); | 79 | rec.u.cycle.extra_u32[i] = va_arg(*args, u32); |
79 | } else { | 80 | } else { |
80 | for (i = 0; i < rec.extra_u32; i++) | 81 | for (i = 0; i < extra; i++) |
81 | rec.u.nocycle.extra_u32[i] = va_arg(*args, u32); | 82 | rec.u.nocycle.extra_u32[i] = va_arg(*args, u32); |
82 | } | 83 | } |
83 | 84 | ||
84 | size = calc_rec_size(rec.cycle_in, rec.extra_u32 * sizeof(u32)); | 85 | size = calc_rec_size(p->cycle_in, extra * sizeof(u32)); |
85 | relay_write(kt->rchan, &rec, size); | 86 | relay_write(kt->rchan, &rec, size); |
86 | } | 87 | } |
87 | 88 | ||