From patchwork Thu Sep 15 05:04:15 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wei Huang X-Patchwork-Id: 670205 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3sZRJx2grYz9s65 for ; Thu, 15 Sep 2016 15:08:49 +1000 (AEST) Received: from localhost ([::1]:59909 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bkOuk-0005l7-TS for incoming@patchwork.ozlabs.org; Thu, 15 Sep 2016 01:08:46 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37171) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bkOqc-0002wX-EB for qemu-devel@nongnu.org; Thu, 15 Sep 2016 01:04:31 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bkOqa-00036U-Rq for qemu-devel@nongnu.org; Thu, 15 Sep 2016 01:04:30 -0400 Received: from mx1.redhat.com ([209.132.183.28]:55256) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bkOqU-0002uk-0D; Thu, 15 Sep 2016 01:04:22 -0400 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4889C445D1; Thu, 15 Sep 2016 05:04:20 +0000 (UTC) Received: from apm-mustang-ev3-30.khw.lab.eng.bos.redhat.com (apm-mustang-ev3-30.khw.lab.eng.bos.redhat.com [10.16.184.124]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u8F54Ij5030796; Thu, 15 Sep 2016 01:04:19 -0400 From: Wei Huang To: qemu-arm@nongnu.org Date: Thu, 15 Sep 2016 01:04:15 -0400 Message-Id: <1473915856-23801-2-git-send-email-wei@redhat.com> In-Reply-To: <1473915856-23801-1-git-send-email-wei@redhat.com> References: <1473915856-23801-1-git-send-email-wei@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Thu, 15 Sep 2016 05:04:20 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH V3 1/2] arm64: Add an option to turn on/off vPMU support X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, drjones@redhat.com, qemu-devel@nongnu.org, abologna@redhat.com, shannon.zhao@linaro.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" This patch adds a pmu=[on/off] option to enable/disable vPMU support in guest vCPU. This option is only available for cortex-a57/cortex-53/ host under both TCG and KVM modes, but unavailable on ARMv7 and other processors. It allows virt tools, such as libvirt, to determine the exsitence of vPMU and configure it. Note that this option, turned off by default, can only be turned on under KVM mode; otherwise a warning message will be printed out. Signed-off-by: Wei Huang --- hw/arm/virt-acpi-build.c | 2 +- hw/arm/virt.c | 2 +- target-arm/cpu.c | 22 ++++++++++++++++++++++ target-arm/cpu.h | 1 + target-arm/cpu64.c | 2 ++ target-arm/kvm64.c | 19 +++++++++++++++---- 6 files changed, 42 insertions(+), 6 deletions(-) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 295ec86..8b3083e 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -540,7 +540,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info) gicc->uid = i; gicc->flags = cpu_to_le32(ACPI_GICC_ENABLED); - if (armcpu->has_pmu) { + if (arm_feature(&armcpu->env, ARM_FEATURE_PMU)) { gicc->performance_interrupt = cpu_to_le32(PPI(VIRTUAL_PMU_IRQ)); } } diff --git a/hw/arm/virt.c b/hw/arm/virt.c index a193b5a..a781ad0 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -477,7 +477,7 @@ static void fdt_add_pmu_nodes(const VirtBoardInfo *vbi, int gictype) CPU_FOREACH(cpu) { armcpu = ARM_CPU(cpu); - if (!armcpu->has_pmu || + if (!arm_feature(&armcpu->env, ARM_FEATURE_PMU) || !kvm_arm_pmu_create(cpu, PPI(VIRTUAL_PMU_IRQ))) { return; } diff --git a/target-arm/cpu.c b/target-arm/cpu.c index ce8b8f4..d304597 100644 --- a/target-arm/cpu.c +++ b/target-arm/cpu.c @@ -19,6 +19,7 @@ */ #include "qemu/osdep.h" +#include "qemu/error-report.h" #include "qapi/error.h" #include "cpu.h" #include "internals.h" @@ -509,6 +510,10 @@ static Property arm_cpu_rvbar_property = static Property arm_cpu_has_el3_property = DEFINE_PROP_BOOL("has_el3", ARMCPU, has_el3, true); +/* use property name "pmu" to match other archs and virt tools */ +static Property arm_cpu_has_pmu_property = + DEFINE_PROP_BOOL("pmu", ARMCPU, has_pmu, false); + static Property arm_cpu_has_mpu_property = DEFINE_PROP_BOOL("has-mpu", ARMCPU, has_mpu, true); @@ -552,6 +557,11 @@ static void arm_cpu_post_init(Object *obj) #endif } + if (arm_feature(&cpu->env, ARM_FEATURE_PMU)) { + qdev_property_add_static(DEVICE(obj), &arm_cpu_has_pmu_property, + &error_abort); + } + if (arm_feature(&cpu->env, ARM_FEATURE_MPU)) { qdev_property_add_static(DEVICE(obj), &arm_cpu_has_mpu_property, &error_abort); @@ -576,6 +586,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) ARMCPU *cpu = ARM_CPU(dev); ARMCPUClass *acc = ARM_CPU_GET_CLASS(dev); CPUARMState *env = &cpu->env; + static bool pmu_warned; /* Some features automatically imply others: */ if (arm_feature(env, ARM_FEATURE_V8)) { @@ -648,6 +659,17 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) cpu->id_aa64pfr0 &= ~0xf000; } + if (cpu->has_pmu && !kvm_enabled()) { + cpu->has_pmu = false; + if (!pmu_warned) { + error_report("warning: pmu can't be enabled without KVM acceleration"); + pmu_warned = true; + } + } + if (!cpu->has_pmu) { + unset_feature(env, ARM_FEATURE_PMU); + } + if (!arm_feature(env, ARM_FEATURE_EL2)) { /* Disable the hypervisor feature bits in the processor feature * registers if we don't have EL2. These are id_pfr1[15:12] and diff --git a/target-arm/cpu.h b/target-arm/cpu.h index 76d824d..5d9e6e7 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -1129,6 +1129,7 @@ enum arm_features { ARM_FEATURE_V8_SHA256, /* implements SHA256 part of v8 Crypto Extensions */ ARM_FEATURE_V8_PMULL, /* implements PMULL part of v8 Crypto Extensions */ ARM_FEATURE_THUMB_DSP, /* DSP insns supported in the Thumb encodings */ + ARM_FEATURE_PMU, /* has PMU support */ }; static inline int arm_feature(CPUARMState *env, int feature) diff --git a/target-arm/cpu64.c b/target-arm/cpu64.c index 1635deb..549cb1e 100644 --- a/target-arm/cpu64.c +++ b/target-arm/cpu64.c @@ -111,6 +111,7 @@ static void aarch64_a57_initfn(Object *obj) set_feature(&cpu->env, ARM_FEATURE_V8_PMULL); set_feature(&cpu->env, ARM_FEATURE_CRC); set_feature(&cpu->env, ARM_FEATURE_EL3); + set_feature(&cpu->env, ARM_FEATURE_PMU); cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A57; cpu->midr = 0x411fd070; cpu->revidr = 0x00000000; @@ -166,6 +167,7 @@ static void aarch64_a53_initfn(Object *obj) set_feature(&cpu->env, ARM_FEATURE_V8_PMULL); set_feature(&cpu->env, ARM_FEATURE_CRC); set_feature(&cpu->env, ARM_FEATURE_EL3); + set_feature(&cpu->env, ARM_FEATURE_PMU); cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A53; cpu->midr = 0x410fd034; cpu->revidr = 0x00000000; diff --git a/target-arm/kvm64.c b/target-arm/kvm64.c index 5faa76c..4e0124c 100644 --- a/target-arm/kvm64.c +++ b/target-arm/kvm64.c @@ -428,6 +428,11 @@ static inline void set_feature(uint64_t *features, int feature) *features |= 1ULL << feature; } +static inline void unset_feature(uint64_t *features, int feature) +{ + *features &= ~(1ULL << feature); +} + bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc) { /* Identify the feature bits corresponding to the host CPU, and @@ -469,6 +474,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc) set_feature(&features, ARM_FEATURE_VFP4); set_feature(&features, ARM_FEATURE_NEON); set_feature(&features, ARM_FEATURE_AARCH64); + set_feature(&features, ARM_FEATURE_PMU); ahcc->features = features; @@ -482,6 +488,7 @@ int kvm_arch_init_vcpu(CPUState *cs) int ret; uint64_t mpidr; ARMCPU *cpu = ARM_CPU(cs); + CPUARMState *env = &cpu->env; if (cpu->kvm_target == QEMU_KVM_ARM_TARGET_NONE || !object_dynamic_cast(OBJECT(cpu), TYPE_AARCH64_CPU)) { @@ -501,10 +508,14 @@ int kvm_arch_init_vcpu(CPUState *cs) if (!arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_EL1_32BIT; } - if (kvm_irqchip_in_kernel() && - kvm_check_extension(cs->kvm_state, KVM_CAP_ARM_PMU_V3)) { - cpu->has_pmu = true; - cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_PMU_V3; + /* enable PMU based on KVM mode, hw capability, and user setting */ + cpu->has_pmu &= kvm_irqchip_in_kernel() && + kvm_check_extension(cs->kvm_state, KVM_CAP_ARM_PMU_V3); + cpu->kvm_init_features[0] |= cpu->has_pmu << KVM_ARM_VCPU_PMU_V3; + if (cpu->has_pmu) { + cpu->kvm_init_features[0] |= cpu->has_pmu << KVM_ARM_VCPU_PMU_V3; + } else { + unset_feature(&env->features, ARM_FEATURE_PMU); } /* Do KVM_ARM_VCPU_INIT ioctl */