From patchwork Mon Mar 25 18:30:01 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Murray X-Patchwork-Id: 10869811 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9A77F139A for ; Mon, 25 Mar 2019 18:30:35 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 812E928CE3 for ; Mon, 25 Mar 2019 18:30:35 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7306F291EE; Mon, 25 Mar 2019 18:30:35 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 01BC228CE3 for ; Mon, 25 Mar 2019 18:30:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=efKLG14ufO1f3n75YcRkGNfabU7oI/UJ3XskOSwiIq4=; b=HjtogncKLEXOsM EmTVqpsf+XXgpILHNMQyzSg8JHh6Z19QsM0coEFOp+R9o4qllCg2FCKKHXQeygI4sZvT9q8iO+M+G HJshpNLzFjWjY6mlnJ8whcx1kyA0x8rSVxd4Bu+37YM/AWhwGlUf6ESQ5+TZh8X+VCJ0tcJ8j2/r3 mVn+ZIVOXFC30dbOx8uDEjlT8K/MXa5DMgjp0KIVtKndA5+DoClPmafnu3jO3XHyZkQ+QjkAYL+HY 6+n9EJSQwD16D3iSIxkOn448Gt75i/XYe8uoa7GVCxob/SQvlaO1slXHhpRH03Uk/wYxZcGOmp0Kt dk6bU9hmwIYnHFH7XbLg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1h8UMc-0004EM-MX; Mon, 25 Mar 2019 18:30:26 +0000 Received: from usa-sjc-mx-foss1.foss.arm.com ([217.140.101.70] helo=foss.arm.com) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1h8UMS-0004C1-NE for linux-arm-kernel@lists.infradead.org; Mon, 25 Mar 2019 18:30:23 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 0D39D15AB; Mon, 25 Mar 2019 11:30:15 -0700 (PDT) Received: from e119886-lin.cambridge.arm.com (unknown [10.37.6.20]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 9CA443F575; Mon, 25 Mar 2019 11:30:13 -0700 (PDT) From: Andrew Murray To: Christoffer Dall , Marc Zyngier Subject: [PATCH v4 1/6] KVM: arm/arm64: rename kvm_pmu_{enable/disable}_counter functions Date: Mon, 25 Mar 2019 18:30:01 +0000 Message-Id: <20190325183006.33115-2-andrew.murray@arm.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190325183006.33115-1-andrew.murray@arm.com> References: <20190325183006.33115-1-andrew.murray@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190325_113016_798761_D3B76036 X-CRM114-Status: GOOD ( 13.38 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Julien Thierry , kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org, Suzuki K Poulose Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP The kvm_pmu_{enable/disable}_counter functions can enabled/disable multiple counters at once as they operate on a bitmask. Let's make this clearer by renaming the function. Suggested-by: Suzuki K Poulose Signed-off-by: Andrew Murray Reviewed-by: Julien Thierry Reviewed-by: Suzuki K Poulose --- arch/arm64/kvm/sys_regs.c | 4 ++-- include/kvm/arm_pmu.h | 8 ++++---- virt/kvm/arm/pmu.c | 12 ++++++------ 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 539feecda5b8..980abfd35669 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -874,11 +874,11 @@ static bool access_pmcnten(struct kvm_vcpu *vcpu, struct sys_reg_params *p, if (r->Op2 & 0x1) { /* accessing PMCNTENSET_EL0 */ __vcpu_sys_reg(vcpu, PMCNTENSET_EL0) |= val; - kvm_pmu_enable_counter(vcpu, val); + kvm_pmu_enable_counter_mask(vcpu, val); } else { /* accessing PMCNTENCLR_EL0 */ __vcpu_sys_reg(vcpu, PMCNTENSET_EL0) &= ~val; - kvm_pmu_disable_counter(vcpu, val); + kvm_pmu_disable_counter_mask(vcpu, val); } } else { p->regval = __vcpu_sys_reg(vcpu, PMCNTENSET_EL0) & mask; diff --git a/include/kvm/arm_pmu.h b/include/kvm/arm_pmu.h index f87fe20fcb05..b73f31baca52 100644 --- a/include/kvm/arm_pmu.h +++ b/include/kvm/arm_pmu.h @@ -46,8 +46,8 @@ void kvm_pmu_set_counter_value(struct kvm_vcpu *vcpu, u64 select_idx, u64 val); u64 kvm_pmu_valid_counter_mask(struct kvm_vcpu *vcpu); void kvm_pmu_vcpu_reset(struct kvm_vcpu *vcpu); void kvm_pmu_vcpu_destroy(struct kvm_vcpu *vcpu); -void kvm_pmu_disable_counter(struct kvm_vcpu *vcpu, u64 val); -void kvm_pmu_enable_counter(struct kvm_vcpu *vcpu, u64 val); +void kvm_pmu_disable_counter_mask(struct kvm_vcpu *vcpu, u64 val); +void kvm_pmu_enable_counter_mask(struct kvm_vcpu *vcpu, u64 val); void kvm_pmu_flush_hwstate(struct kvm_vcpu *vcpu); void kvm_pmu_sync_hwstate(struct kvm_vcpu *vcpu); bool kvm_pmu_should_notify_user(struct kvm_vcpu *vcpu); @@ -83,8 +83,8 @@ static inline u64 kvm_pmu_valid_counter_mask(struct kvm_vcpu *vcpu) } static inline void kvm_pmu_vcpu_reset(struct kvm_vcpu *vcpu) {} static inline void kvm_pmu_vcpu_destroy(struct kvm_vcpu *vcpu) {} -static inline void kvm_pmu_disable_counter(struct kvm_vcpu *vcpu, u64 val) {} -static inline void kvm_pmu_enable_counter(struct kvm_vcpu *vcpu, u64 val) {} +static inline void kvm_pmu_disable_counter_mask(struct kvm_vcpu *vcpu, u64 val) {} +static inline void kvm_pmu_enable_counter_mask(struct kvm_vcpu *vcpu, u64 val) {} static inline void kvm_pmu_flush_hwstate(struct kvm_vcpu *vcpu) {} static inline void kvm_pmu_sync_hwstate(struct kvm_vcpu *vcpu) {} static inline bool kvm_pmu_should_notify_user(struct kvm_vcpu *vcpu) diff --git a/virt/kvm/arm/pmu.c b/virt/kvm/arm/pmu.c index 1c5b76c46e26..c5a722ad283f 100644 --- a/virt/kvm/arm/pmu.c +++ b/virt/kvm/arm/pmu.c @@ -135,13 +135,13 @@ u64 kvm_pmu_valid_counter_mask(struct kvm_vcpu *vcpu) } /** - * kvm_pmu_enable_counter - enable selected PMU counter + * kvm_pmu_enable_counter_mask - enable selected PMU counters * @vcpu: The vcpu pointer * @val: the value guest writes to PMCNTENSET register * * Call perf_event_enable to start counting the perf event */ -void kvm_pmu_enable_counter(struct kvm_vcpu *vcpu, u64 val) +void kvm_pmu_enable_counter_mask(struct kvm_vcpu *vcpu, u64 val) { int i; struct kvm_pmu *pmu = &vcpu->arch.pmu; @@ -164,13 +164,13 @@ void kvm_pmu_enable_counter(struct kvm_vcpu *vcpu, u64 val) } /** - * kvm_pmu_disable_counter - disable selected PMU counter + * kvm_pmu_disable_counter_mask - disable selected PMU counters * @vcpu: The vcpu pointer * @val: the value guest writes to PMCNTENCLR register * * Call perf_event_disable to stop counting the perf event */ -void kvm_pmu_disable_counter(struct kvm_vcpu *vcpu, u64 val) +void kvm_pmu_disable_counter_mask(struct kvm_vcpu *vcpu, u64 val) { int i; struct kvm_pmu *pmu = &vcpu->arch.pmu; @@ -347,10 +347,10 @@ void kvm_pmu_handle_pmcr(struct kvm_vcpu *vcpu, u64 val) mask = kvm_pmu_valid_counter_mask(vcpu); if (val & ARMV8_PMU_PMCR_E) { - kvm_pmu_enable_counter(vcpu, + kvm_pmu_enable_counter_mask(vcpu, __vcpu_sys_reg(vcpu, PMCNTENSET_EL0) & mask); } else { - kvm_pmu_disable_counter(vcpu, mask); + kvm_pmu_disable_counter_mask(vcpu, mask); } if (val & ARMV8_PMU_PMCR_C) From patchwork Mon Mar 25 18:30:02 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Murray X-Patchwork-Id: 10869817 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9B931139A for ; Mon, 25 Mar 2019 18:31:13 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 831E2291D8 for ; Mon, 25 Mar 2019 18:31:13 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 77B0E29216; Mon, 25 Mar 2019 18:31:13 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 2467B291D8 for ; Mon, 25 Mar 2019 18:31:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=4C/vYbqw6suDqp9OFXSgEz0Ad3O+SN6bSQPf0ezlpng=; b=eyBvWB21hi8sAO MCiqxqc1+3HWkUEMgpaNx+4MoyWyHc8CtLesgTI+IUujuHRNOYP5dWyNlRI1g2a7jU/ZBJNJzS9IU CzIVEE2u5epuGBrNZ1VKGb/CqU8dKNp1xZLCl/fExy+eTHfoSD0zMoJ0SvPHrZvujWupd/w4ZBT7h RFZi9TB6k4ANztUwQ3u8WzO/3H9AIgDLOHp3tLhAJ+29lVwbQnsrzsj/76dgVSAEyk0qqsGKmmrty wTtelPHzhToPByYs3KtvjJMiL92aEh6nL5EvEycBtIkf3VgXBhhrgXB2Ut0iW72e/rTH2EF23KK2u jRBFzF7SM4Ou8RWzB3Zg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1h8UNB-0004sJ-Je; Mon, 25 Mar 2019 18:31:01 +0000 Received: from usa-sjc-mx-foss1.foss.arm.com ([217.140.101.70] helo=foss.arm.com) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1h8UMT-0004Cv-4B for linux-arm-kernel@lists.infradead.org; Mon, 25 Mar 2019 18:30:26 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id BB6C215BE; Mon, 25 Mar 2019 11:30:16 -0700 (PDT) Received: from e119886-lin.cambridge.arm.com (unknown [10.37.6.20]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 567E83F575; Mon, 25 Mar 2019 11:30:15 -0700 (PDT) From: Andrew Murray To: Christoffer Dall , Marc Zyngier Subject: [PATCH v4 2/6] KVM: arm/arm64: extract duplicated code to own function Date: Mon, 25 Mar 2019 18:30:02 +0000 Message-Id: <20190325183006.33115-3-andrew.murray@arm.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190325183006.33115-1-andrew.murray@arm.com> References: <20190325183006.33115-1-andrew.murray@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190325_113017_170923_8E36421F X-CRM114-Status: GOOD ( 13.63 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Julien Thierry , kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org, Suzuki K Poulose Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Let's reduce code duplication by extracting common code to its own function. Signed-off-by: Andrew Murray Reviewed-by: Suzuki K Poulose --- virt/kvm/arm/pmu.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/virt/kvm/arm/pmu.c b/virt/kvm/arm/pmu.c index c5a722ad283f..6e7c179103a6 100644 --- a/virt/kvm/arm/pmu.c +++ b/virt/kvm/arm/pmu.c @@ -64,6 +64,19 @@ void kvm_pmu_set_counter_value(struct kvm_vcpu *vcpu, u64 select_idx, u64 val) __vcpu_sys_reg(vcpu, reg) += (s64)val - kvm_pmu_get_counter_value(vcpu, select_idx); } +/** + * kvm_pmu_release_perf_event - remove the perf event + * @pmc: The PMU counter pointer + */ +static void kvm_pmu_release_perf_event(struct kvm_pmc *pmc) +{ + if (pmc->perf_event) { + perf_event_disable(pmc->perf_event); + perf_event_release_kernel(pmc->perf_event); + pmc->perf_event = NULL; + } +} + /** * kvm_pmu_stop_counter - stop PMU counter * @pmc: The PMU counter pointer @@ -79,9 +92,7 @@ static void kvm_pmu_stop_counter(struct kvm_vcpu *vcpu, struct kvm_pmc *pmc) reg = (pmc->idx == ARMV8_PMU_CYCLE_IDX) ? PMCCNTR_EL0 : PMEVCNTR0_EL0 + pmc->idx; __vcpu_sys_reg(vcpu, reg) = counter; - perf_event_disable(pmc->perf_event); - perf_event_release_kernel(pmc->perf_event); - pmc->perf_event = NULL; + kvm_pmu_release_perf_event(pmc); } } @@ -112,15 +123,8 @@ void kvm_pmu_vcpu_destroy(struct kvm_vcpu *vcpu) int i; struct kvm_pmu *pmu = &vcpu->arch.pmu; - for (i = 0; i < ARMV8_PMU_MAX_COUNTERS; i++) { - struct kvm_pmc *pmc = &pmu->pmc[i]; - - if (pmc->perf_event) { - perf_event_disable(pmc->perf_event); - perf_event_release_kernel(pmc->perf_event); - pmc->perf_event = NULL; - } - } + for (i = 0; i < ARMV8_PMU_MAX_COUNTERS; i++) + kvm_pmu_release_perf_event(&pmu->pmc[i]); } u64 kvm_pmu_valid_counter_mask(struct kvm_vcpu *vcpu) From patchwork Mon Mar 25 18:30:03 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Murray X-Patchwork-Id: 10869819 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 39F11139A for ; Mon, 25 Mar 2019 18:31:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2275828CE3 for ; Mon, 25 Mar 2019 18:31:18 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 16D47291EE; Mon, 25 Mar 2019 18:31:18 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 9B6BB28CE3 for ; Mon, 25 Mar 2019 18:31:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=4SlLuZiLWZc5SQWEp7I8aLL550/Gfwy8yqBThfkTzi4=; b=juorIx00YLCUXq waXmIFerxu9D2/zn/sRaFqdOzBSXB+TzVZFIfmBC+nZQDZoV3i67At0fko8xX/8pojMcSXrw6q00W WVjtW7dS95XohNMdYqVrGq72Cd54qcrDfPO7/smKZLwiTxCWqmJbbPzK6BB0ZmTSc4VyGgjHwEbnA 08MFwdIEhaHvRps2g1awkyU820GCry+AQ+/nNixw155zyFmOXH6tUeGn4pbnHlYpl4j2qKy2Kj2aV ueCMI5NDnMM04AHrlYDEcoOA6KPHYcTruJt47a3ivbJGATO34pKZQI8/s6yuYYeot74s7vuWWXqQU 8g9iUqIKCnd2JN6er83Q==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1h8UNM-00057D-Lr; Mon, 25 Mar 2019 18:31:12 +0000 Received: from usa-sjc-mx-foss1.foss.arm.com ([217.140.101.70] helo=foss.arm.com) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1h8UMU-0004DE-VJ for linux-arm-kernel@lists.infradead.org; Mon, 25 Mar 2019 18:30:26 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 9F20C169E; Mon, 25 Mar 2019 11:30:18 -0700 (PDT) Received: from e119886-lin.cambridge.arm.com (unknown [10.37.6.20]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 10EE83F575; Mon, 25 Mar 2019 11:30:16 -0700 (PDT) From: Andrew Murray To: Christoffer Dall , Marc Zyngier Subject: [PATCH v4 3/6] KVM: arm/arm64: re-create event when setting counter value Date: Mon, 25 Mar 2019 18:30:03 +0000 Message-Id: <20190325183006.33115-4-andrew.murray@arm.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190325183006.33115-1-andrew.murray@arm.com> References: <20190325183006.33115-1-andrew.murray@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190325_113019_014267_CBAF6966 X-CRM114-Status: GOOD ( 15.64 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Suzuki K Poulose , Julien Thierry , kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org, Suzuki K Poulose Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP The perf event sample_period is currently set based upon the current counter value, when PMXEVTYPER is written to and the perf event is created. However the user may choose to write the type before the counter value in which case sample_period will be set incorrectly. Let's instead decouple event creation from PMXEVTYPER and (re)create the event in either suitation. Signed-off-by: Andrew Murray Reviewed-by: Julien Thierry Reviewed-by: Suzuki K Poulose --- virt/kvm/arm/pmu.c | 42 +++++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/virt/kvm/arm/pmu.c b/virt/kvm/arm/pmu.c index 6e7c179103a6..ae1e886d4a1a 100644 --- a/virt/kvm/arm/pmu.c +++ b/virt/kvm/arm/pmu.c @@ -24,6 +24,7 @@ #include #include +static void kvm_pmu_create_perf_event(struct kvm_vcpu *vcpu, u64 select_idx); /** * kvm_pmu_get_counter_value - get PMU counter value * @vcpu: The vcpu pointer @@ -62,6 +63,9 @@ void kvm_pmu_set_counter_value(struct kvm_vcpu *vcpu, u64 select_idx, u64 val) reg = (select_idx == ARMV8_PMU_CYCLE_IDX) ? PMCCNTR_EL0 : PMEVCNTR0_EL0 + select_idx; __vcpu_sys_reg(vcpu, reg) += (s64)val - kvm_pmu_get_counter_value(vcpu, select_idx); + + /* Recreate the perf event to reflect the updated sample_period */ + kvm_pmu_create_perf_event(vcpu, select_idx); } /** @@ -378,23 +382,21 @@ static bool kvm_pmu_counter_is_enabled(struct kvm_vcpu *vcpu, u64 select_idx) } /** - * kvm_pmu_set_counter_event_type - set selected counter to monitor some event + * kvm_pmu_create_perf_event - create a perf event for a counter * @vcpu: The vcpu pointer - * @data: The data guest writes to PMXEVTYPER_EL0 * @select_idx: The number of selected counter - * - * When OS accesses PMXEVTYPER_EL0, that means it wants to set a PMC to count an - * event with given hardware event number. Here we call perf_event API to - * emulate this action and create a kernel perf event for it. */ -void kvm_pmu_set_counter_event_type(struct kvm_vcpu *vcpu, u64 data, - u64 select_idx) +static void kvm_pmu_create_perf_event(struct kvm_vcpu *vcpu, u64 select_idx) { struct kvm_pmu *pmu = &vcpu->arch.pmu; struct kvm_pmc *pmc = &pmu->pmc[select_idx]; struct perf_event *event; struct perf_event_attr attr; - u64 eventsel, counter; + u64 eventsel, counter, reg, data; + + reg = (select_idx == ARMV8_PMU_CYCLE_IDX) + ? PMCCFILTR_EL0 : PMEVTYPER0_EL0 + select_idx; + data = __vcpu_sys_reg(vcpu, reg); kvm_pmu_stop_counter(vcpu, pmc); eventsel = data & ARMV8_PMU_EVTYPE_EVENT; @@ -431,6 +433,28 @@ void kvm_pmu_set_counter_event_type(struct kvm_vcpu *vcpu, u64 data, pmc->perf_event = event; } +/** + * kvm_pmu_set_counter_event_type - set selected counter to monitor some event + * @vcpu: The vcpu pointer + * @data: The data guest writes to PMXEVTYPER_EL0 + * @select_idx: The number of selected counter + * + * When OS accesses PMXEVTYPER_EL0, that means it wants to set a PMC to count an + * event with given hardware event number. Here we call perf_event API to + * emulate this action and create a kernel perf event for it. + */ +void kvm_pmu_set_counter_event_type(struct kvm_vcpu *vcpu, u64 data, + u64 select_idx) +{ + u64 reg, event_type = data & ARMV8_PMU_EVTYPE_MASK; + + reg = (select_idx == ARMV8_PMU_CYCLE_IDX) + ? PMCCFILTR_EL0 : PMEVTYPER0_EL0 + select_idx; + + __vcpu_sys_reg(vcpu, reg) = event_type; + kvm_pmu_create_perf_event(vcpu, select_idx); +} + bool kvm_arm_support_pmu_v3(void) { /* From patchwork Mon Mar 25 18:30:04 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Murray X-Patchwork-Id: 10869815 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A23C517E0 for ; Mon, 25 Mar 2019 18:30:54 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8A01E28CE3 for ; Mon, 25 Mar 2019 18:30:54 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7E7C5291EE; Mon, 25 Mar 2019 18:30:54 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 30D2728CE3 for ; Mon, 25 Mar 2019 18:30:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=24mwZphKRWIym1ArudL5G1zwtl+bdKR7/pMAFRe6fNw=; b=D3m+RCeS41mCaq EdOfdj1whCUTU+WhEyiLQknMcE5SlHcspF983gLEZLXogyMMXmSG+PSY/wblIG3HF/mQk83WCywrG YNUCEKr3x+48l1X4xMfS3P6W0kWVHYMFHIhtGKVzOO6f522zy1qjsnJOkHOWzjHbDIdC4XERI4ccO Ea7goUAlpr3lqy+1SOJC+MagS0rQ3bxAjZUCtFl3fcQqGcriHgvs0bJWVozFTmfEWVwvB5VbsEtjN J7PBVvSuW25BTe+oo2TGfEY7AZbsKzFCU8Lq9UwsGlbvFERlDtWYHTf4UtFP3HxsDhql84E/tHlJ6 adO4udAdnesqD9HUSAwA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1h8UN3-0004iZ-5n; Mon, 25 Mar 2019 18:30:53 +0000 Received: from foss.arm.com ([217.140.101.70]) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1h8UMY-0004DZ-N4 for linux-arm-kernel@lists.infradead.org; Mon, 25 Mar 2019 18:30:26 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 5917C168F; Mon, 25 Mar 2019 11:30:20 -0700 (PDT) Received: from e119886-lin.cambridge.arm.com (unknown [10.37.6.20]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id E8B443F575; Mon, 25 Mar 2019 11:30:18 -0700 (PDT) From: Andrew Murray To: Christoffer Dall , Marc Zyngier Subject: [PATCH v4 4/6] arm64: perf: extract chain helper into header Date: Mon, 25 Mar 2019 18:30:04 +0000 Message-Id: <20190325183006.33115-5-andrew.murray@arm.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190325183006.33115-1-andrew.murray@arm.com> References: <20190325183006.33115-1-andrew.murray@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190325_113022_758342_43E81B76 X-CRM114-Status: GOOD ( 11.56 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Julien Thierry , kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org, Suzuki K Poulose Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP The ARMv8 Performance Monitors Extension includes an architectural event type named CHAIN which allows for chaining counters together. Let's extract the test for this event into a header file such that other users, such as KVM (for PMU emulation) can make use of. Signed-off-by: Andrew Murray --- arch/arm64/include/asm/perf_event.h | 5 +++++ arch/arm64/kernel/perf_event.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/perf_event.h b/arch/arm64/include/asm/perf_event.h index c593761ba61c..cd13f3fd1055 100644 --- a/arch/arm64/include/asm/perf_event.h +++ b/arch/arm64/include/asm/perf_event.h @@ -219,6 +219,11 @@ #define ARMV8_PMU_USERENR_CR (1 << 2) /* Cycle counter can be read at EL0 */ #define ARMV8_PMU_USERENR_ER (1 << 3) /* Event counter can be read at EL0 */ +static inline bool armv8pmu_evtype_is_chain(u64 evtype) +{ + return (evtype == ARMV8_PMUV3_PERFCTR_CHAIN); +} + #ifdef CONFIG_PERF_EVENTS struct pt_regs; extern unsigned long perf_instruction_pointer(struct pt_regs *regs); diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c index 4addb38bc250..279f93af19a1 100644 --- a/arch/arm64/kernel/perf_event.c +++ b/arch/arm64/kernel/perf_event.c @@ -850,7 +850,7 @@ static int armv8pmu_set_event_filter(struct hw_perf_event *event, static int armv8pmu_filter_match(struct perf_event *event) { unsigned long evtype = event->hw.config_base & ARMV8_PMU_EVTYPE_EVENT; - return evtype != ARMV8_PMUV3_PERFCTR_CHAIN; + return !armv8pmu_evtype_is_chain(evtype); } static void armv8pmu_reset(void *info) From patchwork Mon Mar 25 18:30:05 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Murray X-Patchwork-Id: 10869835 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B9C7B14DE for ; Mon, 25 Mar 2019 18:36:56 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9D78929216 for ; Mon, 25 Mar 2019 18:36:56 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8D2DC29257; Mon, 25 Mar 2019 18:36:56 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id F162229216 for ; Mon, 25 Mar 2019 18:36:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=KnDZtBBfUXjABA6Hz/BXbtoSmZtFcsKFr1lKx9VRNwQ=; b=DPNkhROkbI8qox CPkq82d5Bz5IuHBY4T2UkrR52SyG0Do8f918RjO/dKRlo3DATPeiheUX7eTijw+zvAV4r5WvDOcSK 6rr/5ih/9rDz9Mh9Z1hLjdLkiGQF7NDUeXQcweRQOzCkw9+tsSQ2VTyM75Ak6GRGotZ1KhZtcjT9l gtBu4jl1CWTWk6Pv8E9fg25W8DCZFFz53cNOwc9SmKPktoBwvj9VHlVZ0zjN0+IO0QgqAtJlInKbG mLu1xw2XX+Utr+gW3wNRPBXx5G3tkEWbnlXL1nGhDBEPiqPAHicMYdtkFZLC2goN3aWV2PNbdzfp5 NZctUgKAr/pR/3vJ4vZQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1h8USr-0002NV-Rp; Mon, 25 Mar 2019 18:36:53 +0000 Received: from usa-sjc-mx-foss1.foss.arm.com ([217.140.101.70] helo=foss.arm.com) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1h8UMc-0004EC-RF for linux-arm-kernel@lists.infradead.org; Mon, 25 Mar 2019 18:30:29 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 3DE3A174E; Mon, 25 Mar 2019 11:30:22 -0700 (PDT) Received: from e119886-lin.cambridge.arm.com (unknown [10.37.6.20]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id A2B2B3F575; Mon, 25 Mar 2019 11:30:20 -0700 (PDT) From: Andrew Murray To: Christoffer Dall , Marc Zyngier Subject: [PATCH v4 5/6] KVM: arm/arm64: represent paired counters with kvm_pmc_pair Date: Mon, 25 Mar 2019 18:30:05 +0000 Message-Id: <20190325183006.33115-6-andrew.murray@arm.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190325183006.33115-1-andrew.murray@arm.com> References: <20190325183006.33115-1-andrew.murray@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190325_113026_940523_AE4E0441 X-CRM114-Status: GOOD ( 15.01 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Julien Thierry , kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org, Suzuki K Poulose Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP The CHAIN PMU event implicitly creates a relationship between a pair of adjacent counters, this is due to the high counter counting overflows occurring in the low counter. To facilitate emulation of chained counters let's represent this relationship via a struct kvm_pmc_pair that holds a pair of counters. Signed-off-by: Andrew Murray --- include/kvm/arm_pmu.h | 13 +++++++- virt/kvm/arm/pmu.c | 78 ++++++++++++++++++++++++++++++++----------- 2 files changed, 71 insertions(+), 20 deletions(-) diff --git a/include/kvm/arm_pmu.h b/include/kvm/arm_pmu.h index b73f31baca52..ee80dc8db990 100644 --- a/include/kvm/arm_pmu.h +++ b/include/kvm/arm_pmu.h @@ -22,6 +22,7 @@ #include #define ARMV8_PMU_CYCLE_IDX (ARMV8_PMU_MAX_COUNTERS - 1) +#define ARMV8_PMU_MAX_COUNTER_PAIRS ((ARMV8_PMU_MAX_COUNTERS + 1) >> 1) #ifdef CONFIG_KVM_ARM_PMU @@ -31,9 +32,19 @@ struct kvm_pmc { u64 bitmask; }; +enum kvm_pmc_type { + KVM_PMC_TYPE_PAIR, +}; + +struct kvm_pmc_pair { + struct kvm_pmc low; + struct kvm_pmc high; + enum kvm_pmc_type type; +}; + struct kvm_pmu { int irq_num; - struct kvm_pmc pmc[ARMV8_PMU_MAX_COUNTERS]; + struct kvm_pmc_pair pmc_pair[ARMV8_PMU_MAX_COUNTER_PAIRS]; bool ready; bool created; bool irq_level; diff --git a/virt/kvm/arm/pmu.c b/virt/kvm/arm/pmu.c index ae1e886d4a1a..08acd60c538a 100644 --- a/virt/kvm/arm/pmu.c +++ b/virt/kvm/arm/pmu.c @@ -25,6 +25,43 @@ #include static void kvm_pmu_create_perf_event(struct kvm_vcpu *vcpu, u64 select_idx); + +/** + * kvm_pmu_pair_is_high_counter - determine if select_idx is a high/low counter + * @select_idx: The counter index + */ +static bool kvm_pmu_pair_is_high_counter(u64 select_idx) +{ + return select_idx & 0x1; +} + +/** + * kvm_pmu_get_kvm_pmc_pair - obtain a pmc_pair from a pmc + * @pmc: The PMU counter pointer + */ +static struct kvm_pmc_pair *kvm_pmu_get_kvm_pmc_pair(struct kvm_pmc *pmc) +{ + if (kvm_pmu_pair_is_high_counter(pmc->idx)) + return container_of(pmc, struct kvm_pmc_pair, high); + else + return container_of(pmc, struct kvm_pmc_pair, low); +} + +/** + * kvm_pmu_get_kvm_pmc - obtain a pmc based on select_idx + * @vcpu: The vcpu pointer + * @select_idx: The counter index + */ +static struct kvm_pmc *kvm_pmu_get_kvm_pmc(struct kvm_vcpu *vcpu, + u64 select_idx) +{ + struct kvm_pmu *pmu = &vcpu->arch.pmu; + struct kvm_pmc_pair *pmc_pair = &pmu->pmc_pair[select_idx >> 1]; + + return kvm_pmu_pair_is_high_counter(select_idx) ? &pmc_pair->high + : &pmc_pair->low; +} + /** * kvm_pmu_get_counter_value - get PMU counter value * @vcpu: The vcpu pointer @@ -33,8 +70,7 @@ static void kvm_pmu_create_perf_event(struct kvm_vcpu *vcpu, u64 select_idx); u64 kvm_pmu_get_counter_value(struct kvm_vcpu *vcpu, u64 select_idx) { u64 counter, reg, enabled, running; - struct kvm_pmu *pmu = &vcpu->arch.pmu; - struct kvm_pmc *pmc = &pmu->pmc[select_idx]; + struct kvm_pmc *pmc = kvm_pmu_get_kvm_pmc(vcpu, select_idx); reg = (select_idx == ARMV8_PMU_CYCLE_IDX) ? PMCCNTR_EL0 : PMEVCNTR0_EL0 + select_idx; @@ -108,12 +144,17 @@ static void kvm_pmu_stop_counter(struct kvm_vcpu *vcpu, struct kvm_pmc *pmc) void kvm_pmu_vcpu_reset(struct kvm_vcpu *vcpu) { int i; - struct kvm_pmu *pmu = &vcpu->arch.pmu; + struct kvm_pmc *pmc; + struct kvm_pmc_pair *pmc_pair; for (i = 0; i < ARMV8_PMU_MAX_COUNTERS; i++) { - kvm_pmu_stop_counter(vcpu, &pmu->pmc[i]); - pmu->pmc[i].idx = i; - pmu->pmc[i].bitmask = 0xffffffffUL; + pmc = kvm_pmu_get_kvm_pmc(vcpu, i); + kvm_pmu_stop_counter(vcpu, pmc); + pmc->idx = i; + pmc->bitmask = 0xffffffffUL; + + pmc_pair = kvm_pmu_get_kvm_pmc_pair(pmc); + pmc_pair->type = KVM_PMC_TYPE_PAIR; } } @@ -125,10 +166,12 @@ void kvm_pmu_vcpu_reset(struct kvm_vcpu *vcpu) void kvm_pmu_vcpu_destroy(struct kvm_vcpu *vcpu) { int i; - struct kvm_pmu *pmu = &vcpu->arch.pmu; + struct kvm_pmc *pmc; - for (i = 0; i < ARMV8_PMU_MAX_COUNTERS; i++) - kvm_pmu_release_perf_event(&pmu->pmc[i]); + for (i = 0; i < ARMV8_PMU_MAX_COUNTERS; i++) { + pmc = kvm_pmu_get_kvm_pmc(vcpu, i); + kvm_pmu_release_perf_event(pmc); + } } u64 kvm_pmu_valid_counter_mask(struct kvm_vcpu *vcpu) @@ -152,7 +195,6 @@ u64 kvm_pmu_valid_counter_mask(struct kvm_vcpu *vcpu) void kvm_pmu_enable_counter_mask(struct kvm_vcpu *vcpu, u64 val) { int i; - struct kvm_pmu *pmu = &vcpu->arch.pmu; struct kvm_pmc *pmc; if (!(__vcpu_sys_reg(vcpu, PMCR_EL0) & ARMV8_PMU_PMCR_E) || !val) @@ -162,7 +204,7 @@ void kvm_pmu_enable_counter_mask(struct kvm_vcpu *vcpu, u64 val) if (!(val & BIT(i))) continue; - pmc = &pmu->pmc[i]; + pmc = kvm_pmu_get_kvm_pmc(vcpu, i); if (pmc->perf_event) { perf_event_enable(pmc->perf_event); if (pmc->perf_event->state != PERF_EVENT_STATE_ACTIVE) @@ -181,7 +223,6 @@ void kvm_pmu_enable_counter_mask(struct kvm_vcpu *vcpu, u64 val) void kvm_pmu_disable_counter_mask(struct kvm_vcpu *vcpu, u64 val) { int i; - struct kvm_pmu *pmu = &vcpu->arch.pmu; struct kvm_pmc *pmc; if (!val) @@ -191,7 +232,7 @@ void kvm_pmu_disable_counter_mask(struct kvm_vcpu *vcpu, u64 val) if (!(val & BIT(i))) continue; - pmc = &pmu->pmc[i]; + pmc = kvm_pmu_get_kvm_pmc(vcpu, i); if (pmc->perf_event) perf_event_disable(pmc->perf_event); } @@ -285,9 +326,10 @@ static inline struct kvm_vcpu *kvm_pmc_to_vcpu(struct kvm_pmc *pmc) { struct kvm_pmu *pmu; struct kvm_vcpu_arch *vcpu_arch; + struct kvm_pmc_pair *pair = kvm_pmu_get_kvm_pmc_pair(pmc); - pmc -= pmc->idx; - pmu = container_of(pmc, struct kvm_pmu, pmc[0]); + pair -= (pmc->idx >> 1); + pmu = container_of(pair, struct kvm_pmu, pmc_pair[0]); vcpu_arch = container_of(pmu, struct kvm_vcpu_arch, pmu); return container_of(vcpu_arch, struct kvm_vcpu, arch); } @@ -348,7 +390,6 @@ void kvm_pmu_software_increment(struct kvm_vcpu *vcpu, u64 val) */ void kvm_pmu_handle_pmcr(struct kvm_vcpu *vcpu, u64 val) { - struct kvm_pmu *pmu = &vcpu->arch.pmu; struct kvm_pmc *pmc; u64 mask; int i; @@ -370,7 +411,7 @@ void kvm_pmu_handle_pmcr(struct kvm_vcpu *vcpu, u64 val) } if (val & ARMV8_PMU_PMCR_LC) { - pmc = &pmu->pmc[ARMV8_PMU_CYCLE_IDX]; + pmc = kvm_pmu_get_kvm_pmc(vcpu, ARMV8_PMU_CYCLE_IDX); pmc->bitmask = 0xffffffffffffffffUL; } } @@ -388,8 +429,7 @@ static bool kvm_pmu_counter_is_enabled(struct kvm_vcpu *vcpu, u64 select_idx) */ static void kvm_pmu_create_perf_event(struct kvm_vcpu *vcpu, u64 select_idx) { - struct kvm_pmu *pmu = &vcpu->arch.pmu; - struct kvm_pmc *pmc = &pmu->pmc[select_idx]; + struct kvm_pmc *pmc = kvm_pmu_get_kvm_pmc(vcpu, select_idx); struct perf_event *event; struct perf_event_attr attr; u64 eventsel, counter, reg, data; From patchwork Mon Mar 25 18:30:06 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Murray X-Patchwork-Id: 10869821 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5BEFE17E0 for ; Mon, 25 Mar 2019 18:31:34 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 41EED291D8 for ; Mon, 25 Mar 2019 18:31:34 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 33BC728CE3; Mon, 25 Mar 2019 18:31:34 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 34C2628CE3 for ; Mon, 25 Mar 2019 18:31:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=ggD0bDgxnaqN+IHqCWwOASC9uHUYrEIj4/mxEClimvA=; b=qtUd5QxSCNUGBf TdTPZxzJ6tYXlue7cDTTZlQhvgKoztZULB60gRodKdKYG/z3PZtg0IqEUiuSS3vBxmqHq/qebq/5V xOSGsw00cax9D0AvA4EB2U/DLJUYmPfQRrpC0a2zlb1abjLBh52YejVzngBWq7tlS6ao59dCqjVW7 tmU4kFEgCcn2Ww3+247Qjf5lAGhzIbsmHKUUBxOOg4PsxbOdYUWcL+qxGF0Eguon5K43qj8ZL6xFB LJTqyRnMD9P4U+6M4owP3rWSPoGEny2Dvcu8cZuwqsu+qDWlZjQmdwFxzMTCF9cTbNrvAl4ZCGXFu wKMW9/TXAOdJwkMFk92A==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1h8UNc-0005Tx-FC; Mon, 25 Mar 2019 18:31:28 +0000 Received: from foss.arm.com ([217.140.101.70]) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1h8UMc-0004ED-RE for linux-arm-kernel@lists.infradead.org; Mon, 25 Mar 2019 18:30:32 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 224A11993; Mon, 25 Mar 2019 11:30:24 -0700 (PDT) Received: from e119886-lin.cambridge.arm.com (unknown [10.37.6.20]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 874BD3F575; Mon, 25 Mar 2019 11:30:22 -0700 (PDT) From: Andrew Murray To: Christoffer Dall , Marc Zyngier Subject: [PATCH v4 6/6] KVM: arm/arm64: support chained PMU counters Date: Mon, 25 Mar 2019 18:30:06 +0000 Message-Id: <20190325183006.33115-7-andrew.murray@arm.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190325183006.33115-1-andrew.murray@arm.com> References: <20190325183006.33115-1-andrew.murray@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190325_113026_951506_98602B03 X-CRM114-Status: GOOD ( 19.06 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Julien Thierry , kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org, Suzuki K Poulose Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Emulate chained PMU counters by creating a single 64 bit event counter for a pair of chained KVM counters. Please note that overflow interrupts are only supported on the high counter of a chained counter pair. Signed-off-by: Andrew Murray --- include/kvm/arm_pmu.h | 2 + virt/kvm/arm/pmu.c | 256 +++++++++++++++++++++++++++++++++++++----- 2 files changed, 231 insertions(+), 27 deletions(-) diff --git a/include/kvm/arm_pmu.h b/include/kvm/arm_pmu.h index ee80dc8db990..ce5f380a6699 100644 --- a/include/kvm/arm_pmu.h +++ b/include/kvm/arm_pmu.h @@ -34,12 +34,14 @@ struct kvm_pmc { enum kvm_pmc_type { KVM_PMC_TYPE_PAIR, + KVM_PMC_TYPE_CHAIN, }; struct kvm_pmc_pair { struct kvm_pmc low; struct kvm_pmc high; enum kvm_pmc_type type; + struct perf_event *chain_event; }; struct kvm_pmu { diff --git a/virt/kvm/arm/pmu.c b/virt/kvm/arm/pmu.c index 08acd60c538a..3a0f1e66c759 100644 --- a/virt/kvm/arm/pmu.c +++ b/virt/kvm/arm/pmu.c @@ -26,6 +26,8 @@ static void kvm_pmu_create_perf_event(struct kvm_vcpu *vcpu, u64 select_idx); +#define PERF_ATTR_CFG1_KVM_PMU_CHAINED 0x1 + /** * kvm_pmu_pair_is_high_counter - determine if select_idx is a high/low counter * @select_idx: The counter index @@ -62,6 +64,113 @@ static struct kvm_pmc *kvm_pmu_get_kvm_pmc(struct kvm_vcpu *vcpu, : &pmc_pair->low; } +/** + * kvm_pmu_pair_is_chained - determine if the pair is a chain + * @pmc: The PMU counter pointer + */ +static bool kvm_pmu_pair_is_chained(struct kvm_pmc *pmc) +{ + struct kvm_pmc_pair *pmc_pair = kvm_pmu_get_kvm_pmc_pair(pmc); + + return (pmc_pair->type == KVM_PMC_TYPE_CHAIN); +} + +/** + * kvm_pmu_event_is_chained - determine if the event type is chain + * @vcpu: The vcpu pointer + * @select_idx: The counter index + */ +static bool kvm_pmu_event_is_chained(struct kvm_vcpu *vcpu, u64 select_idx) +{ + u64 eventsel, reg; + + select_idx |= 0x1; + + if (select_idx == ARMV8_PMU_CYCLE_IDX) + return false; + + reg = PMEVTYPER0_EL0 + select_idx; + eventsel = __vcpu_sys_reg(vcpu, reg) & ARMV8_PMU_EVTYPE_EVENT; + + return armv8pmu_evtype_is_chain(eventsel); +} + +/** + * kvm_pmu_get_perf_event - obtain a perf event from a pmc + * @pmc: The PMU counter pointer + * + * If we are handling the pmc pair as a chained pair then we return the + * chained event instead of the individual pmc event + */ +static struct perf_event *kvm_pmu_get_perf_event(struct kvm_pmc *pmc) +{ + struct kvm_pmc_pair *pmc_pair = kvm_pmu_get_kvm_pmc_pair(pmc); + + if (kvm_pmu_pair_is_chained(pmc)) + return pmc_pair->chain_event; + + return pmc->perf_event; +} + +/** + * kvm_pmu_set_perf_event - set a perf event to a pmc + * @pmc: The PMU counter pointer + * @perf_event: The perf event + * + * If we are handling the pmc pair as a chained pair then we set the + * chained event instead of the individual pmc event + */ +static void kvm_pmu_set_perf_event(struct kvm_pmc *pmc, + struct perf_event *perf_event) +{ + struct kvm_pmc_pair *pmc_pair = kvm_pmu_get_kvm_pmc_pair(pmc); + + if (kvm_pmu_pair_is_chained(pmc)) + pmc_pair->chain_event = perf_event; + else + pmc->perf_event = perf_event; +} + +/** + * kvm_pmu_get_pair_counter_value - get PMU counter value + * @vcpu: The vcpu pointer + * @pmc: The PMU counter pointer + */ +static u64 kvm_pmu_get_pair_counter_value(struct kvm_vcpu *vcpu, + struct kvm_pmc *pmc) +{ + u64 counter, counter_high, reg, enabled, running; + struct perf_event *perf_event = kvm_pmu_get_perf_event(pmc); + struct kvm_pmc_pair *pmc_pair = kvm_pmu_get_kvm_pmc_pair(pmc); + + if (kvm_pmu_pair_is_chained(pmc)) { + reg = PMEVCNTR0_EL0 + pmc_pair->low.idx; + counter = __vcpu_sys_reg(vcpu, reg); + + reg = PMEVCNTR0_EL0 + pmc_pair->high.idx; + counter_high = __vcpu_sys_reg(vcpu, reg); + + counter = lower_32_bits(counter) | (counter_high << 32); + } else { + reg = (pmc->idx == ARMV8_PMU_CYCLE_IDX) + ? PMCCNTR_EL0 : PMEVCNTR0_EL0 + pmc->idx; + counter = __vcpu_sys_reg(vcpu, reg); + } + + /* + * The real counter value is equal to the value of counter register plus + * the value perf event counts. + */ + if (perf_event) + counter += perf_event_read_value(perf_event, &enabled, + &running); + + if (!kvm_pmu_pair_is_chained(pmc)) + counter &= pmc->bitmask; + + return counter; +} + /** * kvm_pmu_get_counter_value - get PMU counter value * @vcpu: The vcpu pointer @@ -69,19 +178,14 @@ static struct kvm_pmc *kvm_pmu_get_kvm_pmc(struct kvm_vcpu *vcpu, */ u64 kvm_pmu_get_counter_value(struct kvm_vcpu *vcpu, u64 select_idx) { - u64 counter, reg, enabled, running; + u64 counter; struct kvm_pmc *pmc = kvm_pmu_get_kvm_pmc(vcpu, select_idx); - reg = (select_idx == ARMV8_PMU_CYCLE_IDX) - ? PMCCNTR_EL0 : PMEVCNTR0_EL0 + select_idx; - counter = __vcpu_sys_reg(vcpu, reg); + counter = kvm_pmu_get_pair_counter_value(vcpu, pmc); - /* The real counter value is equal to the value of counter register plus - * the value perf event counts. - */ - if (pmc->perf_event) - counter += perf_event_read_value(pmc->perf_event, &enabled, - &running); + if (kvm_pmu_pair_is_chained(pmc) && + kvm_pmu_pair_is_high_counter(select_idx)) + counter >>= 32; return counter & pmc->bitmask; } @@ -110,10 +214,12 @@ void kvm_pmu_set_counter_value(struct kvm_vcpu *vcpu, u64 select_idx, u64 val) */ static void kvm_pmu_release_perf_event(struct kvm_pmc *pmc) { - if (pmc->perf_event) { - perf_event_disable(pmc->perf_event); - perf_event_release_kernel(pmc->perf_event); - pmc->perf_event = NULL; + struct perf_event *perf_event = kvm_pmu_get_perf_event(pmc); + + if (perf_event) { + perf_event_disable(perf_event); + perf_event_release_kernel(perf_event); + kvm_pmu_set_perf_event(pmc, NULL); } } @@ -125,15 +231,32 @@ static void kvm_pmu_release_perf_event(struct kvm_pmc *pmc) */ static void kvm_pmu_stop_counter(struct kvm_vcpu *vcpu, struct kvm_pmc *pmc) { - u64 counter, reg; + u64 counter, counter_low, counter_high, reg; + struct perf_event *perf_event = kvm_pmu_get_perf_event(pmc); + struct kvm_pmc_pair *pmc_pair = kvm_pmu_get_kvm_pmc_pair(pmc); + + if (!perf_event) + return; - if (pmc->perf_event) { + if (kvm_pmu_pair_is_chained(pmc)) { + counter_low = kvm_pmu_get_counter_value( + vcpu, pmc_pair->low.idx); + counter_high = kvm_pmu_get_counter_value( + vcpu, pmc_pair->high.idx); + + reg = PMEVCNTR0_EL0 + pmc_pair->low.idx; + __vcpu_sys_reg(vcpu, reg) = counter_low; + + reg = PMEVCNTR0_EL0 + pmc_pair->high.idx; + __vcpu_sys_reg(vcpu, reg) = counter_high; + } else { counter = kvm_pmu_get_counter_value(vcpu, pmc->idx); reg = (pmc->idx == ARMV8_PMU_CYCLE_IDX) ? PMCCNTR_EL0 : PMEVCNTR0_EL0 + pmc->idx; __vcpu_sys_reg(vcpu, reg) = counter; - kvm_pmu_release_perf_event(pmc); } + + kvm_pmu_release_perf_event(pmc); } /** @@ -196,6 +319,7 @@ void kvm_pmu_enable_counter_mask(struct kvm_vcpu *vcpu, u64 val) { int i; struct kvm_pmc *pmc; + struct perf_event *perf_event; if (!(__vcpu_sys_reg(vcpu, PMCR_EL0) & ARMV8_PMU_PMCR_E) || !val) return; @@ -205,9 +329,21 @@ void kvm_pmu_enable_counter_mask(struct kvm_vcpu *vcpu, u64 val) continue; pmc = kvm_pmu_get_kvm_pmc(vcpu, i); - if (pmc->perf_event) { - perf_event_enable(pmc->perf_event); - if (pmc->perf_event->state != PERF_EVENT_STATE_ACTIVE) + + /* + * For high counters of chained events we must recreate the + * perf event with the long (64bit) attribute set. + */ + if (kvm_pmu_pair_is_chained(pmc) && + kvm_pmu_pair_is_high_counter(i)) { + kvm_pmu_create_perf_event(vcpu, i); + continue; + } + + perf_event = kvm_pmu_get_perf_event(pmc); + if (perf_event) { + perf_event_enable(perf_event); + if (perf_event->state != PERF_EVENT_STATE_ACTIVE) kvm_debug("fail to enable perf event\n"); } } @@ -224,6 +360,7 @@ void kvm_pmu_disable_counter_mask(struct kvm_vcpu *vcpu, u64 val) { int i; struct kvm_pmc *pmc; + struct perf_event *perf_event; if (!val) return; @@ -233,8 +370,20 @@ void kvm_pmu_disable_counter_mask(struct kvm_vcpu *vcpu, u64 val) continue; pmc = kvm_pmu_get_kvm_pmc(vcpu, i); - if (pmc->perf_event) - perf_event_disable(pmc->perf_event); + + /* + * For high counters of chained events we must recreate the + * perf event with the long (64bit) attribute unset. + */ + perf_event = kvm_pmu_get_perf_event(pmc); + if (kvm_pmu_pair_is_chained(pmc) && + kvm_pmu_pair_is_high_counter(i)) { + kvm_pmu_create_perf_event(vcpu, i); + continue; + } + + if (perf_event) + perf_event_disable(perf_event); } } @@ -430,10 +579,19 @@ static bool kvm_pmu_counter_is_enabled(struct kvm_vcpu *vcpu, u64 select_idx) static void kvm_pmu_create_perf_event(struct kvm_vcpu *vcpu, u64 select_idx) { struct kvm_pmc *pmc = kvm_pmu_get_kvm_pmc(vcpu, select_idx); + struct kvm_pmc_pair *pmc_pair = kvm_pmu_get_kvm_pmc_pair(pmc); struct perf_event *event; struct perf_event_attr attr; u64 eventsel, counter, reg, data; + /* + * For chained counters the event type and filtering attributes are + * obtained from the low/even counter. We also use this counter to + * determine if the event is enabled/disabled. + */ + if (kvm_pmu_event_is_chained(vcpu, select_idx)) + select_idx &= ~1UL; + reg = (select_idx == ARMV8_PMU_CYCLE_IDX) ? PMCCFILTR_EL0 : PMEVTYPER0_EL0 + select_idx; data = __vcpu_sys_reg(vcpu, reg); @@ -458,19 +616,61 @@ static void kvm_pmu_create_perf_event(struct kvm_vcpu *vcpu, u64 select_idx) attr.config = (select_idx == ARMV8_PMU_CYCLE_IDX) ? ARMV8_PMUV3_PERFCTR_CPU_CYCLES : eventsel; - counter = kvm_pmu_get_counter_value(vcpu, select_idx); - /* The initial sample period (overflow count) of an event. */ - attr.sample_period = (-counter) & pmc->bitmask; + counter = kvm_pmu_get_pair_counter_value(vcpu, pmc); - event = perf_event_create_kernel_counter(&attr, -1, current, + if (kvm_pmu_event_is_chained(vcpu, pmc->idx)) { + /** + * The initial sample period (overflow count) of an event. For + * chained counters we only support overflow interrupts on the + * high counter. + */ + attr.sample_period = (-counter) & 0xffffffffffffffffUL; + event = perf_event_create_kernel_counter(&attr, -1, current, + kvm_pmu_perf_overflow, + &pmc_pair->high); + + if (kvm_pmu_counter_is_enabled(vcpu, pmc_pair->high.idx)) + attr.config1 |= PERF_ATTR_CFG1_KVM_PMU_CHAINED; + } else { + /* The initial sample period (overflow count) of an event. */ + attr.sample_period = (-counter) & pmc->bitmask; + event = perf_event_create_kernel_counter(&attr, -1, current, kvm_pmu_perf_overflow, pmc); + } + if (IS_ERR(event)) { pr_err_once("kvm: pmu event creation failed %ld\n", PTR_ERR(event)); return; } - pmc->perf_event = event; + kvm_pmu_set_perf_event(pmc, event); +} + +/** + * Update the kvm_pmc_pair type based on the event type written in the + * typer register. + * + * @vcpu: The vcpu pointer + * @select_idx: The number of selected counter + */ +static void kvm_pmu_update_kvm_pmc_type(struct kvm_vcpu *vcpu, u64 select_idx) +{ + struct kvm_pmc *pmc = kvm_pmu_get_kvm_pmc(vcpu, select_idx); + struct kvm_pmc_pair *pmc_pair = kvm_pmu_get_kvm_pmc_pair(pmc); + + if (kvm_pmu_event_is_chained(vcpu, pmc->idx)) { + /* + * During promotion from paired to chained we must ensure + * the adjacent counter is stopped and its event destroyed + */ + if (!kvm_pmu_pair_is_chained(pmc)) + kvm_pmu_stop_counter(vcpu, &pmc_pair->low); + + pmc_pair->type = KVM_PMC_TYPE_CHAIN; + } else { + pmc_pair->type = KVM_PMC_TYPE_PAIR; + } } /** @@ -492,6 +692,8 @@ void kvm_pmu_set_counter_event_type(struct kvm_vcpu *vcpu, u64 data, ? PMCCFILTR_EL0 : PMEVTYPER0_EL0 + select_idx; __vcpu_sys_reg(vcpu, reg) = event_type; + + kvm_pmu_update_kvm_pmc_type(vcpu, select_idx); kvm_pmu_create_perf_event(vcpu, select_idx); }