linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 0/9] Add support for monitoring guest TLB operations
@ 2017-01-31 17:16 Punit Agrawal
  2017-01-31 17:16 ` [PATCH v4 1/9] arm64/kvm: hyp: tlb: use __tlbi() helper Punit Agrawal
                   ` (8 more replies)
  0 siblings, 9 replies; 10+ messages in thread
From: Punit Agrawal @ 2017-01-31 17:16 UTC (permalink / raw)
  To: kvmarm, linux-arm-kernel
  Cc: Punit Agrawal, linux-kernel, kvm, Christoffer Dall, Marc Zyngier,
	Steven Rostedt, Peter Zijlstra, Will Deacon

Hi,

This series adds support for a software pmu on the host which can be
used to monitor VM operations. For arm and arm64, support is added to
monitor guest TLB operations using the host pmu infrastructure.

This posting addresses all feedback on the previous
version[0]. Instead of requiring a VM pid as part of the event
attribute, it now depends on vcpu thread ids being passed via the
standard perf interface (-t). Thread ids instead of process ids (-p)
is used as -p when called with the thread id ends up resolving to the
parent process.

Prior versions can be found at [1][2][3][4].

As a result of the changes, the user interface has changed as
well. With the patchset, TLB operations can be monitored using -

# perf stat -e kvm/tlb_invalidate/ -t 3967,3968
^C
 Performance counter stats for thread id '3967,3968':

                71      kvm/tlb_invalidate/

      10.207587028 seconds time elapsed

where 3967 and 3968 are the thread ids of the vcpus.

Patches based on v4.10-rc6.

Thanks,
Punit

[0] http://www.mail-archive.com/kvmarm@lists.cs.columbia.edu/msg09357.html
[1] http://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1210715.html
[2] http://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1224353.html
[3] https://marc.info/?l=linux-kernel&m=147376184208258&w=2
[4] https://marc.info/?l=kvm&m=147750373716545&w=2

Changes:
v3 -> v4
* Use vcpupid specified via perf instead of custom VM specifier. This
  results in simplifying the synchronisation requirements for
  callbacks
* Dropped change to track VM pid as it's no longer being used
* Moved host pmu to virt/kvm
* Added copyright headers

v2 -> v3
* Replaced perf trace monitoring with software PMU
* Re-ordered patches as a result of the above re-write

v1 -> v2
* New (Patch 6) - Add support for trapping and emulating TLB
  operations to ARM hosts
* Move common code to handle perf trace notifications to virt/kvm/arm
* Move tracepoint to include/trace/events/kvm.h
* Drop patch to introduce __tlbi helper as it is now merged
* Reorder patches

RFC v2 -> v1
* Dropped the RFC tag
* Patch 2 - Use VM thread group id for identification
* Patch 4 - Update comment for clarity
* Patch 6 - Add comment explaining switch to hype-role when VHE is enabled
* Patch 7 - Add comment to clarify struct kvm_trace_hook

RFC -> RFC v2
* Patch 4 - Rename left-over TLBI macro to __TLBI
* Patch 6 - Replace individual TLB operation emulation with
  invalidating all stage 1 TLB for the VM. TLB monitoring is expected
  to be a debug feature and performance is not critical.

Mark Rutland (1):
  arm64/kvm: hyp: tlb: use __tlbi() helper

Punit Agrawal (8):
  KVM: Add event to trace tlb invalidations
  arm: KVM: Handle trappable TLB instructions
  arm64: KVM: Handle trappable TLB instructions
  kvm: Add host pmu to support VM introspection
  kvm: host_pmu: Add support for tracking guest TLB operations
  arm64: KVM: Enable support for the host pmu
  arm: KVM: Enable support for host pmu
  arm: KVM: Initialise the host pmu

 arch/arm/include/asm/kvm_asm.h    |   2 +
 arch/arm/include/asm/kvm_host.h   |   9 ++
 arch/arm/kvm/Kconfig              |   1 +
 arch/arm/kvm/Makefile             |   1 +
 arch/arm/kvm/arm.c                |   2 +
 arch/arm/kvm/coproc.c             |  56 +++++++++
 arch/arm/kvm/hyp/tlb.c            |  33 +++++
 arch/arm64/include/asm/kvm_asm.h  |   2 +
 arch/arm64/include/asm/kvm_host.h |   9 ++
 arch/arm64/kvm/Kconfig            |   1 +
 arch/arm64/kvm/Makefile           |   1 +
 arch/arm64/kvm/hyp/tlb.c          |  87 +++++++++++++-
 arch/arm64/kvm/sys_regs.c         |  83 +++++++++++++
 include/kvm/host_pmu.h            |  35 ++++++
 include/trace/events/kvm.h        |  18 +++
 virt/kvm/Kconfig                  |   3 +
 virt/kvm/arm/host_pmu_events.c    |  82 +++++++++++++
 virt/kvm/host_pmu.c               | 246 ++++++++++++++++++++++++++++++++++++++
 18 files changed, 665 insertions(+), 6 deletions(-)
 create mode 100644 include/kvm/host_pmu.h
 create mode 100644 virt/kvm/arm/host_pmu_events.c
 create mode 100644 virt/kvm/host_pmu.c

-- 
2.11.0

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v4 1/9] arm64/kvm: hyp: tlb: use __tlbi() helper
  2017-01-31 17:16 [PATCH v4 0/9] Add support for monitoring guest TLB operations Punit Agrawal
@ 2017-01-31 17:16 ` Punit Agrawal
  2017-01-31 17:16 ` [PATCH v4 2/9] KVM: Add event to trace tlb invalidations Punit Agrawal
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Punit Agrawal @ 2017-01-31 17:16 UTC (permalink / raw)
  To: kvmarm, linux-arm-kernel
  Cc: Mark Rutland, linux-kernel, kvm, Christoffer Dall, Marc Zyngier,
	Will Deacon, Punit Agrawal

From: Mark Rutland <mark.rutland@arm.com>

Now that we have a __tlbi() helper, make use of this in the arm64 KVM hyp
code to get rid of asm() boilerplate. At the same time, we simplify
__tlb_flush_vm_context by using __flush_icache_all(), as this has the
appropriate instruction cache maintenance and barrier.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Marc Zyngier <marc.zyngier@arm.com>
[ rename tlbi -> __tlbi, convert additional sites, update commit log ]
Signed-off-by: Punit Agrawal <punit.agrawal@arm.com>
Acked-by: Christoffer Dall <christoffer.dall@linaro.org>
---
 arch/arm64/kvm/hyp/tlb.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/kvm/hyp/tlb.c b/arch/arm64/kvm/hyp/tlb.c
index 88e2f2b938f0..b2cfbedea582 100644
--- a/arch/arm64/kvm/hyp/tlb.c
+++ b/arch/arm64/kvm/hyp/tlb.c
@@ -16,6 +16,7 @@
  */
 
 #include <asm/kvm_hyp.h>
