Commit 3c78f78a authored by Suresh E. Warrier's avatar Suresh E. Warrier Committed by Alexander Graf

KVM: PPC: Book3S HV: Tracepoints for KVM HV guest interactions

This patch adds trace points in the guest entry and exit code and also
for exceptions handled by the host in kernel mode - hypercalls and page
faults. The new events are added to /sys/kernel/debug/tracing/events
under a new subsystem called kvm_hv.
Acked-by: default avatarPaul Mackerras <paulus@samba.org>
Signed-off-by: default avatarSuresh Warrier <warrier@linux.vnet.ibm.com>
Signed-off-by: default avatarAlexander Graf <agraf@suse.de>
parent 2711e248
...@@ -37,6 +37,8 @@ ...@@ -37,6 +37,8 @@
#include <asm/ppc-opcode.h> #include <asm/ppc-opcode.h>
#include <asm/cputable.h> #include <asm/cputable.h>
#include "trace_hv.h"
/* POWER7 has 10-bit LPIDs, PPC970 has 6-bit LPIDs */ /* POWER7 has 10-bit LPIDs, PPC970 has 6-bit LPIDs */
#define MAX_LPID_970 63 #define MAX_LPID_970 63
...@@ -622,6 +624,8 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu, ...@@ -622,6 +624,8 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
gfn = gpa >> PAGE_SHIFT; gfn = gpa >> PAGE_SHIFT;
memslot = gfn_to_memslot(kvm, gfn); memslot = gfn_to_memslot(kvm, gfn);
trace_kvm_page_fault_enter(vcpu, hpte, memslot, ea, dsisr);
/* No memslot means it's an emulated MMIO region */ /* No memslot means it's an emulated MMIO region */
if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID)) if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID))
return kvmppc_hv_emulate_mmio(run, vcpu, gpa, ea, return kvmppc_hv_emulate_mmio(run, vcpu, gpa, ea,
...@@ -641,6 +645,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu, ...@@ -641,6 +645,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
mmu_seq = kvm->mmu_notifier_seq; mmu_seq = kvm->mmu_notifier_seq;
smp_rmb(); smp_rmb();
ret = -EFAULT;
is_io = 0; is_io = 0;
pfn = 0; pfn = 0;
page = NULL; page = NULL;
...@@ -664,7 +669,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu, ...@@ -664,7 +669,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
} }
up_read(&current->mm->mmap_sem); up_read(&current->mm->mmap_sem);
if (!pfn) if (!pfn)
return -EFAULT; goto out_put;
} else { } else {
page = pages[0]; page = pages[0];
pfn = page_to_pfn(page); pfn = page_to_pfn(page);
...@@ -694,14 +699,14 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu, ...@@ -694,14 +699,14 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
} }
} }
ret = -EFAULT;
if (psize > pte_size) if (psize > pte_size)
goto out_put; goto out_put;
/* Check WIMG vs. the actual page we're accessing */ /* Check WIMG vs. the actual page we're accessing */
if (!hpte_cache_flags_ok(r, is_io)) { if (!hpte_cache_flags_ok(r, is_io)) {
if (is_io) if (is_io)
return -EFAULT; goto out_put;
/* /*
* Allow guest to map emulated device memory as * Allow guest to map emulated device memory as
* uncacheable, but actually make it cacheable. * uncacheable, but actually make it cacheable.
...@@ -765,6 +770,8 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu, ...@@ -765,6 +770,8 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
SetPageDirty(page); SetPageDirty(page);
out_put: out_put:
trace_kvm_page_fault_exit(vcpu, hpte, ret);
if (page) { if (page) {
/* /*
* We drop pages[0] here, not page because page might * We drop pages[0] here, not page because page might
......
...@@ -58,6 +58,9 @@ ...@@ -58,6 +58,9 @@
#include "book3s.h" #include "book3s.h"
#define CREATE_TRACE_POINTS
#include "trace_hv.h"
/* #define EXIT_DEBUG */ /* #define EXIT_DEBUG */
/* #define EXIT_DEBUG_SIMPLE */ /* #define EXIT_DEBUG_SIMPLE */
/* #define EXIT_DEBUG_INT */ /* #define EXIT_DEBUG_INT */
...@@ -1730,6 +1733,7 @@ static void kvmppc_run_core(struct kvmppc_vcore *vc) ...@@ -1730,6 +1733,7 @@ static void kvmppc_run_core(struct kvmppc_vcore *vc)
list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list) { list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list) {
kvmppc_start_thread(vcpu); kvmppc_start_thread(vcpu);
kvmppc_create_dtl_entry(vcpu, vc); kvmppc_create_dtl_entry(vcpu, vc);
trace_kvm_guest_enter(vcpu);
} }
/* Set this explicitly in case thread 0 doesn't have a vcpu */ /* Set this explicitly in case thread 0 doesn't have a vcpu */
...@@ -1738,6 +1742,9 @@ static void kvmppc_run_core(struct kvmppc_vcore *vc) ...@@ -1738,6 +1742,9 @@ static void kvmppc_run_core(struct kvmppc_vcore *vc)
vc->vcore_state = VCORE_RUNNING; vc->vcore_state = VCORE_RUNNING;
preempt_disable(); preempt_disable();
trace_kvmppc_run_core(vc, 0);
spin_unlock(&vc->lock); spin_unlock(&vc->lock);
kvm_guest_enter(); kvm_guest_enter();
...@@ -1783,6 +1790,8 @@ static void kvmppc_run_core(struct kvmppc_vcore *vc) ...@@ -1783,6 +1790,8 @@ static void kvmppc_run_core(struct kvmppc_vcore *vc)
kvmppc_core_pending_dec(vcpu)) kvmppc_core_pending_dec(vcpu))
kvmppc_core_dequeue_dec(vcpu); kvmppc_core_dequeue_dec(vcpu);
trace_kvm_guest_exit(vcpu);
ret = RESUME_GUEST; ret = RESUME_GUEST;
if (vcpu->arch.trap) if (vcpu->arch.trap)
ret = kvmppc_handle_exit_hv(vcpu->arch.kvm_run, vcpu, ret = kvmppc_handle_exit_hv(vcpu->arch.kvm_run, vcpu,
...@@ -1808,6 +1817,8 @@ static void kvmppc_run_core(struct kvmppc_vcore *vc) ...@@ -1808,6 +1817,8 @@ static void kvmppc_run_core(struct kvmppc_vcore *vc)
wake_up(&vcpu->arch.cpu_run); wake_up(&vcpu->arch.cpu_run);
} }
} }
trace_kvmppc_run_core(vc, 1);
} }
/* /*
...@@ -1854,11 +1865,13 @@ static void kvmppc_vcore_blocked(struct kvmppc_vcore *vc) ...@@ -1854,11 +1865,13 @@ static void kvmppc_vcore_blocked(struct kvmppc_vcore *vc)
} }
vc->vcore_state = VCORE_SLEEPING; vc->vcore_state = VCORE_SLEEPING;
trace_kvmppc_vcore_blocked(vc, 0);
spin_unlock(&vc->lock); spin_unlock(&vc->lock);
schedule(); schedule();
finish_wait(&vc->wq, &wait); finish_wait(&vc->wq, &wait);
spin_lock(&vc->lock); spin_lock(&vc->lock);
vc->vcore_state = VCORE_INACTIVE; vc->vcore_state = VCORE_INACTIVE;
trace_kvmppc_vcore_blocked(vc, 1);
} }
static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
...@@ -1867,6 +1880,8 @@ static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) ...@@ -1867,6 +1880,8 @@ static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
struct kvmppc_vcore *vc; struct kvmppc_vcore *vc;
struct kvm_vcpu *v, *vn; struct kvm_vcpu *v, *vn;
trace_kvmppc_run_vcpu_enter(vcpu);
kvm_run->exit_reason = 0; kvm_run->exit_reason = 0;
vcpu->arch.ret = RESUME_GUEST; vcpu->arch.ret = RESUME_GUEST;
vcpu->arch.trap = 0; vcpu->arch.trap = 0;
...@@ -1896,6 +1911,7 @@ static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) ...@@ -1896,6 +1911,7 @@ static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
VCORE_EXIT_COUNT(vc) == 0) { VCORE_EXIT_COUNT(vc) == 0) {
kvmppc_create_dtl_entry(vcpu, vc); kvmppc_create_dtl_entry(vcpu, vc);
kvmppc_start_thread(vcpu); kvmppc_start_thread(vcpu);
trace_kvm_guest_enter(vcpu);
} else if (vc->vcore_state == VCORE_SLEEPING) { } else if (vc->vcore_state == VCORE_SLEEPING) {
wake_up(&vc->wq); wake_up(&vc->wq);
} }
...@@ -1960,6 +1976,7 @@ static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) ...@@ -1960,6 +1976,7 @@ static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
wake_up(&v->arch.cpu_run); wake_up(&v->arch.cpu_run);
} }
trace_kvmppc_run_vcpu_exit(vcpu, kvm_run);
spin_unlock(&vc->lock); spin_unlock(&vc->lock);
return vcpu->arch.ret; return vcpu->arch.ret;
} }
...@@ -2005,7 +2022,9 @@ static int kvmppc_vcpu_run_hv(struct kvm_run *run, struct kvm_vcpu *vcpu) ...@@ -2005,7 +2022,9 @@ static int kvmppc_vcpu_run_hv(struct kvm_run *run, struct kvm_vcpu *vcpu)
if (run->exit_reason == KVM_EXIT_PAPR_HCALL && if (run->exit_reason == KVM_EXIT_PAPR_HCALL &&
!(vcpu->arch.shregs.msr & MSR_PR)) { !(vcpu->arch.shregs.msr & MSR_PR)) {
trace_kvm_hcall_enter(vcpu);
r = kvmppc_pseries_do_hcall(vcpu); r = kvmppc_pseries_do_hcall(vcpu);
trace_kvm_hcall_exit(vcpu, r);
kvmppc_core_prepare_to_enter(vcpu); kvmppc_core_prepare_to_enter(vcpu);
} else if (r == RESUME_PAGE_FAULT) { } else if (r == RESUME_PAGE_FAULT) {
srcu_idx = srcu_read_lock(&vcpu->kvm->srcu); srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
......
#if !defined(_TRACE_KVM_BOOK3S_H)
#define _TRACE_KVM_BOOK3S_H
/*
* Common defines used by the trace macros in trace_pr.h and trace_hv.h
*/
#define kvm_trace_symbol_exit \
{0x100, "SYSTEM_RESET"}, \
{0x200, "MACHINE_CHECK"}, \
{0x300, "DATA_STORAGE"}, \
{0x380, "DATA_SEGMENT"}, \
{0x400, "INST_STORAGE"}, \
{0x480, "INST_SEGMENT"}, \
{0x500, "EXTERNAL"}, \
{0x501, "EXTERNAL_LEVEL"}, \
{0x502, "EXTERNAL_HV"}, \
{0x600, "ALIGNMENT"}, \
{0x700, "PROGRAM"}, \
{0x800, "FP_UNAVAIL"}, \
{0x900, "DECREMENTER"}, \
{0x980, "HV_DECREMENTER"}, \
{0xc00, "SYSCALL"}, \
{0xd00, "TRACE"}, \
{0xe00, "H_DATA_STORAGE"}, \
{0xe20, "H_INST_STORAGE"}, \
{0xe40, "H_EMUL_ASSIST"}, \
{0xf00, "PERFMON"}, \
{0xf20, "ALTIVEC"}, \
{0xf40, "VSX"}
#endif
This diff is collapsed.
...@@ -3,36 +3,13 @@ ...@@ -3,36 +3,13 @@
#define _TRACE_KVM_PR_H #define _TRACE_KVM_PR_H
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
#include "trace_book3s.h"
#undef TRACE_SYSTEM #undef TRACE_SYSTEM
#define TRACE_SYSTEM kvm_pr #define TRACE_SYSTEM kvm_pr
#define TRACE_INCLUDE_PATH . #define TRACE_INCLUDE_PATH .
#define TRACE_INCLUDE_FILE trace_pr #define TRACE_INCLUDE_FILE trace_pr
#define kvm_trace_symbol_exit \
{0x100, "SYSTEM_RESET"}, \
{0x200, "MACHINE_CHECK"}, \
{0x300, "DATA_STORAGE"}, \
{0x380, "DATA_SEGMENT"}, \
{0x400, "INST_STORAGE"}, \
{0x480, "INST_SEGMENT"}, \
{0x500, "EXTERNAL"}, \
{0x501, "EXTERNAL_LEVEL"}, \
{0x502, "EXTERNAL_HV"}, \
{0x600, "ALIGNMENT"}, \
{0x700, "PROGRAM"}, \
{0x800, "FP_UNAVAIL"}, \
{0x900, "DECREMENTER"}, \
{0x980, "HV_DECREMENTER"}, \
{0xc00, "SYSCALL"}, \
{0xd00, "TRACE"}, \
{0xe00, "H_DATA_STORAGE"}, \
{0xe20, "H_INST_STORAGE"}, \
{0xe40, "H_EMUL_ASSIST"}, \
{0xf00, "PERFMON"}, \
{0xf20, "ALTIVEC"}, \
{0xf40, "VSX"}
TRACE_EVENT(kvm_book3s_reenter, TRACE_EVENT(kvm_book3s_reenter,
TP_PROTO(int r, struct kvm_vcpu *vcpu), TP_PROTO(int r, struct kvm_vcpu *vcpu),
TP_ARGS(r, vcpu), TP_ARGS(r, vcpu),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment