-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathkvm_impl.c
More file actions
118 lines (100 loc) · 3.73 KB
/
Copy pathkvm_impl.c
File metadata and controls
118 lines (100 loc) · 3.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include <stdio.h>
#include <unistd.h>
#include <bpf/libbpf.h>
#include <bpf/bpf.h>
#include "trace.h"
#include "kvm_trace.skel.h"
#include "msr_names.h"
#include "cpuid_names.h"
static struct kvm_trace_bpf *skel = NULL;
static struct ring_buffer *rb = NULL;
struct ring_buffer *trace_init_rb(handle_event_t handler, int flags, int verbose)
{
int err;
skel = kvm_trace_bpf__open();
if (!skel) {
fprintf(stderr, "Failed to open BPF skeleton (Do you have permissions?)\n");
return NULL;
}
skel->rodata->verbose = verbose;
err = kvm_trace_bpf__load(skel);
if (err) {
fprintf(stderr, "Failed to load BPF skeleton (Do you have permissions?)\n");
kvm_trace_bpf__destroy(skel);
return NULL;
}
if (flags & TRACE_MSR) {
skel->links.tp_kvm_msr = bpf_program__attach(skel->progs.tp_kvm_msr);
skel->links.tp_kvm_inj_exception = bpf_program__attach(skel->progs.tp_kvm_inj_exception);
skel->links.tp_kvm_entry = bpf_program__attach(skel->progs.tp_kvm_entry);
}
if (flags & TRACE_CPUID) {
skel->links.tp_kvm_cpuid = bpf_program__attach(skel->progs.tp_kvm_cpuid);
}
if (flags & (TRACE_MSR | TRACE_CPUID)) {
skel->links.tp_kvm_exit = bpf_program__attach(skel->progs.tp_kvm_exit);
}
rb = ring_buffer__new(bpf_map__fd(skel->maps.rb), handler, NULL, NULL);
if (!rb) {
fprintf(stderr, "Failed to create ring buffer\n");
kvm_trace_bpf__destroy(skel);
return NULL;
}
return rb;
}
void trace_apply_filters(unsigned int *filters, int count)
{
if (!skel || count <= 0) return;
int config_fd = bpf_map__fd(skel->maps.filter_config);
__u32 key = 0;
__u32 val = 1;
bpf_map_update_elem(config_fd, &key, &val, BPF_ANY);
int map_fd = bpf_map__fd(skel->maps.filter_msr);
__u8 allowed = 1;
for (int i = 0; i < count; i++) {
__u32 msr_index = filters[i];
bpf_map_update_elem(map_fd, &msr_index, &allowed, BPF_ANY);
}
}
void trace_cleanup(void)
{
if (rb) ring_buffer__free(rb);
if (skel) kvm_trace_bpf__destroy(skel);
}
int trace_get_dropped_fd(void)
{
if (!skel) return -1;
return bpf_map__fd(skel->maps.dropped);
}
void trace_print(struct event *e, char prefix, unsigned long long current_time_ns, int dedupe_mode)
{
unsigned int ago_ms = (current_time_ns - e->ts) / 1000000;
double ts_sec = (double)e->ts / 1000000000.0;
const char *name = "";
char buf[256];
switch (e->kind) {
case EVENT_KIND_MSR: {
const char *mode = e->type ? "WR" : "RD";
name = get_msr_name(e->index);
char val_str[64];
snprintf(val_str, sizeof(val_str), "0x%016llx", e->value);
// if we have an MSR fault, lets adjust the value
if (e->result) snprintf(val_str, sizeof(val_str), "FAULT (Except #%d)", e->exception);
snprintf(buf, sizeof(buf), "%c%sMSR: 0x%08x RIP: 0x%016llx EAX: 0x%08llx EDX: 0x%08llx Value: %s",
prefix, mode, e->index, e->rip,
e->value & 0xFFFFFFFF, e->value >> 32, val_str);
break;
}
case EVENT_KIND_CPUID: {
name = get_cpuid_name(e->index);
snprintf(buf, sizeof(buf), "%cCPUID: 0x%08x RIP: 0x%016llx EAX: 0x%08llx EBX: 0x%08llx ECX: 0x%08llx EDX: 0x%08llx",
prefix, e->index, e->rip,
e->value & 0xFFFFFFFF, e->value >> 32,
e->value_extra & 0xFFFFFFFF, e->value_extra >> 32);
break;
}
}
// print trailing information, pad to 106 columns so arrows align
if (dedupe_mode) printf("%-106s -> %7u ms ago (%s)\n", buf, ago_ms, name);
else printf("%-106s -> [%.6f] (%s)\n", buf, ts_sec, name);
}