From c16a3265992ba8159ab1da6d589026c0aa0914ba Mon Sep 17 00:00:00 2001 From: Anup Patel 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 Signed-off-by: Anup Patel --- 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 @@ -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 +#include + +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