]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
riscv: KVM: add basic support for host vs guest profiling
authorQuan Zhou <zhouquan@iscas.ac.cn>
Tue, 15 Oct 2024 02:58:37 +0000 (10:58 +0800)
committerAnup Patel <anup@brainfault.org>
Mon, 28 Oct 2024 11:11:14 +0000 (16:41 +0530)
For the information collected on the host side, we need to
identify which data originates from the guest and record
these events separately, this can be achieved by having
KVM register perf callbacks.

Signed-off-by: Quan Zhou <zhouquan@iscas.ac.cn>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Link: https://lore.kernel.org/r/00342d535311eb0629b9ba4f1e457a48e2abee33.1728957131.git.zhouquan@iscas.ac.cn
Signed-off-by: Anup Patel <anup@brainfault.org>
arch/riscv/include/asm/kvm_host.h
arch/riscv/kvm/Kconfig
arch/riscv/kvm/main.c
arch/riscv/kvm/vcpu.c

index 2e2254fd2a2aae847d4e229d0d3f35fe1c6e341b..35eab6e0f4ae0edb7f5a62ee1770ac988523c753 100644 (file)
@@ -286,6 +286,16 @@ struct kvm_vcpu_arch {
        } sta;
 };
 
+/*
+ * Returns true if a Performance Monitoring Interrupt (PMI), a.k.a. perf event,
+ * arrived in guest context.  For riscv, any event that arrives while a vCPU is
+ * loaded is considered to be "in guest".
+ */
+static inline bool kvm_arch_pmi_in_guest(struct kvm_vcpu *vcpu)
+{
+       return IS_ENABLED(CONFIG_GUEST_PERF_EVENTS) && !!vcpu;
+}
+
 static inline void kvm_arch_sync_events(struct kvm *kvm) {}
 
 #define KVM_RISCV_GSTAGE_TLB_MIN_ORDER         12
index 26d1727f0550d3dbf8cf55ce9e1d3ca1e2d41fc4..0c3cbb0915ffa093243264e6169446543981a648 100644 (file)
@@ -32,6 +32,7 @@ config KVM
        select KVM_XFER_TO_GUEST_WORK
        select KVM_GENERIC_MMU_NOTIFIER
        select SCHED_INFO
+       select GUEST_PERF_EVENTS if PERF_EVENTS
        help
          Support hosting virtualized guest machines.
 
index f3427f6de60807145c9aec641367ff7d1178aab0..5682e338ae6ddab49d6abbd1df217277a1f2a000 100644 (file)
@@ -51,6 +51,12 @@ void kvm_arch_disable_virtualization_cpu(void)
        csr_write(CSR_HIDELEG, 0);
 }
 
+static void kvm_riscv_teardown(void)
+{
+       kvm_riscv_aia_exit();
+       kvm_unregister_perf_callbacks();
+}
+
 static int __init riscv_kvm_init(void)
 {
        int rc;
@@ -105,9 +111,11 @@ static int __init riscv_kvm_init(void)
                kvm_info("AIA available with %d guest external interrupts\n",
                         kvm_riscv_aia_nr_hgei);
 
+       kvm_register_perf_callbacks(NULL);
+
        rc = kvm_init(sizeof(struct kvm_vcpu), 0, THIS_MODULE);
        if (rc) {
-               kvm_riscv_aia_exit();
+               kvm_riscv_teardown();
                return rc;
        }
 
@@ -117,7 +125,7 @@ module_init(riscv_kvm_init);
 
 static void __exit riscv_kvm_exit(void)
 {
-       kvm_riscv_aia_exit();
+       kvm_riscv_teardown();
 
        kvm_exit();
 }
index 8d7d381737ee54f7adf9c294977eb1e7a639012f..e8ffb34568988665aaf2e2fc3c546c5654e5a2f4 100644 (file)
@@ -226,6 +226,13 @@ bool kvm_arch_vcpu_in_kernel(struct kvm_vcpu *vcpu)
        return (vcpu->arch.guest_context.sstatus & SR_SPP) ? true : false;
 }
 
+#ifdef CONFIG_GUEST_PERF_EVENTS
+unsigned long kvm_arch_vcpu_get_ip(struct kvm_vcpu *vcpu)
+{
+       return vcpu->arch.guest_context.sepc;
+}
+#endif
+
 vm_fault_t kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
 {
        return VM_FAULT_SIGBUS;