+#include <asm/tlbflush.h>
 
 void __hyp_text __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa)
 {
@@ -32,7 +33,7 @@ void __hyp_text __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa)
 	 * whole of Stage-1. Weep...
 	 */
 	ipa >>= 12;
-	asm volatile("tlbi ipas2e1is, %0" : : "r" (ipa));
+	__tlbi(ipas2e1is, ipa);
 
 	/*
 	 * We have to ensure completion of the invalidation at Stage-2,
@@ -41,7 +42,7 @@ void __hyp_text __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa)
 	 * the Stage-1 invalidation happened first.
 	 */
 	dsb(ish);
-	asm volatile("tlbi vmalle1is" : : );
+	__tlbi(vmalle1is);
 	dsb(ish);
 	isb();
 
@@ -57,7 +58,7 @@ void __hyp_text __kvm_tlb_flush_vmid(struct kvm *kvm)
 	write_sysreg(kvm->arch.vttbr, vttbr_el2);
 	isb();
 
-	asm volatile("tlbi vmalls12e1is" : : );
+	__tlbi(vmalls12e1is);
 	dsb(ish);
 	isb();
 
@@ -82,7 +83,6 @@ void __hyp_text __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu)
 void __hyp_text __kvm_flush_vm_context(void)
 {
 	dsb(ishst);
-	asm volatile("tlbi alle1is	\n"
-		     "ic ialluis	  ": : );
-	dsb(ish);
+	__tlbi(alle1is);
+	__flush_icache_all(); /* contains a dsb(ish) */
 }
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v4 2/9] KVM: Add event to trace tlb invalidations
  2017-01-31 17:16 [PATCH v4 0/9] Add support for monitoring guest TLB operations Punit Agrawal
  2017-01-31 17:16 ` [PATCH v4 1/9] arm64/kvm: hyp: tlb: use __tlbi() helper Punit Agrawal
@ 2017-01-31 17:16 ` Punit Agrawal
  2017-01-31 17:16 ` [PATCH v4 3/9] arm: KVM: Handle trappable TLB instructions Punit Agrawal
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Punit Agrawal @ 2017-01-31 17:16 UTC (permalink / raw)
  To: kvmarm, linux-arm-kernel
  Cc: Punit Agrawal, linux-kernel, kvm, Christoffer Dall, Marc Zyngier,
	Steven Rostedt, Will Deacon, Mark Rutland, Paolo Bonzini

As TLB operations can have an impact on system performance, add a trace
event to enable monitoring of guest TLB maintenance operations.

Signed-off-by: Punit Agrawal <punit.agrawal@arm.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Paolo Bonzini <pbonzini@redhat.com>
---
 include/trace/events/kvm.h | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/include/trace/events/kvm.h b/include/trace/events/kvm.h
index 8ade3eb6c640..fbe33089264c 100644
--- a/include/trace/events/kvm.h
+++ b/include/trace/events/kvm.h
@@ -393,6 +393,24 @@ TRACE_EVENT(kvm_halt_poll_ns,
 #define trace_kvm_halt_poll_ns_shrink(vcpu_id, new, old) \
 	trace_kvm_halt_poll_ns(false, vcpu_id, new, old)
 
+TRACE_EVENT(kvm_tlb_invalidate,
+	TP_PROTO(unsigned long vcpu_pc, u32 opcode),
+	TP_ARGS(vcpu_pc, opcode),
+
+	TP_STRUCT__entry(
+		__field(unsigned long, vcpu_pc)
+		__field(u32, opcode)
+	),
+
+	TP_fast_assign(
+		__entry->vcpu_pc = vcpu_pc;
+		__entry->opcode = opcode;
+	),
+
+	TP_printk("vcpu_pc=0x%16lx opcode=%08x", __entry->vcpu_pc,
+		  __entry->opcode)
+);
+
 #endif /* _TRACE_KVM_MAIN_H */
 
 /* This part must be outside protection */
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v4 3/9] arm: KVM: Handle trappable TLB instructions
  2017-01-31 17:16 [PATCH v4 0/9] Add support for monitoring guest TLB operations Punit Agrawal
  2017-01-31 17:16 ` [PATCH v4 1/9] arm64/kvm: hyp: tlb: use __tlbi() helper Punit Agrawal
  2017-01-31 17:16 ` [PATCH v4 2/9] KVM: Add event to trace tlb invalidations Punit Agrawal
@ 2017-01-31 17:16 ` Punit Agrawal
  2017-01-31 17:16 ` [PATCH v4 4/9] arm64: " Punit Agrawal
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Punit Agrawal @ 2017-01-31 17:16 UTC (permalink / raw)
  To: kvmarm, linux-arm-kernel
  Cc: Punit Agrawal, linux-kernel, kvm, Christoffer Dall, Marc Zyngier,
	Will Deacon, Mark Rutland

It is possible to enable selective trapping of guest TLB maintenance
instructions executed in lower privilege levels to HYP mode. This
feature can be used to monitor guest TLB operations.

Add support to emulate the TLB instructions when their execution traps
to hyp mode. Also keep track of the number of emulated operations.

Signed-off-by: Punit Agrawal <punit.agrawal@arm.com>
Cc: Christoffer Dall <christoffer.dall@linaro.org>
Cc: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/include/asm/kvm_asm.h  |  2 ++
 arch/arm/include/asm/kvm_host.h |  1 +
 arch/arm/kvm/coproc.c           | 56 +++++++++++++++++++++++++++++++++++++++++
 arch/arm/kvm/hyp/tlb.c          | 33 ++++++++++++++++++++++++
 4 files changed, 92 insertions(+)

diff --git a/arch/arm/include/asm/kvm_asm.h b/arch/arm/include/asm/kvm_asm.h
index 8ef05381984b..782034a5a3c3 100644
--- a/arch/arm/include/asm/kvm_asm.h
+++ b/arch/arm/include/asm/kvm_asm.h
@@ -67,6 +67,8 @@ extern void __kvm_flush_vm_context(void);
 extern void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa);
 extern void __kvm_tlb_flush_vmid(struct kvm *kvm);
 extern void __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu);
+extern void __kvm_emulate_tlb_invalidate(struct kvm *kvm, u32 opcode,
+					 u64 regval);
 
 extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu);
 
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index d5423ab15ed5..26f0c8a0b790 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -205,6 +205,7 @@ struct kvm_vcpu_stat {
 	u64 mmio_exit_user;
 	u64 mmio_exit_kernel;
 	u64 exits;
+	u64 tlb_invalidate;
 };
 
 #define vcpu_cp15(v,r)	(v)->arch.ctxt.cp15[r]
diff --git a/arch/arm/kvm/coproc.c b/arch/arm/kvm/coproc.c
index 3e5e4194ef86..b978b0bf211e 100644
--- a/arch/arm/kvm/coproc.c
+++ b/arch/arm/kvm/coproc.c
@@ -205,6 +205,24 @@ static bool access_dcsw(struct kvm_vcpu *vcpu,
 	return true;
 }
 
+static bool emulate_tlb_invalidate(struct kvm_vcpu *vcpu,
+				   const struct coproc_params *p,
+				   const struct coproc_reg *r)
+{
+	/*
+	 * Based on system register encoding from ARM v8 ARM
+	 * (DDI 0487A.k F5.1.103)
+	 */
+	u32 opcode = p->Op1 << 21 | p->CRn << 16 | p->Op2 << 5 | p->CRm << 0;
+
+	kvm_call_hyp(__kvm_emulate_tlb_invalidate,
+		     vcpu->kvm, opcode, p->Rt1);
+	trace_kvm_tlb_invalidate(*vcpu_pc(vcpu), opcode);
+	++vcpu->stat.tlb_invalidate;
+
+	return true;
+}
+
 /*
  * Generic accessor for VM registers. Only called as long as HCR_TVM
  * is set.  If the guest enables the MMU, we stop trapping the VM
@@ -354,6 +372,44 @@ static const struct coproc_reg cp15_regs[] = {
 	{ CRn( 7), CRm( 6), Op1( 0), Op2( 2), is32, access_dcsw},
 	{ CRn( 7), CRm(10), Op1( 0), Op2( 2), is32, access_dcsw},
 	{ CRn( 7), CRm(14), Op1( 0), Op2( 2), is32, access_dcsw},
+
+	/* TLBIALLIS */
+	{ CRn( 8), CRm( 3), Op1( 0), Op2( 0), is32, emulate_tlb_invalidate},
+	/* TLBIMVAIS */
+	{ CRn( 8), CRm( 3), Op1( 0), Op2( 1), is32, emulate_tlb_invalidate},
+	/* TLBIASIDIS */
+	{ CRn( 8), CRm( 3), Op1( 0), Op2( 2), is32, emulate_tlb_invalidate},
+	/* TLBIMVAAIS */
+	{ CRn( 8), CRm( 3), Op1( 0), Op2( 3), is32, emulate_tlb_invalidate},
+	/* TLBIMVALIS */
+	{ CRn( 8), CRm( 3), Op1( 0), Op2( 5), is32, emulate_tlb_invalidate},
+	/* TLBIMVAALIS */
+	{ CRn( 8), CRm( 3), Op1( 0), Op2( 7), is32, emulate_tlb_invalidate},
+	/* ITLBIALL */
+	{ CRn( 8), CRm( 5), Op1( 0), Op2( 0), is32, emulate_tlb_invalidate},
+	/* ITLBIMVA */
+	{ CRn( 8), CRm( 5), Op1( 0), Op2( 1), is32, emulate_tlb_invalidate},
+	/* ITLBIASID */
+	{ CRn( 8), CRm( 5), Op1( 0), Op2( 2), is32, emulate_tlb_invalidate},
+	/* DTLBIALL */
+	{ CRn( 8), CRm( 6), Op1( 0), Op2( 0), is32, emulate_tlb_invalidate},
+	/* DTLBIMVA */
+	{ CRn( 8), CRm( 6), Op1( 0), Op2( 1), is32, emulate_tlb_invalidate},
+	/* DTLBIASID */
+	{ CRn( 8), CRm( 6), Op1( 0), Op2( 2), is32, emulate_tlb_invalidate},
+	/* TLBIALL */
+	{ CRn( 8), CRm( 7), Op1( 0), Op2( 0), is32, emulate_tlb_invalidate},
+	/* TLBIMVA */
+	{ CRn( 8), CRm( 7), Op1( 0), Op2( 1), is32, emulate_tlb_invalidate},
+	/* TLBIASID */
+	{ CRn( 8), CRm( 7), Op1( 0), Op2( 2), is32, emulate_tlb_invalidate},
+	/* TLBIMVAA */
+	{ CRn( 8), CRm( 7), Op1( 0), Op2( 3), is32, emulate_tlb_invalidate},
+	/* TLBIMVAL */
+	{ CRn( 8), CRm( 7), Op1( 0), Op2( 5), is32, emulate_tlb_invalidate},
+	/* TLBIMVAAL */
+	{ CRn( 8), CRm( 7), Op1( 0), Op2( 7), is32, emulate_tlb_invalidate},
+
 	/*
 	 * L2CTLR access (guest wants to know #CPUs).
 	 */
diff --git a/arch/arm/kvm/hyp/tlb.c b/arch/arm/kvm/hyp/tlb.c
index 6d810af2d9fd..d2b86100d1bb 100644
--- a/arch/arm/kvm/hyp/tlb.c
+++ b/arch/arm/kvm/hyp/tlb.c
@@ -76,3 +76,36 @@ void __hyp_text __kvm_flush_vm_context(void)
 	write_sysreg(0, ICIALLUIS);
 	dsb(ish);
 }
+
+static void __hyp_text __switch_to_guest_regime(struct kvm *kvm)
+{
+	write_sysreg(kvm->arch.vttbr, VTTBR);
+	isb();
+}
+
+static void __hyp_text __switch_to_host_regime(void)
+{
+	write_sysreg(0, VTTBR);
+}
+
+void __hyp_text
+__kvm_emulate_tlb_invalidate(struct kvm *kvm, u32 opcode, u64 regval)
+{
+	kvm = kern_hyp_va(kvm);
+
+	__switch_to_guest_regime(kvm);
+
+	/*
+	 *  TLB maintenance operations are broadcast to
+	 *  inner-shareable domain when HCR_FB is set (default for
+	 *  KVM).
+	 *
+	 *  Nuke all Stage 1 TLB entries for the VM. This will kill
+	 *  performance but it's always safe to do as we don't leave
+	 *  behind any strays in the TLB
+	 */
+	write_sysreg(0, TLBIALLIS);
+	isb();
+
+	__switch_to_host_regime();
+}
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v4 4/9] arm64: KVM: Handle trappable TLB instructions
  2017-01-31 17:16 [PATCH v4 0/9] Add support for monitoring guest TLB operations Punit Agrawal
                   ` (2 preceding siblings ...)
  2017-01-31 17:16 ` [PATCH v4 3/9] arm: KVM: Handle trappable TLB instructions Punit Agrawal
@ 2017-01-31 17:16 ` Punit Agrawal
  2017-01-31 17:16 ` [PATCH v4 5/9] kvm: Add host pmu to support VM introspection Punit Agrawal
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Punit Agrawal @ 2017-01-31 17:16 UTC (permalink / raw)
  To: kvmarm, linux-arm-kernel
  Cc: Punit Agrawal, linux-kernel, kvm, Christoffer Dall, Marc Zyngier,
	Will Deacon, Mark Rutland

The ARMv8 architecture allows trapping of TLB maintenane instructions
from EL0/EL1 to higher exception levels. On encountering a trappable TLB
instruction in a guest, an exception is taken to EL2.

Add support to handle emulating the TLB instructions. Also track the
number of emulated operations.

Signed-off-by: Punit Agrawal <punit.agrawal@arm.com>
Cc: Christoffer Dall <christoffer.dall@linaro.org>
Cc: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/include/asm/kvm_asm.h  |  2 +
 arch/arm64/include/asm/kvm_host.h |  1 +
 arch/arm64/kvm/hyp/tlb.c          | 75 +++++++++++++++++++++++++++++++++++
 arch/arm64/kvm/sys_regs.c         | 83 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 161 insertions(+)

diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
index ec3553eb9349..8b695785d454 100644
--- a/arch/arm64/include/asm/kvm_asm.h
+++ b/arch/arm64/include/asm/kvm_asm.h
@@ -55,6 +55,8 @@ extern void __kvm_flush_vm_context(void);
 extern void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa);
 extern void __kvm_tlb_flush_vmid(struct kvm *kvm);
 extern void __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu);
+extern void __kvm_emulate_tlb_invalidate(struct kvm *kvm, u32 opcode,
+					 u64 regval);
 
 extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu);
 
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index e5050388e062..1e83b707f14c 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -307,6 +307,7 @@ struct kvm_vcpu_stat {
 	u64 mmio_exit_user;
 	u64 mmio_exit_kernel;
 	u64 exits;
+	u64 tlb_invalidate;
 };
 
 int kvm_vcpu_preferred_target(struct kvm_vcpu_init *init);
diff --git a/arch/arm64/kvm/hyp/tlb.c b/arch/arm64/kvm/hyp/tlb.c
index b2cfbedea582..c14237858d75 100644
--- a/arch/arm64/kvm/hyp/tlb.c
+++ b/arch/arm64/kvm/hyp/tlb.c
@@ -86,3 +86,78 @@ void __hyp_text __kvm_flush_vm_context(void)
 	__tlbi(alle1is);
 	__flush_icache_all(); /* contains a dsb(ish) */
 }
+
+/* Intentionally empty functions */
+static void __hyp_text __switch_to_hyp_role_nvhe(void) { }
+static void __hyp_text __switch_to_host_role_nvhe(void) { }
+
+static void __hyp_text __switch_to_hyp_role_vhe(void)
+{
+	u64 hcr = read_sysreg(hcr_el2);
+
+	/*
+	 * When VHE is enabled and HCR_EL2.TGE=1, EL1&0 TLB operations
+	 * apply to EL2&0 translation regime. As we prepare to emulate
+	 * guest TLB operation clear HCR_TGE to target TLB operations
+	 * to EL1&0 (guest).
+	 */
+	hcr &= ~HCR_TGE;
+	write_sysreg(hcr, hcr_el2);
+}
+
+static void __hyp_text __switch_to_host_role_vhe(void)
+{
+	u64 hcr = read_sysreg(hcr_el2);
+
+	hcr |= HCR_TGE;
+	write_sysreg(hcr, hcr_el2);
+}
+
+static hyp_alternate_select(__switch_to_hyp_role,
+			    __switch_to_hyp_role_nvhe,
+			    __switch_to_hyp_role_vhe,
+			    ARM64_HAS_VIRT_HOST_EXTN);
+
+static hyp_alternate_select(__switch_to_host_role,
+			    __switch_to_host_role_nvhe,
+			    __switch_to_host_role_vhe,
+			    ARM64_HAS_VIRT_HOST_EXTN);
+
+static void __hyp_text __switch_to_guest_regime(struct kvm *kvm)
+{
+	write_sysreg(kvm->arch.vttbr, vttbr_el2);
+	__switch_to_hyp_role();
+	isb();
+}
+
+static void __hyp_text __switch_to_host_regime(void)
+{
+	__switch_to_host_role();
+	write_sysreg(0, vttbr_el2);
+}
+
+void __hyp_text
+__kvm_emulate_tlb_invalidate(struct kvm *kvm, u32 opcode, u64 regval)
+{
+	kvm = kern_hyp_va(kvm);
+
+	/*
+	 * Switch to the guest before performing any TLB operations to
+	 * target the appropriate VMID
+	 */
+	__switch_to_guest_regime(kvm);
+
+	/*
+	 *  TLB maintenance operations are broadcast to
+	 *  inner-shareable domain when HCR_FB is set (default for
+	 *  KVM).
+	 *
+	 *  Nuke all Stage 1 TLB entries for the VM. This will kill
+	 *  performance but it's always safe to do as we don't leave
+	 *  behind any strays in the TLB
+	 */
+	__tlbi(vmalle1is);
+	isb();
+
+	__switch_to_host_regime();
+}
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 87e7e6608cd8..12ff8cf9f18a 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -791,6 +791,20 @@ static bool access_pmuserenr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
 	return true;
 }
 
+static bool emulate_tlb_invalidate(struct kvm_vcpu *vcpu,
+				   struct sys_reg_params *p,
+				   const struct sys_reg_desc *r)
+{
+	u32 opcode = sys_reg(p->Op0, p->Op1, p->CRn, p->CRm, p->Op2);
+
+	kvm_call_hyp(__kvm_emulate_tlb_invalidate,
+		     vcpu->kvm, opcode, p->regval);
+	trace_kvm_tlb_invalidate(*vcpu_pc(vcpu), opcode);
+	++vcpu->stat.tlb_invalidate;
+
+	return true;
+}
+
 /* Silly macro to expand the DBG{BCR,BVR,WVR,WCR}n_EL1 registers in one go */
 #define DBG_BCR_BVR_WCR_WVR_EL1(n)					\
 	/* DBGBVRn_EL1 */						\
@@ -842,6 +856,35 @@ static const struct sys_reg_desc sys_reg_descs[] = {
 	{ Op0(0b01), Op1(0b000), CRn(0b0111), CRm(0b1110), Op2(0b010),
 	  access_dcsw },
 
+	/*
+	 * ARMv8 ARM: Table C5-4 TLB maintenance instructions
+	 * (Ref: ARMv8 ARM C5.1 version: ARM DDI 0487A.j)
+	 */
+	/* TLBI VMALLE1IS */
+	{ Op0(1), Op1(0), CRn(8), CRm(3), Op2(0), emulate_tlb_invalidate },
+	/* TLBI VAE1IS */
+	{ Op0(1), Op1(0), CRn(8), CRm(3), Op2(1), emulate_tlb_invalidate },
+	/* TLBI ASIDE1IS */
+	{ Op0(1), Op1(0), CRn(8), CRm(3), Op2(2), emulate_tlb_invalidate },
+	/* TLBI VAAE1IS */
+	{ Op0(1), Op1(0), CRn(8), CRm(3), Op2(3), emulate_tlb_invalidate },
+	/* TLBI VALE1IS */
+	{ Op0(1), Op1(0), CRn(8), CRm(3), Op2(5), emulate_tlb_invalidate },
+	/* TLBI VAALE1IS */
+	{ Op0(1), Op1(0), CRn(8), CRm(3), Op2(7), emulate_tlb_invalidate },
+	/* TLBI VMALLE1 */
+	{ Op0(1), Op1(0), CRn(8), CRm(7), Op2(0), emulate_tlb_invalidate },
+	/* TLBI VAE1 */
+	{ Op0(1), Op1(0), CRn(8), CRm(7), Op2(1), emulate_tlb_invalidate },
+	/* TLBI ASIDE1 */
+	{ Op0(1), Op1(0), CRn(8), CRm(7), Op2(2), emulate_tlb_invalidate },
+	/* TLBI VAAE1 */
+	{ Op0(1), Op1(0), CRn(8), CRm(7), Op2(3), emulate_tlb_invalidate },
+	/* TLBI VALE1 */
+	{ Op0(1), Op1(0), CRn(8), CRm(7), Op2(5), emulate_tlb_invalidate },
+	/* TLBI VAALE1 */
+	{ Op0(1), Op1(0), CRn(8), CRm(7), Op2(7), emulate_tlb_invalidate },
+
 	DBG_BCR_BVR_WCR_WVR_EL1(0),
 	DBG_BCR_BVR_WCR_WVR_EL1(1),
 	/* MDCCINT_EL1 */
@@ -1330,6 +1373,46 @@ static const struct sys_reg_desc cp15_regs[] = {
 	{ Op1( 0), CRn( 7), CRm(10), Op2( 2), access_dcsw },
 	{ Op1( 0), CRn( 7), CRm(14), Op2( 2), access_dcsw },
 
+	/*
+	 * TLB operations
+	 */
+	/* TLBIALLIS */
+	{ Op1( 0), CRn( 8), CRm( 3), Op2( 0), emulate_tlb_invalidate},
+	/* TLBIMVAIS */
+	{ Op1( 0), CRn( 8), CRm( 3), Op2( 1), emulate_tlb_invalidate},
+	/* TLBIASIDIS */
+	{ Op1( 0), CRn( 8), CRm( 3), Op2( 2), emulate_tlb_invalidate},
+	/* TLBIMVAAIS */
+	{ Op1( 0), CRn( 8), CRm( 3), Op2( 3), emulate_tlb_invalidate},
+	/* TLBIMVALIS */
+	{ Op1( 0), CRn( 8), CRm( 3), Op2( 5), emulate_tlb_invalidate},
+	/* TLBIMVAALIS */
+	{ Op1( 0), CRn( 8), CRm( 3), Op2( 7), emulate_tlb_invalidate},
+	/* ITLBIALL */
+	{ Op1( 0), CRn( 8), CRm( 5), Op2( 0), emulate_tlb_invalidate},
+	/* ITLBIMVA */
+	{ Op1( 0), CRn( 8), CRm( 5), Op2( 1), emulate_tlb_invalidate},
+	/* ITLBIASID */
+	{ Op1( 0), CRn( 8), CRm( 5), Op2( 2), emulate_tlb_invalidate},
+	/* DTLBIALL */
+	{ Op1( 0), CRn( 8), CRm( 6), Op2( 0), emulate_tlb_invalidate},
+	/* DTLBIMVA */
+	{ Op1( 0), CRn( 8), CRm( 6), Op2( 1), emulate_tlb_invalidate},
+	/* DTLBIASID */
+	{ Op1( 0), CRn( 8), CRm( 6), Op2( 2), emulate_tlb_invalidate},
+	/* TLBIALL */
+	{ Op1( 0), CRn( 8), CRm( 7), Op2( 0), emulate_tlb_invalidate},
+	/* TLBIMVA */
+	{ Op1( 0), CRn( 8), CRm( 7), Op2( 1), emulate_tlb_invalidate},
+	/* TLBIASID */
+	{ Op1( 0), CRn( 8), CRm( 7), Op2( 2), emulate_tlb_invalidate},
+	/* TLBIMVAA */
+	{ Op1( 0), CRn( 8), CRm( 7), Op2( 3), emulate_tlb_invalidate},
+	/* TLBIMVAL */
+	{ Op1( 0), CRn( 8), CRm( 7), Op2( 5), emulate_tlb_invalidate},
+	/* TLBIMVAAL */
+	{ Op1( 0), CRn( 8), CRm( 7), Op2( 7), emulate_tlb_invalidate},
+
 	/* PMU */
 	{ Op1( 0), CRn( 9), CRm(12), Op2( 0), access_pmcr },
 	{ Op1( 0), CRn( 9), CRm(12), Op2( 1), access_pmcnten },
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v4 5/9] kvm: Add host pmu to support VM introspection
  2017-01-31 17:16 [PATCH v4 0/9] Add support for monitoring guest TLB operations Punit Agrawal
                   ` (3 preceding siblings ...)
  2017-01-31 17:16 ` [PATCH v4 4/9] arm64: " Punit Agrawal
@ 2017-01-31 17:16 ` Punit Agrawal
  2017-01-31 17:16 ` [PATCH v4 6/9] KVM: arm/arm64: Add support for tracking guest TLB operations Punit Agrawal
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Punit Agrawal @ 2017-01-31 17:16 UTC (permalink / raw)
  To: kvmarm, linux-arm-kernel
  Cc: Punit Agrawal, linux-kernel, kvm, Christoffer Dall, Marc Zyngier,
	Peter Zijlstra, Will Deacon, Mark Rutland, Paolo Bonzini,
	Radim Krčmář

Add a software PMU on the host that supports tracking VM operations (in
the form of PMU events). To add support for events, users of this
functionality will provide the callbacks to configure the VM to
enable/disable the events and read a count of the event's frequency.

The host PMU events can be controlled by tools like perf using standard
kernel perf interfaces.

Signed-off-by: Punit Agrawal <punit.agrawal@arm.com>
Cc: Christoffer Dall <christoffer.dall@linaro.org>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: "Radim Krčmář" <rkrcmar@redhat.com>
Cc: Mark Rutland <mark.rutland@arm.com>
---
 include/kvm/host_pmu.h |  35 +++++++
 virt/kvm/Kconfig       |   3 +
 virt/kvm/host_pmu.c    | 246 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 284 insertions(+)
 create mode 100644 include/kvm/host_pmu.h
 create mode 100644 virt/kvm/host_pmu.c

diff --git a/include/kvm/host_pmu.h b/include/kvm/host_pmu.h
new file mode 100644
index 000000000000..f9dc21de8886
--- /dev/null
+++ b/include/kvm/host_pmu.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2017 ARM Ltd.
+ * Author: Punit Agrawal <punit.agrawal@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef _KVM_HOST_PMU_H
+#define _KVM_HOST_PMU_H
+
+#include <linux/kvm_host.h>
+#include <linux/perf_event.h>
+
+typedef void (*configure_event_fn)(struct kvm_vcpu *vcpu, bool enable);
+typedef u64 (*get_event_count_fn)(struct kvm_vcpu *vcpu);
+
+struct kvm_event_cb {
+	get_event_count_fn get_event_count;
+	configure_event_fn configure_event;
+};
+
+int kvm_host_pmu_register(int nr_events, struct kvm_event_cb *cbs,
+			  struct attribute **event_attrs);
+void kvm_host_pmu_unregister(void);
+
+#endif /* _KVM_HOST_PMU_H */
diff --git a/virt/kvm/Kconfig b/virt/kvm/Kconfig
index b0cc1a34db27..3fe27172e757 100644
--- a/virt/kvm/Kconfig
+++ b/virt/kvm/Kconfig
@@ -50,3 +50,6 @@ config KVM_COMPAT
 
 config HAVE_KVM_IRQ_BYPASS
        bool
+
+config KVM_HOST_PMU
+	bool
\ No newline at end of file
diff --git a/virt/kvm/host_pmu.c b/virt/kvm/host_pmu.c
new file mode 100644
index 000000000000..ae7c0c3aed92
--- /dev/null
+++ b/virt/kvm/host_pmu.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2017 ARM Ltd.
+ * Author: Punit Agrawal <punit.agrawal@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <kvm/host_pmu.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/kvm_host.h>
+#include <linux/list.h>
+#include <linux/perf_event.h>
+#include <linux/pid.h>
+#include <linux/slab.h>
+#include <linux/spinlock_types.h>
+#include <linux/sysfs.h>
+
+struct host_pmu {
+	int nr_events;
+	struct pmu pmu;
+	struct kvm_event_cb *cbs;
+	spinlock_t event_list_lock;
+	struct list_head event_list_head;
+} host_pmu;
+#define to_host_pmu(p) (container_of(p, struct host_pmu, pmu))
+
+struct event_data {
+	int event_id;
+	struct kvm_vcpu *vcpu;
+	struct kvm_event_cb *cb;
+	struct list_head event_list;
+};
+
+static struct attribute_group events_attr_group = {
+	.name	= "events",
+};
+
+
+#define EVENT_MASK	GENMASK_ULL(0, 7)
+#define to_event(cfg)	((cfg) & EVENT_MASK)
+
+PMU_FORMAT_ATTR(event, "config:0-7");
+
+static struct attribute *format_attrs[] = {
+	&format_attr_event.attr,
+	NULL,
+};
+
+static struct attribute_group format_attr_group = {
+	.name	= "format",
+	.attrs	= format_attrs,
+};
+
+static const struct attribute_group *attr_groups[] = {
+	&events_attr_group,
+	&format_attr_group,
+	NULL,
+};
+
+static void host_event_destroy(struct perf_event *event)
+{
+	struct host_pmu *host_pmu = to_host_pmu(event->pmu);
+	struct event_data *e_data = event->pmu_private;
+
+	spin_lock(&host_pmu->event_list_lock);
+	list_del(&e_data->event_list);
+	spin_unlock(&host_pmu->event_list_lock);
+	kfree(e_data);
+}
+
+static int host_event_init(struct perf_event *event)
+{
+	struct host_pmu *host_pmu = to_host_pmu(event->pmu);
+	int event_id = to_event(event->attr.config);
+	struct event_data *e_data, *pos;
+	struct kvm_vcpu *vcpu;
+	bool found = false;
+	struct pid *pid;
+	struct kvm *kvm;
+	int i, ret = 0;
+
+	if (event->attr.type != event->pmu->type)
+		return -ENOENT;
+
+	if (has_branch_stack(event)	||
+	    is_sampling_event(event)	||
+	    event->attr.exclude_user	||
+	    event->attr.exclude_kernel	||
+	    event->attr.exclude_hv	||
+	    event->attr.exclude_idle	||
+	    event->attr.exclude_guest) {
+		return -EINVAL;
+	}
+
+	if (event->attach_state != PERF_ATTACH_TASK)
+		return -EOPNOTSUPP;
+
+	if (event_id >= host_pmu->nr_events)
+		return -EINVAL;
+
+	pid = get_task_pid(event->hw.target, PIDTYPE_PID);
+	spin_lock(&kvm_lock);
+	list_for_each_entry(kvm, &vm_list, vm_list) {
+		kvm_for_each_vcpu(i, vcpu, kvm) {
+			if (vcpu->pid == pid) {
+				found = true;
+				goto found;
+			}
+		}
+	}
+found:
+	spin_unlock(&kvm_lock);
+	put_pid(pid);
+
+	if (!found)
+		return -EINVAL;
+
+	spin_lock(&host_pmu->event_list_lock);
+	/* Make sure we don't already have the (event_id, kvm) pair */
+	list_for_each_entry(pos, &host_pmu->event_list_head, event_list) {
+		if (pos->event_id == event_id &&
+		    pos->vcpu->pid == pid) {
+			ret = -EOPNOTSUPP;
+			goto unlock;
+		}
+	}
+
+	e_data = kzalloc(sizeof(*e_data), GFP_KERNEL);
+	e_data->event_id = event_id;
+	e_data->vcpu = vcpu;
+	e_data->cb = &host_pmu->cbs[event_id];
+
+	event->pmu_private = e_data;
+	event->destroy = host_event_destroy;
+
+	list_add_tail(&e_data->event_list, &host_pmu->event_list_head);
+
+unlock:
+	spin_unlock(&host_pmu->event_list_lock);
+
+	return ret;
+}
+
+static void host_event_update(struct perf_event *event)
+{
+	struct event_data *e_data = event->pmu_private;
+	struct kvm_event_cb *cb = e_data->cb;
+	struct kvm_vcpu *vcpu = e_data->vcpu;
+	struct hw_perf_event *hw = &event->hw;
+	u64 prev_count, new_count;
+
+	do {
+		prev_count = local64_read(&hw->prev_count);
+		new_count = cb->get_event_count(vcpu);
+	} while (local64_xchg(&hw->prev_count, new_count) != prev_count);
+
+	local64_add(new_count - prev_count, &event->count);
+}
+
+static void host_event_start(struct perf_event *event, int flags)
+{
+	struct event_data *e_data = event->pmu_private;
+	struct kvm_event_cb *cb = e_data->cb;
+	struct kvm_vcpu *vcpu = e_data->vcpu;
+	u64 val;
+
+	val = cb->get_event_count(vcpu);
+	local64_set(&event->hw.prev_count, val);
+
+	cb->configure_event(vcpu, true);
+}
+
+static void host_event_stop(struct perf_event *event, int flags)
+{
+	struct event_data *e_data = event->pmu_private;
+	struct kvm_event_cb *cb = e_data->cb;
+	struct kvm_vcpu *vcpu = e_data->vcpu;
+
+	cb->configure_event(vcpu, false);
+
+	if (flags & PERF_EF_UPDATE)
+		host_event_update(event);
+}
+
+static int host_event_add(struct perf_event *event, int flags)
+{
+	if (flags & PERF_EF_START)
+		host_event_start(event, flags);
+
+	return 0;
+}
+
+static void host_event_del(struct perf_event *event, int flags)
+{
+	host_event_stop(event, PERF_EF_UPDATE);
+}
+
+static void host_event_read(struct perf_event *event)
+{
+	host_event_update(event);
+}
+
+static void init_host_pmu(struct host_pmu *host_pmu)
+{
+	host_pmu->pmu = (struct pmu) {
+		.task_ctx_nr	= perf_sw_context,
+		.attr_groups	= attr_groups,
+		.event_init	= host_event_init,
+		.add		= host_event_add,
+		.del		= host_event_del,
+		.start		= host_event_start,
+		.stop		= host_event_stop,
+		.read		= host_event_read,
+		.capabilities	= PERF_PMU_CAP_NO_INTERRUPT,
+	};
+
+	INIT_LIST_HEAD(&host_pmu->event_list_head);
+	spin_lock_init(&host_pmu->event_list_lock);
+}
+
+int kvm_host_pmu_register(int nr_events, struct kvm_event_cb *cbs,
+			  struct attribute **event_attrs)
+{
+	host_pmu.nr_events  = nr_events;
+	host_pmu.cbs = cbs;
+	events_attr_group.attrs = event_attrs;
+
+	init_host_pmu(&host_pmu);
+
+	return perf_pmu_register(&host_pmu.pmu, "kvm", -1);
+}
+
+void kvm_host_pmu_unregister(void)
+{
+	perf_pmu_unregister(&host_pmu.pmu);
+}
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v4 6/9] KVM: arm/arm64: Add support for tracking guest TLB operations
  2017-01-31 17:16 [PATCH v4 0/9] Add support for monitoring guest TLB operations Punit Agrawal
                   ` (4 preceding siblings ...)
  2017-01-31 17:16 ` [PATCH v4 5/9] kvm: Add host pmu to support VM introspection Punit Agrawal
@ 2017-01-31 17:16 ` Punit Agrawal
  2017-01-31 17:16 ` [PATCH v4 7/9] arm64: KVM: Enable support for the host pmu Punit Agrawal
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Punit Agrawal @ 2017-01-31 17:16 UTC (permalink / raw)
  To: kvmarm, linux-arm-kernel
  Cc: Punit Agrawal, linux-kernel, kvm, Christoffer Dall, Marc Zyngier,
	Peter Zijlstra, Will Deacon, Mark Rutland

The host pmu supports monitoring of VM operations. Register a host pmu
and provide the necessary callbacks to enable monitoring TLB operations.

Signed-off-by: Punit Agrawal <punit.agrawal@arm.com>
Cc: Christoffer Dall <christoffer.dall@linaro.org>
Cc: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/host_pmu_events.c | 82 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 82 insertions(+)
 create mode 100644 virt/kvm/arm/host_pmu_events.c

diff --git a/virt/kvm/arm/host_pmu_events.c b/virt/kvm/arm/host_pmu_events.c
new file mode 100644
index 000000000000..a5f097a6fb21
--- /dev/null
+++ b/virt/kvm/arm/host_pmu_events.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2017 ARM Ltd.
+ * Author: Punit Agrawal <punit.agrawal@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <kvm/host_pmu.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/kvm_host.h>
+#include <linux/sysfs.h>
+#include <linux/types.h>
+
+#include <asm/kvm_emulate.h>
+
+enum host_pmu_events {
+	tlb_invalidate,
+	MAX_EVENTS,
+};
+
+static u64 get_tlb_invalidate_count(struct kvm_vcpu *vcpu)
+{
+	return vcpu->stat.tlb_invalidate;
+}
+
+static void configure_tlb_invalidate(struct kvm_vcpu *vcpu, bool enable)
+{
+	unsigned long hcr;
+
+	hcr = vcpu_get_hcr(vcpu);
+
+	if (enable)
+		hcr |= HCR_TTLB;
+	else
+		hcr &= ~HCR_TTLB;
+
+	vcpu_set_hcr(vcpu, hcr);
+}
+
+static ssize_t events_sysfs_show(struct device *dev,
+				 struct device_attribute *attr, char *page)
+{
+	struct perf_pmu_events_attr *pmu_attr;
+
+	pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr);
+
+	return sprintf(page, "event=0x%03llx\n", pmu_attr->id);
+}
+PMU_EVENT_ATTR(tlb_invalidate, event_attr_tlb_invalidate, tlb_invalidate,
+	       events_sysfs_show);
+
+static struct attribute *event_attrs[] = {
+	&event_attr_tlb_invalidate.attr.attr,
+	NULL,
+};
+
+static struct kvm_event_cb event_callbacks[] = {
+	{
+		.get_event_count = get_tlb_invalidate_count,
+		.configure_event = configure_tlb_invalidate,
+	},
+};
+
+int arm_host_pmu_init(void)
+{
+	return kvm_host_pmu_register(MAX_EVENTS, event_callbacks, event_attrs);
+}
+
+void arm_host_pmu_teardown(void)
+{
+	kvm_host_pmu_unregister();
+}
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v4 7/9] arm64: KVM: Enable support for the host pmu
  2017-01-31 17:16 [PATCH v4 0/9] Add support for monitoring guest TLB operations Punit Agrawal
                   ` (5 preceding siblings ...)
  2017-01-31 17:16 ` [PATCH v4 6/9] KVM: arm/arm64: Add support for tracking guest TLB operations Punit Agrawal
@ 2017-01-31 17:16 ` Punit Agrawal
  2017-01-31 17:16 ` [PATCH v4 8/9] arm: KVM: Enable support for " Punit Agrawal
  2017-01-31 17:16 ` [PATCH v4 9/9] arm/arm64: KVM: Initialise the " Punit Agrawal
  8 siblings, 0 replies; 10+ messages in thread
