summaryrefslogtreecommitdiffstats
path: root/arch/mips/kvm
diff options
context:
space:
mode:
authorJames Hogan <james.hogan@imgtec.com>2017-03-14 06:15:40 -0400
committerJames Hogan <james.hogan@imgtec.com>2017-03-28 09:54:00 -0400
commitedec9d7bdc4eb3845ec7a3f9610f0d54a7152e90 (patch)
tree89b4d3c4b8c0f549d9aa9c4f379142bce3e85bed /arch/mips/kvm
parentf4474d50c7d483dd4432d5b0891b0bb9ad0eefc9 (diff)
KVM: MIPS/VZ: Trace guest mode changes
Create a trace event for guest mode changes, and enable VZ's GuestCtl0.MC bit after the trace event is enabled to trap all guest mode changes. The MC bit causes Guest Hardware Field Change (GHFC) exceptions whenever a guest mode change occurs (such as an exception entry or return from exception), so we need to handle this exception now. The MC bit is only enabled when restoring register state, so enabling the trace event won't take immediate effect. Tracing guest mode changes can be particularly handy when trying to work out what a guest OS gets up to before something goes wrong, especially if the problem occurs as a result of some previous guest userland exception which would otherwise be invisible in the trace. Signed-off-by: James Hogan <james.hogan@imgtec.com> Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: "Radim Krčmář" <rkrcmar@redhat.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Ingo Molnar <mingo@redhat.com> Cc: Ralf Baechle <ralf@linux-mips.org> Cc: linux-mips@linux-mips.org Cc: kvm@vger.kernel.org
Diffstat (limited to 'arch/mips/kvm')
-rw-r--r--arch/mips/kvm/mips.c13
-rw-r--r--arch/mips/kvm/trace.h37
-rw-r--r--arch/mips/kvm/vz.c21
3 files changed, 69 insertions, 2 deletions
diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c
index e8ddb128b8ad..1fc6fef463db 100644
--- a/arch/mips/kvm/mips.c
+++ b/arch/mips/kvm/mips.c
@@ -76,6 +76,19 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
76 {NULL} 76 {NULL}
77}; 77};
78 78
79bool kvm_trace_guest_mode_change;
80
81int kvm_guest_mode_change_trace_reg(void)
82{
83 kvm_trace_guest_mode_change = 1;
84 return 0;
85}
86
87void kvm_guest_mode_change_trace_unreg(void)
88{
89 kvm_trace_guest_mode_change = 0;
90}
91
79/* 92/*
80 * XXXKYMA: We are simulatoring a processor that has the WII bit set in 93 * XXXKYMA: We are simulatoring a processor that has the WII bit set in
81 * Config7, so we are "runnable" if interrupts are pending 94 * Config7, so we are "runnable" if interrupts are pending
diff --git a/arch/mips/kvm/trace.h b/arch/mips/kvm/trace.h
index affde8a2c584..a8c7fd7bf6d2 100644
--- a/arch/mips/kvm/trace.h
+++ b/arch/mips/kvm/trace.h
@@ -18,6 +18,13 @@
18#define TRACE_INCLUDE_FILE trace 18#define TRACE_INCLUDE_FILE trace
19 19
20/* 20/*
21 * arch/mips/kvm/mips.c
22 */
23extern bool kvm_trace_guest_mode_change;
24int kvm_guest_mode_change_trace_reg(void);
25void kvm_guest_mode_change_trace_unreg(void);
26
27/*
21 * Tracepoints for VM enters 28 * Tracepoints for VM enters
22 */ 29 */
23DECLARE_EVENT_CLASS(kvm_transition, 30DECLARE_EVENT_CLASS(kvm_transition,
@@ -303,6 +310,36 @@ TRACE_EVENT(kvm_guestid_change,
303 __entry->guestid) 310 __entry->guestid)
304); 311);
305 312
313TRACE_EVENT_FN(kvm_guest_mode_change,
314 TP_PROTO(struct kvm_vcpu *vcpu),
315 TP_ARGS(vcpu),
316 TP_STRUCT__entry(
317 __field(unsigned long, epc)
318 __field(unsigned long, pc)
319 __field(unsigned long, badvaddr)
320 __field(unsigned int, status)
321 __field(unsigned int, cause)
322 ),
323
324 TP_fast_assign(
325 __entry->epc = kvm_read_c0_guest_epc(vcpu->arch.cop0);
326 __entry->pc = vcpu->arch.pc;
327 __entry->badvaddr = kvm_read_c0_guest_badvaddr(vcpu->arch.cop0);
328 __entry->status = kvm_read_c0_guest_status(vcpu->arch.cop0);
329 __entry->cause = kvm_read_c0_guest_cause(vcpu->arch.cop0);
330 ),
331
332 TP_printk("EPC: 0x%08lx PC: 0x%08lx Status: 0x%08x Cause: 0x%08x BadVAddr: 0x%08lx",
333 __entry->epc,
334 __entry->pc,
335 __entry->status,
336 __entry->cause,
337 __entry->badvaddr),
338
339 kvm_guest_mode_change_trace_reg,
340 kvm_guest_mode_change_trace_unreg
341);
342
306#endif /* _TRACE_KVM_H */ 343#endif /* _TRACE_KVM_H */
307 344
308/* This part must be outside protection */ 345/* This part must be outside protection */
diff --git a/arch/mips/kvm/vz.c b/arch/mips/kvm/vz.c
index 44dad9ae5d02..33bb8c6e1b05 100644
--- a/arch/mips/kvm/vz.c
+++ b/arch/mips/kvm/vz.c
@@ -1322,6 +1322,18 @@ static enum emulation_result kvm_trap_vz_handle_gsfc(u32 cause, u32 *opc,
1322 return er; 1322 return er;
1323} 1323}
1324 1324
1325static enum emulation_result kvm_trap_vz_handle_ghfc(u32 cause, u32 *opc,
1326 struct kvm_vcpu *vcpu)
1327{
1328 /*
1329 * Presumably this is due to MC (guest mode change), so lets trace some
1330 * relevant info.
1331 */
1332 trace_kvm_guest_mode_change(vcpu);
1333
1334 return EMULATE_DONE;
1335}
1336
1325static enum emulation_result kvm_trap_vz_handle_hc(u32 cause, u32 *opc, 1337static enum emulation_result kvm_trap_vz_handle_hc(u32 cause, u32 *opc,
1326 struct kvm_vcpu *vcpu) 1338 struct kvm_vcpu *vcpu)
1327{ 1339{
@@ -1407,8 +1419,7 @@ static int kvm_trap_vz_handle_guest_exit(struct kvm_vcpu *vcpu)
1407 break; 1419 break;
1408 case MIPS_GCTL0_GEXC_GHFC: 1420 case MIPS_GCTL0_GEXC_GHFC:
1409 ++vcpu->stat.vz_ghfc_exits; 1421 ++vcpu->stat.vz_ghfc_exits;
1410 er = kvm_trap_vz_no_handler_guest_exit(gexccode, cause, opc, 1422 er = kvm_trap_vz_handle_ghfc(cause, opc, vcpu);
1411 vcpu);
1412 break; 1423 break;
1413 case MIPS_GCTL0_GEXC_GPA: 1424 case MIPS_GCTL0_GEXC_GPA:
1414 ++vcpu->stat.vz_gpa_exits; 1425 ++vcpu->stat.vz_gpa_exits;
@@ -2459,6 +2470,12 @@ static int kvm_vz_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
2459 */ 2470 */
2460 kvm_vz_restore_timer(vcpu); 2471 kvm_vz_restore_timer(vcpu);
2461 2472
2473 /* Set MC bit if we want to trace guest mode changes */
2474 if (kvm_trace_guest_mode_change)
2475 set_c0_guestctl0(MIPS_GCTL0_MC);
2476 else
2477 clear_c0_guestctl0(MIPS_GCTL0_MC);
2478
2462 /* Don't bother restoring registers multiple times unless necessary */ 2479 /* Don't bother restoring registers multiple times unless necessary */
2463 if (!all) 2480 if (!all)
2464 return 0; 2481 return 0;