~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/perf/arch/x86/util/kvm-stat.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 #include <errno.h>
  3 #include <string.h>
  4 #include "../../../util/kvm-stat.h"
  5 #include "../../../util/evsel.h"
  6 #include <asm/svm.h>
  7 #include <asm/vmx.h>
  8 #include <asm/kvm.h>
  9 
 10 define_exit_reasons_table(vmx_exit_reasons, VMX_EXIT_REASONS);
 11 define_exit_reasons_table(svm_exit_reasons, SVM_EXIT_REASONS);
 12 
 13 static struct kvm_events_ops exit_events = {
 14         .is_begin_event = exit_event_begin,
 15         .is_end_event = exit_event_end,
 16         .decode_key = exit_event_decode_key,
 17         .name = "VM-EXIT"
 18 };
 19 
 20 const char *vcpu_id_str = "vcpu_id";
 21 const char *kvm_exit_reason = "exit_reason";
 22 const char *kvm_entry_trace = "kvm:kvm_entry";
 23 const char *kvm_exit_trace = "kvm:kvm_exit";
 24 
 25 /*
 26  * For the mmio events, we treat:
 27  * the time of MMIO write: kvm_mmio(KVM_TRACE_MMIO_WRITE...) -> kvm_entry
 28  * the time of MMIO read: kvm_exit -> kvm_mmio(KVM_TRACE_MMIO_READ...).
 29  */
 30 static void mmio_event_get_key(struct evsel *evsel, struct perf_sample *sample,
 31                                struct event_key *key)
 32 {
 33         key->key  = evsel__intval(evsel, sample, "gpa");
 34         key->info = evsel__intval(evsel, sample, "type");
 35 }
 36 
 37 #define KVM_TRACE_MMIO_READ_UNSATISFIED 0
 38 #define KVM_TRACE_MMIO_READ 1
 39 #define KVM_TRACE_MMIO_WRITE 2
 40 
 41 static bool mmio_event_begin(struct evsel *evsel,
 42                              struct perf_sample *sample, struct event_key *key)
 43 {
 44         /* MMIO read begin event in kernel. */
 45         if (kvm_exit_event(evsel))
 46                 return true;
 47 
 48         /* MMIO write begin event in kernel. */
 49         if (evsel__name_is(evsel, "kvm:kvm_mmio") &&
 50             evsel__intval(evsel, sample, "type") == KVM_TRACE_MMIO_WRITE) {
 51                 mmio_event_get_key(evsel, sample, key);
 52                 return true;
 53         }
 54 
 55         return false;
 56 }
 57 
 58 static bool mmio_event_end(struct evsel *evsel, struct perf_sample *sample,
 59                            struct event_key *key)
 60 {
 61         /* MMIO write end event in kernel. */
 62         if (kvm_entry_event(evsel))
 63                 return true;
 64 
 65         /* MMIO read end event in kernel.*/
 66         if (evsel__name_is(evsel, "kvm:kvm_mmio") &&
 67             evsel__intval(evsel, sample, "type") == KVM_TRACE_MMIO_READ) {
 68                 mmio_event_get_key(evsel, sample, key);
 69                 return true;
 70         }
 71 
 72         return false;
 73 }
 74 
 75 static void mmio_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused,
 76                                   struct event_key *key,
 77                                   char *decode)
 78 {
 79         scnprintf(decode, KVM_EVENT_NAME_LEN, "%#lx:%s",
 80                   (unsigned long)key->key,
 81                   key->info == KVM_TRACE_MMIO_WRITE ? "W" : "R");
 82 }
 83 
 84 static struct kvm_events_ops mmio_events = {
 85         .is_begin_event = mmio_event_begin,
 86         .is_end_event = mmio_event_end,
 87         .decode_key = mmio_event_decode_key,
 88         .name = "MMIO Access"
 89 };
 90 
 91  /* The time of emulation pio access is from kvm_pio to kvm_entry. */
 92 static void ioport_event_get_key(struct evsel *evsel,
 93                                  struct perf_sample *sample,
 94                                  struct event_key *key)
 95 {
 96         key->key  = evsel__intval(evsel, sample, "port");
 97         key->info = evsel__intval(evsel, sample, "rw");
 98 }
 99 