From: Punit Agrawal @ 2017-01-31 17:16 UTC (permalink / raw)
  To: kvmarm, linux-arm-kernel
  Cc: Punit Agrawal, linux-kernel, kvm, Christoffer Dall, Marc Zyngier,
	Will Deacon, Mark Rutland

Add the Kconfig option and Makefile update the enable the recently added
host pmu.

Signed-off-by: Punit Agrawal <punit.agrawal@arm.com>
Cc: Christoffer Dall <christoffer.dall@linaro.org>
Cc: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/include/asm/kvm_host.h | 8 ++++++++
 arch/arm64/kvm/Kconfig            | 1 +
 arch/arm64/kvm/Makefile           | 1 +
 3 files changed, 10 insertions(+)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 1e83b707f14c..78c4e9af64b1 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -349,6 +349,14 @@ int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
 int kvm_perf_init(void);
 int kvm_perf_teardown(void);
 
+#if !defined(CONFIG_KVM_HOST_PMU)
+static inline int arm_host_pmu_init(void) { return 0; }
+static inline void arm_host_pmu_teardown(void) { }
+#else
+int arm_host_pmu_init(void);
+void arm_host_pmu_teardown(void);
+#endif
+
 struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr);
 
 static inline void __cpu_init_hyp_mode(phys_addr_t pgd_ptr,
diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
index 52cb7ad9b2fd..608adb532118 100644
--- a/arch/arm64/kvm/Kconfig
+++ b/arch/arm64/kvm/Kconfig
@@ -31,6 +31,7 @@ config KVM
 	select KVM_VFIO
 	select HAVE_KVM_EVENTFD
 	select HAVE_KVM_IRQFD
+	select KVM_HOST_PMU if PERF_EVENTS
 	select KVM_ARM_PMU if HW_PERF_EVENTS
 	select HAVE_KVM_MSI
 	select HAVE_KVM_IRQCHIP
diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
index d50a82a16ff6..b12c78c9e9dd 100644
--- a/arch/arm64/kvm/Makefile
+++ b/arch/arm64/kvm/Makefile
@@ -34,3 +34,4 @@ kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-its.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/irqchip.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/arch_timer.o
 kvm-$(CONFIG_KVM_ARM_PMU) += $(KVM)/arm/pmu.o
+kvm-$(CONFIG_KVM_HOST_PMU) += $(KVM)/host_pmu.o $(KVM)/arm/host_pmu_events.o
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v4 8/9] arm: KVM: Enable support for host pmu
  2017-01-31 17:16 [PATCH v4 0/9] Add support for monitoring guest TLB operations Punit Agrawal
                   ` (6 preceding siblings ...)
  2017-01-31 17:16 ` [PATCH v4 7/9] arm64: KVM: Enable support for the host pmu Punit Agrawal
