From patchwork Fri Apr 11 11:01:23 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Neil Zhang X-Patchwork-Id: 28278 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-yk0-f200.google.com (mail-yk0-f200.google.com [209.85.160.200]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 9AE2420A72 for ; Fri, 11 Apr 2014 11:02:18 +0000 (UTC) Received: by mail-yk0-f200.google.com with SMTP id q9sf10498045ykb.7 for ; Fri, 11 Apr 2014 04:02:18 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:cc:subject:date:message-id :mime-version:sender:precedence:list-id:x-original-sender :x-original-authentication-results:mailing-list:list-post:list-help :list-archive:list-unsubscribe:content-type; bh=H7ffH3vqvh9nqh877d2ME1jaHoPb+Uo1QhAxLr7pqh4=; b=cgVW2LXzICcBBI+l0iAot8xv8fikLBPZcPhVzeP733sI/KMyI4eJo5ARmbMOfatDe+ XkqRHn5ediTkERh66D360UCQ8FABTBWk3CxKzsNe6vnwbR/mbAXnCCQ2mT87n4QYxv2N JQE+fVGvzVv3mUICfrb4WCdavvEb5comWwzqUttg0QRQgZCytlKuGRSmW7TuvuS1X6Zp TzaSdHgkWS2A83Z1uS2WzVUzQxS5OmMawlzwgBCi4/qLqfQjdPC/qaOGXqdUVUuUJFWh fT40jZp4itb93RT1MbN5x2vJ3ldellHlJAk/gGsfdR9eoWa5DTDzco1yS+wXB7ibe8CS Nt6Q== X-Gm-Message-State: ALoCoQlDhXF6eiihM7A9Rd7PwI4mRnCw4TF49hl5y2tVkep6nWq/CQKTQcjn8LLktsPfn3TwP7y1 X-Received: by 10.52.28.116 with SMTP id a20mr9479947vdh.2.1397214138279; Fri, 11 Apr 2014 04:02:18 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.88.72 with SMTP id s66ls1592737qgd.11.gmail; Fri, 11 Apr 2014 04:02:18 -0700 (PDT) X-Received: by 10.58.107.65 with SMTP id ha1mr19548242veb.1.1397214138137; Fri, 11 Apr 2014 04:02:18 -0700 (PDT) Received: from mail-vc0-f178.google.com (mail-vc0-f178.google.com [209.85.220.178]) by mx.google.com with ESMTPS id y7si570982veb.36.2014.04.11.04.02.18 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 11 Apr 2014 04:02:18 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.220.178 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.220.178; Received: by mail-vc0-f178.google.com with SMTP id im17so4557480vcb.37 for ; Fri, 11 Apr 2014 04:02:18 -0700 (PDT) X-Received: by 10.58.46.207 with SMTP id x15mr19896805vem.17.1397214138041; Fri, 11 Apr 2014 04:02:18 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.220.221.72 with SMTP id ib8csp47276vcb; Fri, 11 Apr 2014 04:02:17 -0700 (PDT) X-Received: by 10.66.192.73 with SMTP id he9mr26463853pac.88.1397214137319; Fri, 11 Apr 2014 04:02:17 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id ep2si3998930pbb.88.2014.04.11.04.02.16; Fri, 11 Apr 2014 04:02:16 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755347AbaDKLCH (ORCPT + 26 others); Fri, 11 Apr 2014 07:02:07 -0400 Received: from mx0b-0016f401.pphosted.com ([67.231.156.173]:9939 "EHLO mx0b-0016f401.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753559AbaDKLCE (ORCPT ); Fri, 11 Apr 2014 07:02:04 -0400 Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.14.5/8.14.5) with SMTP id s3BB1TGo019141; Fri, 11 Apr 2014 04:01:29 -0700 Received: from sc-owa04.marvell.com ([199.233.58.150]) by mx0b-0016f401.pphosted.com with ESMTP id 1k69whshdh-18 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=NOT); Fri, 11 Apr 2014 04:01:29 -0700 Received: from maili.marvell.com (10.93.76.43) by sc-owa02.marvell.com (10.93.76.33) with Microsoft SMTP Server id 8.3.327.1; Fri, 11 Apr 2014 04:01:26 -0700 Received: from localhost (unknown [10.38.164.185]) by maili.marvell.com (Postfix) with ESMTP id 817F93F7044; Fri, 11 Apr 2014 04:01:25 -0700 (PDT) From: Neil Zhang To: , CC: , , Sudeep KarkadaNagesha , Neil Zhang Subject: [PATCH] ARM: perf: save/restore pmu registers in pm notifier Date: Fri, 11 Apr 2014 19:01:23 +0800 Message-ID: <1397214083-30916-1-git-send-email-zhangwm@marvell.com> X-Mailer: git-send-email 1.7.9.5 MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:5.11.96, 1.0.14, 0.0.0000 definitions=2014-04-11_03:2014-04-11, 2014-04-11, 1970-01-01 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=2 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=7.0.1-1402240000 definitions=main-1404110180 Sender: linux-kernel-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: zhangwm@marvell.com X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.220.178 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , From: Sudeep KarkadaNagesha This adds core support for saving and restoring CPU PMU registers for suspend/resume support i.e. deeper C-states in cpuidle terms. This patch adds support only to ARMv7 PMU registers save/restore. It needs to be extended to xscale and ARMv6 if needed. [Neil] We found that DS-5 not work on our CA7 based SoCs. After debuging, found PMU registers were lost because of core power down. Then i found Sudeep had a patch to fix it about two years ago but not in the mainline, just port it. Signed-off-by: Sudeep KarkadaNagesha Signed-off-by: Neil Zhang --- arch/arm/include/asm/pmu.h | 11 +++++++++ arch/arm/kernel/perf_event_cpu.c | 30 +++++++++++++++++++++++- arch/arm/kernel/perf_event_v7.c | 47 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 1 deletion(-) diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h index ae1919b..f37f048 100644 --- a/arch/arm/include/asm/pmu.h +++ b/arch/arm/include/asm/pmu.h @@ -62,6 +62,15 @@ struct pmu_hw_events { raw_spinlock_t pmu_lock; }; +struct cpupmu_regs { + u32 pmc; + u32 pmcntenset; + u32 pmuseren; + u32 pmintenset; + u32 pmxevttype[8]; + u32 pmxevtcnt[8]; +}; + struct arm_pmu { struct pmu pmu; cpumask_t active_irqs; @@ -83,6 +92,8 @@ struct arm_pmu { int (*request_irq)(struct arm_pmu *, irq_handler_t handler); void (*free_irq)(struct arm_pmu *); int (*map_event)(struct perf_event *event); + void (*save_regs)(struct arm_pmu *, struct cpupmu_regs *); + void (*restore_regs)(struct arm_pmu *, struct cpupmu_regs *); int num_events; atomic_t active_events; struct mutex reserve_mutex; diff --git a/arch/arm/kernel/perf_event_cpu.c b/arch/arm/kernel/perf_event_cpu.c index 51798d7..934f49b 100644 --- a/arch/arm/kernel/perf_event_cpu.c +++ b/arch/arm/kernel/perf_event_cpu.c @@ -19,6 +19,7 @@ #define pr_fmt(fmt) "CPU PMU: " fmt #include +#include #include #include #include @@ -39,6 +40,7 @@ static DEFINE_PER_CPU(struct arm_pmu *, percpu_pmu); static DEFINE_PER_CPU(struct perf_event * [ARMPMU_MAX_HWEVENTS], hw_events); static DEFINE_PER_CPU(unsigned long [BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)], used_mask); static DEFINE_PER_CPU(struct pmu_hw_events, cpu_hw_events); +static DEFINE_PER_CPU(struct cpupmu_regs, cpu_pmu_regs); /* * Despite the names, these two functions are CPU-specific and are used @@ -217,6 +219,24 @@ static struct notifier_block cpu_pmu_hotplug_notifier = { .notifier_call = cpu_pmu_notify, }; +static int cpu_pmu_pm_notify(struct notifier_block *b, + unsigned long action, void *hcpu) +{ + int cpu = smp_processor_id(); + struct cpupmu_regs *pmuregs = &per_cpu(cpu_pmu_regs, cpu); + + if (action == CPU_PM_ENTER && cpu_pmu->save_regs) + cpu_pmu->save_regs(cpu_pmu, pmuregs); + else if (action == CPU_PM_EXIT && cpu_pmu->restore_regs) + cpu_pmu->restore_regs(cpu_pmu, pmuregs); + + return NOTIFY_OK; +} + +static struct notifier_block cpu_pmu_pm_notifier = { + .notifier_call = cpu_pmu_pm_notify, +}; + /* * PMU platform driver and devicetree bindings. */ @@ -349,9 +369,17 @@ static int __init register_pmu_driver(void) if (err) return err; + err = cpu_pm_register_notifier(&cpu_pmu_pm_notifier); + if (err) { + unregister_cpu_notifier(&cpu_pmu_hotplug_notifier); + return err; + } + err = platform_driver_register(&cpu_pmu_driver); - if (err) + if (err) { + cpu_pm_unregister_notifier(&cpu_pmu_pm_notifier); unregister_cpu_notifier(&cpu_pmu_hotplug_notifier); + } return err; } diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c index f4ef398..29ae8f1 100644 --- a/arch/arm/kernel/perf_event_v7.c +++ b/arch/arm/kernel/perf_event_v7.c @@ -1237,6 +1237,51 @@ static void armv7_pmnc_dump_regs(struct arm_pmu *cpu_pmu) } #endif +static void armv7pmu_save_regs(struct arm_pmu *cpu_pmu, + struct cpupmu_regs *regs) +{ + unsigned int cnt; + asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r" (regs->pmc)); + if (!(regs->pmc & ARMV7_PMNC_E)) + return; + + asm volatile("mrc p15, 0, %0, c9, c12, 1" : "=r" (regs->pmcntenset)); + asm volatile("mrc p15, 0, %0, c9, c14, 0" : "=r" (regs->pmuseren)); + asm volatile("mrc p15, 0, %0, c9, c14, 1" : "=r" (regs->pmintenset)); + asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (regs->pmxevtcnt[0])); + for (cnt = ARMV7_IDX_COUNTER0; + cnt <= ARMV7_IDX_COUNTER_LAST(cpu_pmu); cnt++) { + armv7_pmnc_select_counter(cnt); + asm volatile("mrc p15, 0, %0, c9, c13, 1" + : "=r"(regs->pmxevttype[cnt])); + asm volatile("mrc p15, 0, %0, c9, c13, 2" + : "=r"(regs->pmxevtcnt[cnt])); + } + return; +} + +static void armv7pmu_restore_regs(struct arm_pmu *cpu_pmu, + struct cpupmu_regs *regs) +{ + unsigned int cnt; + if (!(regs->pmc & ARMV7_PMNC_E)) + return; + + asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (regs->pmcntenset)); + asm volatile("mcr p15, 0, %0, c9, c14, 0" : : "r" (regs->pmuseren)); + asm volatile("mcr p15, 0, %0, c9, c14, 1" : : "r" (regs->pmintenset)); + asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (regs->pmxevtcnt[0])); + for (cnt = ARMV7_IDX_COUNTER0; + cnt <= ARMV7_IDX_COUNTER_LAST(cpu_pmu); cnt++) { + armv7_pmnc_select_counter(cnt); + asm volatile("mcr p15, 0, %0, c9, c13, 1" + : : "r"(regs->pmxevttype[cnt])); + asm volatile("mcr p15, 0, %0, c9, c13, 2" + : : "r"(regs->pmxevtcnt[cnt])); + } + asm volatile("mcr p15, 0, %0, c9, c12, 0" : : "r" (regs->pmc)); +} + static void armv7pmu_enable_event(struct perf_event *event) { unsigned long flags; @@ -1528,6 +1573,8 @@ static void armv7pmu_init(struct arm_pmu *cpu_pmu) cpu_pmu->start = armv7pmu_start; cpu_pmu->stop = armv7pmu_stop; cpu_pmu->reset = armv7pmu_reset; + cpu_pmu->save_regs = armv7pmu_save_regs; + cpu_pmu->restore_regs = armv7pmu_restore_regs; cpu_pmu->max_period = (1LLU << 32) - 1; };