100 static bool ioport_event_begin(struct evsel *evsel,
101                                struct perf_sample *sample,
102                                struct event_key *key)
103 {
104         if (evsel__name_is(evsel, "kvm:kvm_pio")) {
105                 ioport_event_get_key(evsel, sample, key);
106                 return true;
107         }
108 
109         return false;
110 }
111 
112 static bool ioport_event_end(struct evsel *evsel,
113                              struct perf_sample *sample __maybe_unused,
114                              struct event_key *key __maybe_unused)
115 {
116         return kvm_entry_event(evsel);
117 }
118 
119 static void ioport_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused,
120                                     struct event_key *key,
121                                     char *decode)
122 {
123         scnprintf(decode, KVM_EVENT_NAME_LEN, "%#llx:%s",
124                   (unsigned long long)key->key,
125                   key->info ? "POUT" : "PIN");
126 }
127 
128 static struct kvm_events_ops ioport_events = {
129         .is_begin_event = ioport_event_begin,
130         .is_end_event = ioport_event_end,
131         .decode_key = ioport_event_decode_key,
132         .name = "IO Port Access"
133 };
134 
135  /* The time of emulation msr is from kvm_msr to kvm_entry. */
136 static void msr_event_get_key(struct evsel *evsel,
137                                  struct perf_sample *sample,
138                                  struct event_key *key)
139 {
140         key->key  = evsel__intval(evsel, sample, "ecx");
141         key->info = evsel__intval(evsel, sample, "write");
142 }
143 
144 static bool msr_event_begin(struct evsel *evsel,
145                                struct perf_sample *sample,
146                                struct event_key *key)
147 {
148         if (evsel__name_is(evsel, "kvm:kvm_msr")) {
149                 msr_event_get_key(evsel, sample, key);
150                 return true;
151         }
152 
153         return false;
154 }
155 
156 static bool msr_event_end(struct evsel *evsel,
157                              struct perf_sample *sample __maybe_unused,
158                              struct event_key *key __maybe_unused)
159 {
160         return kvm_entry_event(evsel);
161 }
162 
163 static void msr_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused,
164                                     struct event_key *key,
165                                     char *decode)
166 {
167         scnprintf(decode, KVM_EVENT_NAME_LEN, "%#llx:%s",
168                   (unsigned long long)key->key,
169                   key->info ? "W" : "R");
170 }
171 
172 static struct kvm_events_ops msr_events = {
173         .is_begin_event = msr_event_begin,
174         .is_end_event = msr_event_end,
175         .decode_key = msr_event_decode_key,
176         .name = "MSR Access"
177 };
178 
179 const char *kvm_events_tp[] = {
180         "kvm:kvm_entry",
181         "kvm:kvm_exit",
182         "kvm:kvm_mmio",
183         "kvm:kvm_pio",
184         "kvm:kvm_msr",
185         NULL,
186 };
187 
188 struct kvm_reg_events_ops kvm_reg_events_ops[] = {
189         { .name = "vmexit", .ops = &exit_events },
190         { .name = "mmio", .ops = &mmio_events },
191         { .name = "ioport", .ops = &ioport_events },
192         { .name = "msr", .ops = &msr_events },
193         { NULL, NULL },
194 };
195 
196 const char * const kvm_skip_events[] = {
197         "HLT",
198         NULL,
199 };
200 
201 int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid)
202 {
203         if (strstr(cpuid, "Intel")) {
204                 kvm->exit_reasons = vmx_exit_reasons;
205                 kvm->exit_reasons_isa = "VMX";
206         } else if (strstr(cpuid, "AMD") || strstr(cpuid, "Hygon")) {
207                 kvm->exit_reasons = svm_exit_reasons;
208                 kvm->exit_reasons_isa = "SVM";
209         } else
210                 return -ENOTSUP;
211 
212         return 0;
213 }
214 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php