On Tue, Aug 5, 2014 at 2:54 PM, Anup Patel <anup.patel@xxxxxxxxxx> wrote: > This patchset enables PMU virtualization in KVM ARM64. The > Guest can now directly use PMU available on the host HW. > > The virtual PMU IRQ injection for Guest VCPUs is managed by > small piece of code shared between KVM ARM and KVM ARM64. The > virtual PMU IRQ number will be based on Guest machine model and > user space will provide it using set device address vm ioctl. > > The second last patch of this series implements full context > switch of PMU registers which will context switch all PMU > registers on every KVM world-switch. > > The last patch implements a lazy context switch of PMU registers > which is very similar to lazy debug context switch. > (Refer, http://lists.infradead.org/pipermail/linux-arm-kernel/2014-July/271040.html) > > Also, we reserve last PMU event counter for EL2 mode which > will not be accessible from Host and Guest EL1 mode. This > reserved EL2 mode PMU event counter can be used for profiling > KVM world-switch and other EL2 mode functions. > > All testing have been done using KVMTOOL on X-Gene Mustang and > Foundation v8 Model for both Aarch32 and Aarch64 guest. > > Anup Patel (6): > ARM64: Move PMU register related defines to asm/pmu.h > ARM64: perf: Re-enable overflow interrupt from interrupt handler > ARM: perf: Re-enable overflow interrupt from interrupt handler > ARM/ARM64: KVM: Add common code PMU IRQ routing > ARM64: KVM: Implement full context switch of PMU registers > ARM64: KVM: Upgrade to lazy context switch of PMU registers > > arch/arm/include/asm/kvm_host.h | 9 + > arch/arm/include/uapi/asm/kvm.h | 1 + > arch/arm/kernel/perf_event_v7.c | 8 + > arch/arm/kvm/arm.c | 6 + > arch/arm/kvm/reset.c | 4 + > arch/arm64/include/asm/kvm_asm.h | 39 +++- > arch/arm64/include/asm/kvm_host.h | 12 ++ > arch/arm64/include/asm/pmu.h | 44 +++++ > arch/arm64/include/uapi/asm/kvm.h | 1 + > arch/arm64/kernel/asm-offsets.c | 2 + > arch/arm64/kernel/perf_event.c | 40 +--- > arch/arm64/kvm/Kconfig | 7 + > arch/arm64/kvm/Makefile | 1 + > arch/arm64/kvm/hyp-init.S | 15 ++ > arch/arm64/kvm/hyp.S | 209 +++++++++++++++++++- > arch/arm64/kvm/reset.c | 4 + > arch/arm64/kvm/sys_regs.c | 385 +++++++++++++++++++++++++++++++++---- > include/kvm/arm_pmu.h | 52 +++++ > virt/kvm/arm/pmu.c | 105 ++++++++++ > 19 files changed, 870 insertions(+), 74 deletions(-) > create mode 100644 include/kvm/arm_pmu.h > create mode 100644 virt/kvm/arm/pmu.c > > -- > 1.7.9.5 > > CONFIDENTIALITY NOTICE: This e-mail message, including any attachments, > is for the sole use of the intended recipient(s) and contains information > that is confidential and proprietary to Applied Micro Circuits Corporation or its subsidiaries. > It is to be used solely for the purpose of furthering the parties' business relationship. > All unauthorized review, use, disclosure or distribution is prohibited. > If you are not the intended recipient, please contact the sender by reply e-mail > and destroy all copies of the original message. > Hi All, Please apply attached patch to KVMTOOL on-top-of my recent KVMTOOL patchset for trying this patchset using KVMTOOL. Regards, Anup
From c16a3265992ba8159ab1da6d589026c0aa0914ba Mon Sep 17 00:00:00 2001 From: Anup Patel <anup.patel@xxxxxxxxxx> Date: Mon, 4 Aug 2014 16:45:44 +0530 Subject: [RFC PATCH] kvmtool: ARM/ARM64: Add PMU node to generated guest DTB. This patch informs KVM ARM/ARM64 in-kernel PMU virtualization about the PMU irq numbers for each guest VCPU using set device address vm ioctl. We also adds PMU node in generated guest DTB to inform guest about the PMU irq numbers. For now, we have assumed PPI17 as PMU IRQ of KVMTOOL guest. Signed-off-by: Pranavkumar Sawargaonkar <pranavkumar@xxxxxxxxxx> Signed-off-by: Anup Patel <anup.patel@xxxxxxxxxx> --- tools/kvm/Makefile | 3 ++- tools/kvm/arm/fdt.c | 4 +++ tools/kvm/arm/include/arm-common/pmu.h | 10 +++++++ tools/kvm/arm/pmu.c | 45 ++++++++++++++++++++++++++++++++ 4 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 tools/kvm/arm/include/arm-common/pmu.h create mode 100644 tools/kvm/arm/pmu.c diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile index fba60f1..59b75c4 100644 --- a/tools/kvm/Makefile +++ b/tools/kvm/Makefile @@ -158,7 +158,8 @@ endif # ARM OBJS_ARM_COMMON := arm/fdt.o arm/gic.o arm/ioport.o arm/irq.o \ - arm/kvm.o arm/kvm-cpu.o arm/pci.o arm/timer.o + arm/kvm.o arm/kvm-cpu.o arm/pci.o arm/timer.o \ + arm/pmu.o HDRS_ARM_COMMON := arm/include ifeq ($(ARCH), arm) DEFINES += -DCONFIG_ARM diff --git a/tools/kvm/arm/fdt.c b/tools/kvm/arm/fdt.c index 93849cf2..42b0a67 100644 --- a/tools/kvm/arm/fdt.c +++ b/tools/kvm/arm/fdt.c @@ -5,6 +5,7 @@ #include "kvm/virtio-mmio.h" #include "arm-common/gic.h" +#include "arm-common/pmu.h" #include "arm-common/pci.h" #include <stdbool.h> @@ -142,6 +143,9 @@ static int setup_fdt(struct kvm *kvm) if (generate_cpu_peripheral_fdt_nodes) generate_cpu_peripheral_fdt_nodes(fdt, kvm, gic_phandle); + /* Performance monitoring unit */ + pmu__generate_fdt_nodes(fdt, kvm); + /* Virtio MMIO devices */ dev_hdr = device__first_dev(DEVICE_BUS_MMIO); while (dev_hdr) { diff --git a/tools/kvm/arm/include/arm-common/pmu.h b/tools/kvm/arm/include/arm-common/pmu.h new file mode 100644 index 0000000..49ec9a8 --- /dev/null +++ b/tools/kvm/arm/include/arm-common/pmu.h @@ -0,0 +1,10 @@ +#ifndef ARM_COMMON__PMU_H +#define ARM_COMMON__PMU_H + +#define PMU_CPU_IRQ 17 + +struct kvm; + +void pmu__generate_fdt_nodes(void *fdt, struct kvm *kvm); + +#endif /* ARM_COMMON__PMU_H */ diff --git a/tools/kvm/arm/pmu.c b/tools/kvm/arm/pmu.c new file mode 100644 index 0000000..7731a4c --- /dev/null +++ b/tools/kvm/arm/pmu.c @@ -0,0 +1,45 @@ +#include "kvm/devices.h" +#include "kvm/fdt.h" +#include "kvm/kvm.h" +#include "kvm/kvm-cpu.h" + +#include "arm-common/gic.h" +#include "arm-common/pmu.h" + +#include <linux/byteorder.h> +#include <linux/kvm.h> + +void pmu__generate_fdt_nodes(void *fdt, struct kvm *kvm) +{ + int cpu, err; + const char compatible[] = "arm,armv8-pmuv3\0arm,cortex-a15-pmu"; + u32 cpu_mask = (((1 << kvm->nrcpus) - 1) << GIC_FDT_IRQ_PPI_CPU_SHIFT) \ + & GIC_FDT_IRQ_PPI_CPU_MASK; + u32 irq_prop[] = { + cpu_to_fdt32(GIC_FDT_IRQ_TYPE_PPI), + cpu_to_fdt32(PMU_CPU_IRQ - 0x10), + cpu_to_fdt32(cpu_mask | GIC_FDT_IRQ_FLAGS_EDGE_LO_HI), + }; + struct kvm_arm_device_addr pmu_addr = { + .id = KVM_ARM_DEVICE_PMU << KVM_ARM_DEVICE_ID_SHIFT, + .addr = PMU_CPU_IRQ, + }; + + for (cpu = 0; cpu < kvm->nrcpus; ++cpu) { + pmu_addr.id &= ~KVM_ARM_DEVICE_TYPE_MASK; + pmu_addr.id |= (cpu << KVM_ARM_DEVICE_TYPE_SHIFT) & + KVM_ARM_DEVICE_TYPE_MASK; + err = ioctl(kvm->vm_fd, KVM_ARM_SET_DEVICE_ADDR, &pmu_addr); + if (err) { + printf("%s: KVM_ARM_SET_DEVICE_ADDR failed for CPU%d", + __func__, cpu); + } + } + + _FDT(fdt_begin_node(fdt, "pmu")); + + _FDT(fdt_property(fdt, "compatible", compatible, sizeof(compatible))); + _FDT(fdt_property(fdt, "interrupts", irq_prop, sizeof(irq_prop))); + + _FDT(fdt_end_node(fdt)); +} -- 1.7.9.5