From patchwork Thu Nov 16 06:27:28 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jia He X-Patchwork-Id: 10060779 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 69C6A601AE for ; Thu, 16 Nov 2017 06:28:41 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5BEDE2A7D0 for ; Thu, 16 Nov 2017 06:28:41 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 509902A7CE; Thu, 16 Nov 2017 06:28:41 +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=-4.2 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, DKIM_VALID, FREEMAIL_FROM, RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.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 C8FAD2A7AE for ; Thu, 16 Nov 2017 06:28:40 +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:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id: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:In-Reply-To: References:List-Owner; bh=2i79Z9AqjJnziDBpWSrQagq6nH90/Xq6aHmB33BIt9Q=; b=Nis +xp2fE0ouc7X2wwaednGHOhBbg3IIVH8PiypY6wfP++PTbktg82x3HMoz82FejNO6xdAYVdIMhOJd 7NfuKkHDY+HSdt8d7JFmN9MfXHv++5ttDFReISY1PMXnkb/HQmN7co8003ROPIZZqBrIPXxCMQ1WP HwmBVOUgg1pnGtGN+t7cjg0KrqAmY7bQtlY6pweNiP1YfteMXRVdRkKuuuYgs04kkBxuZ7OyNnko3 yAGxEoj2ZZCc4SXFJopBZuHgBS4+Z/xENpVK8bujaSC8/75qfJ7M9Brw8QVd05rlHkYwLIpy71Sb3 ZhNzRnK4OYCKgDAJHHepqfuuS5uzSKQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1eFDf8-0003t4-S4; Thu, 16 Nov 2017 06:28:34 +0000 Received: from mail-pg0-x242.google.com ([2607:f8b0:400e:c05::242]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1eFDek-0003rj-0K for linux-arm-kernel@lists.infradead.org; Thu, 16 Nov 2017 06:28:11 +0000 Received: by mail-pg0-x242.google.com with SMTP id 70so7387171pgf.6 for ; Wed, 15 Nov 2017 22:27:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=pbgEEgiKln0I816TlsoIyiN9YUEeBrRgvHQLFGfdUbc=; b=f2CPGnLifNSrJncvmRmTlJoj8xAj4ONiZuRJjZ/PSvV60ruhOhLFgvSYwWO5zpr0iS OCxfqzKMyfot6jm6A4cAyxnxPDPd8KEzbVvi1No6oDxw994Qj6s7HHGjSATQfHvI8fkP UfBnn1YEhd8M5QIv9lfB41Cs3yr9rZel7yVHUYiGqF52nPFV/6W2DrQJjqJocrONkOII mpKJmNNv+eT9qZUWxUxCpCFJwcpP73ZFksjopDPUhC6PkGKkd3OD1JMbQLo+Qw0qbNVe xCOMNmdy35Mi+Q4pv3J2gm0JV1/CRiSEmhi5pHSX0xkSfmoAEC1wxt7D+X4Tjjtzwyre 6R4g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=pbgEEgiKln0I816TlsoIyiN9YUEeBrRgvHQLFGfdUbc=; b=rMTux2uA+xQFJdVbzwpkV3s/YWURhp8cJtHF4aU+UnERyiH2d5nbAcr/zupZ105wLn jSbMuGsJFS5w2ajIu44tvEp1+usE67crY0O9/pHR7h3oNEsPlFyKQ/VbPoQUwRn/kdi5 mnD8eLijie5iaVEHGZSCTfA5mtJO+Iry2uHNrMpinnogBbC6nv0cc1YK7kpTIlpNaSlX gOrSsdoGWMYFfu8d2EG3om1mukKBj5sTTH4fPGtiPWYg2nYs3+IZojd8tWGR05Py3/kG OKwItzFDLBF4CeK46GDhKWn7HiGTbaCKMsjn7wn09K2ZEgmWchsrGw0Fi3UUdyYJMUKJ LIZA== X-Gm-Message-State: AJaThX4ZO2Jz8h3JSIdfmOmKgQzH78Jeok976tDx08TrQJDFJRHb0Wfg DtW0zxIuCL+fgvpaWbeKjgg= X-Google-Smtp-Source: AGs4zMbg04uiYKG9SCjjKporfLPkHxLhFt/CMQrLXiWaqNJVTm/Ek7X7UKGjEbd78PVaIMYb89Oqpg== X-Received: by 10.99.60.26 with SMTP id j26mr664099pga.256.1510813668406; Wed, 15 Nov 2017 22:27:48 -0800 (PST) Received: from nfv-demo01.hxtcorp.net ([38.106.11.25]) by smtp.gmail.com with ESMTPSA id q8sm1111298pfk.100.2017.11.15.22.27.43 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 15 Nov 2017 22:27:47 -0800 (PST) From: Jia He To: Will Deacon , Mark Rutland , linux-arm-kernel@lists.infradead.org Subject: [PATCH] drivers/perf: arm_pmu: save/restore cpu cycle counter in cpu_pm_pmu_notify Date: Thu, 16 Nov 2017 06:27:28 +0000 Message-Id: <1510813648-45090-1-git-send-email-hejianet@gmail.com> X-Mailer: git-send-email 2.7.4 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171115_222810_084792_0A6A3187 X-CRM114-Status: GOOD ( 15.42 ) 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: Jia He , Jia He , Lorenzo Pieralisi , linux-kernel@vger.kernel.org MIME-Version: 1.0 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 Sometimes userspace need a high resolution cycle counter by reading pmccntr_el0. In commit da4e4f18afe0 ("drivers/perf: arm_pmu: implement CPU_PM notifier"), it resets all the counters even when the pmcr_el0.E and pmcntenset_el0.C are both 1 . That is incorrect. We need to save the registers and counter before CPU_PM_ENTER and restore them after CPU_PM_EXIT. Fixes: da4e4f18afe0 ("drivers/perf: arm_pmu: implement CPU_PM notifier") Signed-off-by: Jia He --- drivers/perf/arm_pmu.c | 72 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 66 insertions(+), 6 deletions(-) diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c index 7bc5eee..cf55c91 100644 --- a/drivers/perf/arm_pmu.c +++ b/drivers/perf/arm_pmu.c @@ -26,6 +26,12 @@ #include +#ifdef CONFIG_CPU_PM +DEFINE_PER_CPU(u32, saved_pmcr_el0); +DEFINE_PER_CPU(u32, saved_pmcntenset_el0); +DEFINE_PER_CPU(u64, saved_cycle_cnter); +#endif + static int armpmu_map_cache_event(const unsigned (*cache_map) [PERF_COUNT_HW_CACHE_MAX] @@ -719,6 +725,15 @@ static void cpu_pm_pmu_setup(struct arm_pmu *armpmu, unsigned long cmd) } } +static int pmc_cycle_counter_enabled(void) +{ + if ((read_sysreg(pmcr_el0) & ARMV8_PMU_PMCR_E) && + read_sysreg(pmcntenset_el0) & 1<<31) + return 1; + + return 0; +} + static int cpu_pm_pmu_notify(struct notifier_block *b, unsigned long cmd, void *v) { @@ -729,16 +744,53 @@ static int cpu_pm_pmu_notify(struct notifier_block *b, unsigned long cmd, if (!cpumask_test_cpu(smp_processor_id(), &armpmu->supported_cpus)) return NOTIFY_DONE; - /* - * Always reset the PMU registers on power-up even if - * there are no events running. - */ - if (cmd == CPU_PM_EXIT && armpmu->reset) - armpmu->reset(armpmu); + if (cmd == CPU_PM_EXIT) { + /* + * Always reset the PMU registers on power-up even if + * there are no events running. + */ + if (armpmu->reset) + armpmu->reset(armpmu); + + /* + * Restore the saved pmcr_el0 and pmcntenset_el0 + * if pmc cycle counter is enabled, restore the counter + */ + write_sysreg(get_cpu_var(saved_pmcr_el0), pmcr_el0); + write_sysreg(get_cpu_var(saved_pmcntenset_el0), + pmcntenset_el0); + + if (pmc_cycle_counter_enabled()) { + write_sysreg(get_cpu_var(saved_cycle_cnter), + pmccntr_el0); + put_cpu_var(saved_cycle_cnter); + } + put_cpu_var(saved_pmcntenset_el0); + put_cpu_var(saved_pmcr_el0); + } + + if (cmd == CPU_PM_ENTER) { + /* If currently pmc cycle counter is enabled, + * save the counter to percpu section + */ + if (pmc_cycle_counter_enabled()) { + get_cpu_var(saved_cycle_cnter) = read_sysreg( + pmccntr_el0); + put_cpu_var(saved_cycle_cnter); + } + + get_cpu_var(saved_pmcr_el0) = read_sysreg(pmcr_el0); + + get_cpu_var(saved_pmcntenset_el0) = read_sysreg( + pmcntenset_el0); + put_cpu_var(saved_pmcntenset_el0); + put_cpu_var(saved_pmcr_el0); + } if (!enabled) return NOTIFY_OK; + /* if any hw_events is used */ switch (cmd) { case CPU_PM_ENTER: armpmu->stop(armpmu); @@ -758,7 +810,15 @@ static int cpu_pm_pmu_notify(struct notifier_block *b, unsigned long cmd, static int cpu_pm_pmu_register(struct arm_pmu *cpu_pmu) { + int i; cpu_pmu->cpu_pm_nb.notifier_call = cpu_pm_pmu_notify; + + for_each_possible_cpu(i) { + per_cpu(saved_pmcr_el0, i) = 0; + per_cpu(saved_pmcntenset_el0, i) = 0; + per_cpu(saved_cycle_cnter, i) = 0; + } + return cpu_pm_register_notifier(&cpu_pmu->cpu_pm_nb); }