@ 2017-01-31 17:16 ` Punit Agrawal
  2017-01-31 17:16 ` [PATCH v4 9/9] arm/arm64: KVM: Initialise the " Punit Agrawal
  8 siblings, 0 replies; 10+ messages in thread
From: Punit Agrawal @ 2017-01-31 17:16 UTC (permalink / raw)
  To: kvmarm, linux-arm-kernel
  Cc: Punit Agrawal, linux-kernel, kvm, Christoffer Dall, Marc Zyngier,
	Will Deacon, Mark Rutland, Russell King

Add the Kconfig option and Makefile updates to enable the recently added
support for host pmu.

Signed-off-by: Punit Agrawal <punit.agrawal@arm.com>
Cc: Christoffer Dall <christoffer.dall@linaro.org>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: Russell King <linux@armlinux.org.uk>
---
 arch/arm/include/asm/kvm_host.h | 8 ++++++++
 arch/arm/kvm/Kconfig            | 1 +
 arch/arm/kvm/Makefile           | 1 +
 3 files changed, 10 insertions(+)

diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index 26f0c8a0b790..b530c85db894 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -289,6 +289,14 @@ static inline int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext)
 int kvm_perf_init(void);
 int kvm_perf_teardown(void);
 
+#if !defined(CONFIG_KVM_HOST_PMU)
+static inline int arm_host_pmu_init(void) { return 0; }
+static inline void arm_host_pmu_teardown(void) { }
+#else
+int arm_host_pmu_init(void);
+void arm_host_pmu_teardown(void);
+#endif
+
 void kvm_mmu_wp_memory_region(struct kvm *kvm, int slot);
 
 struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr);
diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig
index 90d0176fb30d..fbc09bd161fd 100644
--- a/arch/arm/kvm/Kconfig
+++ b/arch/arm/kvm/Kconfig
@@ -30,6 +30,7 @@ config KVM
 	select SRCU
 	select MMU_NOTIFIER
 	select KVM_VFIO
+	select KVM_HOST_PMU if PERF_EVENTS
 	select HAVE_KVM_EVENTFD
 	select HAVE_KVM_IRQFD
 	select HAVE_KVM_IRQCHIP
diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile
index d571243ab4d1..639aaef165f3 100644
--- a/arch/arm/kvm/Makefile
+++ b/arch/arm/kvm/Makefile
@@ -35,3 +35,4 @@ obj-y += $(KVM)/arm/vgic/vgic-kvm-device.o
 obj-y += $(KVM)/arm/vgic/vgic-its.o
 obj-y += $(KVM)/irqchip.o
 obj-y += $(KVM)/arm/arch_timer.o
+obj-$(CONFIG_KVM_HOST_PMU) += $(KVM)/host_pmu.o $(KVM)/arm/host_pmu_events.o
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v4 9/9] arm/arm64: KVM: Initialise the host pmu
  2017-01-31 17:16 [PATCH v4 0/9] Add support for monitoring guest TLB operations Punit Agrawal
                   ` (7 preceding siblings ...)
  2017-01-31 17:16 ` [PATCH v4 8/9] arm: KVM: Enable support for " Punit Agrawal
