FILE
kvm-stat.c
File preview with syntax highlighting.
linux-6.19.14/tools/perf/arch/loongarch/util/kvm-stat.c
1// SPDX-License-Identifier: GPL-2.0 2#include <errno.h> 3#include <memory.h> 4#include "util/kvm-stat.h" 5#include "util/parse-events.h" 6#include "util/debug.h" 7#include "util/evsel.h" 8#include "util/evlist.h" 9#include "util/pmus.h" 10 11#define LOONGARCH_EXCEPTION_INT 0 12#define LOONGARCH_EXCEPTION_PIL 1 13#define LOONGARCH_EXCEPTION_PIS 2 14#define LOONGARCH_EXCEPTION_PIF 3 15#define LOONGARCH_EXCEPTION_PME 4 16#define LOONGARCH_EXCEPTION_FPD 15 17#define LOONGARCH_EXCEPTION_SXD 16 18#define LOONGARCH_EXCEPTION_ASXD 17 19#define LOONGARCH_EXCEPTION_GSPR 22 20#define LOONGARCH_EXCEPTION_CPUCFG 100 21#define LOONGARCH_EXCEPTION_CSR 101 22#define LOONGARCH_EXCEPTION_IOCSR 102 23#define LOONGARCH_EXCEPTION_IDLE 103 24#define LOONGARCH_EXCEPTION_OTHERS 104 25#define LOONGARCH_EXCEPTION_HVC 23 26 27#define loongarch_exception_type \ 28 {LOONGARCH_EXCEPTION_INT, "Interrupt" }, \ 29 {LOONGARCH_EXCEPTION_PIL, "Mem Read" }, \ 30 {LOONGARCH_EXCEPTION_PIS, "Mem Store" }, \ 31 {LOONGARCH_EXCEPTION_PIF, "Inst Fetch" }, \ 32 {LOONGARCH_EXCEPTION_PME, "Mem Modify" }, \ 33 {LOONGARCH_EXCEPTION_FPD, "FPU" }, \ 34 {LOONGARCH_EXCEPTION_SXD, "LSX" }, \ 35 {LOONGARCH_EXCEPTION_ASXD, "LASX" }, \ 36 {LOONGARCH_EXCEPTION_GSPR, "Privilege Error" }, \ 37 {LOONGARCH_EXCEPTION_HVC, "Hypercall" }, \ 38 {LOONGARCH_EXCEPTION_CPUCFG, "CPUCFG" }, \ 39 {LOONGARCH_EXCEPTION_CSR, "CSR" }, \ 40 {LOONGARCH_EXCEPTION_IOCSR, "IOCSR" }, \ 41 {LOONGARCH_EXCEPTION_IDLE, "Idle" }, \ 42 {LOONGARCH_EXCEPTION_OTHERS, "Others" } 43 44define_exit_reasons_table(loongarch_exit_reasons, loongarch_exception_type); 45 46const char *vcpu_id_str = "vcpu_id"; 47const char *kvm_exit_reason = "reason"; 48const char *kvm_entry_trace = "kvm:kvm_enter"; 49const char *kvm_reenter_trace = "kvm:kvm_reenter"; 50const char *kvm_exit_trace = "kvm:kvm_exit"; 51const char *kvm_events_tp[] = { 52 "kvm:kvm_enter", 53 "kvm:kvm_reenter", 54 "kvm:kvm_exit", 55 "kvm:kvm_exit_gspr", 56 NULL, 57}; 58 59static bool event_begin(struct evsel *evsel, 60 struct perf_sample *sample, struct event_key *key) 61{ 62 return exit_event_begin(evsel, sample, key); 63} 64 65static bool event_end(struct evsel *evsel, 66 struct perf_sample *sample __maybe_unused, 67 struct event_key *key __maybe_unused) 68{ 69 /* 70 * LoongArch kvm is different with other architectures 71 * 72 * There is kvm:kvm_reenter or kvm:kvm_enter event adjacent with 73 * kvm:kvm_exit event. 74 * kvm:kvm_enter means returning to vmm and then to guest 75 * kvm:kvm_reenter means returning to guest immediately 76 */ 77 return evsel__name_is(evsel, kvm_entry_trace) || evsel__name_is(evsel, kvm_reenter_trace); 78} 79 80static void event_gspr_get_key(struct evsel *evsel, 81 struct perf_sample *sample, struct event_key *key) 82{ 83 unsigned int insn; 84 85 key->key = LOONGARCH_EXCEPTION_OTHERS; 86 insn = evsel__intval(evsel, sample, "inst_word"); 87 88 switch (insn >> 24) { 89 case 0: 90 /* CPUCFG inst trap */ 91 if ((insn >> 10) == 0x1b) 92 key->key = LOONGARCH_EXCEPTION_CPUCFG; 93 break; 94 case 4: 95 /* CSR inst trap */ 96 key->key = LOONGARCH_EXCEPTION_CSR; 97 break; 98 case 6: 99 /* IOCSR inst trap */ 100 if ((insn >> 15) == 0xc90) 101 key->key = LOONGARCH_EXCEPTION_IOCSR; 102 else if ((insn >> 15) == 0xc91) 103 /* Idle inst trap */ 104 key->key = LOONGARCH_EXCEPTION_IDLE; 105 break; 106 default: 107 key->key = LOONGARCH_EXCEPTION_OTHERS; 108 break; 109 } 110} 111 112static struct child_event_ops child_events[] = { 113 { .name = "kvm:kvm_exit_gspr", .get_key = event_gspr_get_key }, 114 { NULL, NULL }, 115}; 116 117static struct kvm_events_ops exit_events = { 118 .is_begin_event = event_begin, 119 .is_end_event = event_end, 120 .child_ops = child_events, 121 .decode_key = exit_event_decode_key, 122 .name = "VM-EXIT" 123}; 124 125struct kvm_reg_events_ops kvm_reg_events_ops[] = { 126 { .name = "vmexit", .ops = &exit_events, }, 127 { NULL, NULL }, 128}; 129 130const char * const kvm_skip_events[] = { 131 NULL, 132}; 133 134int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid __maybe_unused) 135{ 136 kvm->exit_reasons_isa = "loongarch64"; 137 kvm->exit_reasons = loongarch_exit_reasons; 138 return 0; 139}
~/
Read-only file preview.