Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6398da13 authored by James Hogan's avatar James Hogan Committed by Paolo Bonzini
Browse files

MIPS: KVM: Trace guest register access emulation



Trace emulation of guest access to various registers via
MFC0/MTC0/DMFC0/DMTC0 instructions (coprocessor 0) and the RDHWR
instruction (hardware registers exposed to userland), replacing some
existing kvm_debug calls. Trace events are much more practical for this
kind of debug output.

Signed-off-by: default avatarJames Hogan <james.hogan@imgtec.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Radim Krčmář <rkrcmar@redhat.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: linux-mips@linux-mips.org
Cc: kvm@vger.kernel.org
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 93258604
Loading
Loading
Loading
Loading
+19 −12
Original line number Diff line number Diff line
@@ -979,7 +979,6 @@ enum emulation_result kvm_mips_emulate_CP0(u32 inst, u32 *opc, u32 cause,
	struct mips_coproc *cop0 = vcpu->arch.cop0;
	enum emulation_result er = EMULATE_DONE;
	u32 rt, rd, copz, sel, co_bit, op;
	unsigned long pc = vcpu->arch.pc;
	unsigned long curr_pc;

	/*
@@ -1046,20 +1045,27 @@ enum emulation_result kvm_mips_emulate_CP0(u32 inst, u32 *opc, u32 cause,
#endif
			}

			kvm_debug
			    ("[%#lx] MFCz[%d][%d], vcpu->arch.gprs[%d]: %#lx\n",
			     pc, rd, sel, rt, vcpu->arch.gprs[rt]);

			trace_kvm_hwr(vcpu, KVM_TRACE_MFC0,
				      KVM_TRACE_COP0(rd, sel),
				      vcpu->arch.gprs[rt]);
			break;

		case dmfc_op:
			vcpu->arch.gprs[rt] = cop0->reg[rd][sel];

			trace_kvm_hwr(vcpu, KVM_TRACE_DMFC0,
				      KVM_TRACE_COP0(rd, sel),
				      vcpu->arch.gprs[rt]);
			break;

		case mtc_op:
#ifdef CONFIG_KVM_MIPS_DEBUG_COP0_COUNTERS
			cop0->stat[rd][sel]++;
#endif
			trace_kvm_hwr(vcpu, KVM_TRACE_MTC0,
				      KVM_TRACE_COP0(rd, sel),
				      vcpu->arch.gprs[rt]);

			if ((rd == MIPS_CP0_TLB_INDEX)
			    && (vcpu->arch.gprs[rt] >=
				KVM_MIPS_GUEST_TLB_SIZE)) {
@@ -1098,10 +1104,6 @@ enum emulation_result kvm_mips_emulate_CP0(u32 inst, u32 *opc, u32 cause,
				kvm_mips_write_count(vcpu, vcpu->arch.gprs[rt]);
				goto done;
			} else if ((rd == MIPS_CP0_COMPARE) && (sel == 0)) {
				kvm_debug("[%#lx] MTCz, COMPARE %#lx <- %#lx\n",
					  pc, kvm_read_c0_guest_compare(cop0),
					  vcpu->arch.gprs[rt]);

				/* If we are writing to COMPARE */
				/* Clear pending timer interrupt, if any */
				kvm_mips_write_compare(vcpu,
@@ -1237,14 +1239,14 @@ enum emulation_result kvm_mips_emulate_CP0(u32 inst, u32 *opc, u32 cause,
				kvm_mips_trans_mtc0(inst, opc, vcpu);
#endif
			}

			kvm_debug("[%#lx] MTCz, cop0->reg[%d][%d]: %#lx\n", pc,
				  rd, sel, cop0->reg[rd][sel]);
			break;

		case dmtc_op:
			kvm_err("!!!!!!![%#lx]dmtc_op: rt: %d, rd: %d, sel: %d!!!!!!\n",
				vcpu->arch.pc, rt, rd, sel);
			trace_kvm_hwr(vcpu, KVM_TRACE_DMTC0,
				      KVM_TRACE_COP0(rd, sel),
				      vcpu->arch.gprs[rt]);
			er = EMULATE_FAIL;
			break;

@@ -2307,6 +2309,8 @@ enum emulation_result kvm_mips_handle_ri(u32 cause, u32 *opc,
		int usermode = !KVM_GUEST_KERNEL_MODE(vcpu);
		int rd = (inst & RD) >> 11;
		int rt = (inst & RT) >> 16;
		int sel = (inst >> 6) & 0x7;

		/* If usermode, check RDHWR rd is allowed by guest HWREna */
		if (usermode && !(kvm_read_c0_guest_hwrena(cop0) & BIT(rd))) {
			kvm_debug("RDHWR %#x disallowed by HWREna @ %p\n",
@@ -2342,6 +2346,9 @@ enum emulation_result kvm_mips_handle_ri(u32 cause, u32 *opc,
			kvm_debug("RDHWR %#x not supported @ %p\n", rd, opc);
			goto emulate_ri;
		}

		trace_kvm_hwr(vcpu, KVM_TRACE_RDHWR, KVM_TRACE_HWR(rd, sel),
			      vcpu->arch.gprs[rt]);
	} else {
		kvm_debug("Emulate RI not supported @ %p: %#x\n", opc, inst);
		goto emulate_ri;
+88 −0
Original line number Diff line number Diff line
@@ -124,6 +124,94 @@ TRACE_EVENT(kvm_exit,
		      __entry->pc)
);

#define KVM_TRACE_MFC0		0
#define KVM_TRACE_MTC0		1
#define KVM_TRACE_DMFC0		2
#define KVM_TRACE_DMTC0		3
#define KVM_TRACE_RDHWR		4

#define KVM_TRACE_HWR_COP0	0
#define KVM_TRACE_HWR_HWR	1

#define KVM_TRACE_COP0(REG, SEL)	((KVM_TRACE_HWR_COP0 << 8) |	\
					 ((REG) << 3) | (SEL))
#define KVM_TRACE_HWR(REG, SEL)		((KVM_TRACE_HWR_HWR  << 8) |	\
					 ((REG) << 3) | (SEL))

#define kvm_trace_symbol_hwr_ops				\
	{ KVM_TRACE_MFC0,		"MFC0" },		\
	{ KVM_TRACE_MTC0,		"MTC0" },		\
	{ KVM_TRACE_DMFC0,		"DMFC0" },		\
	{ KVM_TRACE_DMTC0,		"DMTC0" },		\
	{ KVM_TRACE_RDHWR,		"RDHWR" }

#define kvm_trace_symbol_hwr_cop				\
	{ KVM_TRACE_HWR_COP0,		"COP0" },		\
	{ KVM_TRACE_HWR_HWR,		"HWR" }

#define kvm_trace_symbol_hwr_regs				\
	{ KVM_TRACE_COP0( 0, 0),	"Index" },		\
	{ KVM_TRACE_COP0( 2, 0),	"EntryLo0" },		\
	{ KVM_TRACE_COP0( 3, 0),	"EntryLo1" },		\
	{ KVM_TRACE_COP0( 4, 0),	"Context" },		\
	{ KVM_TRACE_COP0( 4, 2),	"UserLocal" },		\
	{ KVM_TRACE_COP0( 5, 0),	"PageMask" },		\
	{ KVM_TRACE_COP0( 6, 0),	"Wired" },		\
	{ KVM_TRACE_COP0( 7, 0),	"HWREna" },		\
	{ KVM_TRACE_COP0( 8, 0),	"BadVAddr" },		\
	{ KVM_TRACE_COP0( 9, 0),	"Count" },		\
	{ KVM_TRACE_COP0(10, 0),	"EntryHi" },		\
	{ KVM_TRACE_COP0(11, 0),	"Compare" },		\
	{ KVM_TRACE_COP0(12, 0),	"Status" },		\
	{ KVM_TRACE_COP0(12, 1),	"IntCtl" },		\
	{ KVM_TRACE_COP0(12, 2),	"SRSCtl" },		\
	{ KVM_TRACE_COP0(13, 0),	"Cause" },		\
	{ KVM_TRACE_COP0(14, 0),	"EPC" },		\
	{ KVM_TRACE_COP0(15, 0),	"PRId" },		\
	{ KVM_TRACE_COP0(15, 1),	"EBase" },		\
	{ KVM_TRACE_COP0(16, 0),	"Config" },		\
	{ KVM_TRACE_COP0(16, 1),	"Config1" },		\
	{ KVM_TRACE_COP0(16, 2),	"Config2" },		\
	{ KVM_TRACE_COP0(16, 3),	"Config3" },		\
	{ KVM_TRACE_COP0(16, 4),	"Config4" },		\
	{ KVM_TRACE_COP0(16, 5),	"Config5" },		\
	{ KVM_TRACE_COP0(16, 7),	"Config7" },		\
	{ KVM_TRACE_COP0(26, 0),	"ECC" },		\
	{ KVM_TRACE_COP0(30, 0),	"ErrorEPC" },		\
	{ KVM_TRACE_HWR( 0, 0),		"CPUNum" },		\
	{ KVM_TRACE_HWR( 1, 0),		"SYNCI_Step" },		\
	{ KVM_TRACE_HWR( 2, 0),		"CC" },			\
	{ KVM_TRACE_HWR( 3, 0),		"CCRes" },		\
	{ KVM_TRACE_HWR(29, 0),		"ULR" }

TRACE_EVENT(kvm_hwr,
	    TP_PROTO(struct kvm_vcpu *vcpu, unsigned int op, unsigned int reg,
		     unsigned long val),
	    TP_ARGS(vcpu, op, reg, val),
	    TP_STRUCT__entry(
			__field(unsigned long, val)
			__field(u16, reg)
			__field(u8, op)
	    ),

	    TP_fast_assign(
			__entry->val = val;
			__entry->reg = reg;
			__entry->op = op;
	    ),

	    TP_printk("%s %s (%s:%u:%u) 0x%08lx",
		      __print_symbolic(__entry->op,
				       kvm_trace_symbol_hwr_ops),
		      __print_symbolic(__entry->reg,
				       kvm_trace_symbol_hwr_regs),
		      __print_symbolic(__entry->reg >> 8,
				       kvm_trace_symbol_hwr_cop),
		      (__entry->reg >> 3) & 0x1f,
		      __entry->reg & 0x7,
		      __entry->val)
);

#define KVM_TRACE_AUX_RESTORE		0
#define KVM_TRACE_AUX_SAVE		1
#define KVM_TRACE_AUX_ENABLE		2