@ 2017-01-31 17:16 ` Punit Agrawal
  8 siblings, 0 replies; 10+ messages in thread
From: Punit Agrawal @ 2017-01-31 17:16 UTC (permalink / raw)
  To: kvmarm, linux-arm-kernel
  Cc: Punit Agrawal, linux-kernel, kvm, Christoffer Dall, Marc Zyngier,
	Will Deacon, Mark Rutland

Now that we've added support for handling TLB traps as well as
infrastructure for monitoring these operations, all that remains is
initialising the host pmu for arm/arm64.

Signed-off-by: Punit Agrawal <punit.agrawal@arm.com>
Cc: Christoffer Dall <christoffer.dall@linaro.org>
Cc: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/kvm/arm.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 9d7446456e0c..e5f77a3d08ea 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -1266,6 +1266,7 @@ static int init_subsystems(void)
 		goto out;
 
 	kvm_perf_init();
+	arm_host_pmu_init();
 	kvm_coproc_table_init();
 
 out:
@@ -1456,6 +1457,7 @@ int kvm_arch_init(void *opaque)
 void kvm_arch_exit(void)
 {
 	kvm_perf_teardown();
+	arm_host_pmu_teardown();
 }
 
 static int arm_init(void)
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2017-01-31 17:30 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-01-31 17:16 [PATCH v4 0/9] Add support for monitoring guest TLB operations Punit Agrawal
2017-01-31 17:16 ` [PATCH v4 1/9] arm64/kvm: hyp: tlb: use __tlbi() helper Punit Agrawal
2017-01-31 17:16 ` [PATCH v4 2/9] KVM: Add event to trace tlb invalidations Punit Agrawal
2017-01-31 17:16 ` [PATCH v4 3/9] arm: KVM: Handle trappable TLB instructions Punit Agrawal
2017-01-31 17:16 ` [PATCH v4 4/9] arm64: " Punit Agrawal
2017-01-31 17:16 ` [PATCH v4 5/9] kvm: Add host pmu to support VM introspection Punit Agrawal
2017-01-31 17:16 ` [PATCH v4 6/9] KVM: arm/arm64: Add support for tracking guest TLB operations Punit Agrawal
2017-01-31 17:16 ` [PATCH v4 7/9] arm64: KVM: Enable support for the host pmu Punit Agrawal
2017-01-31 17:16 ` [PATCH v4 8/9] arm: KVM: Enable support for " Punit Agrawal
2017-01-31 17:16 ` [PATCH v4 9/9] arm/arm64: KVM: Initialise the " Punit Agrawal

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).