From patchwork Thu Aug 17 08:39:19 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julien Thierry X-Patchwork-Id: 9905313 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 3696960244 for ; Thu, 17 Aug 2017 08:40:29 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 243EE28AD0 for ; Thu, 17 Aug 2017 08:40:29 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 192E128AD3; Thu, 17 Aug 2017 08:40:29 +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=-2.6 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_LOW autolearn=ham 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 5DADD28AD0 for ; Thu, 17 Aug 2017 08:40:28 +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: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=THM3yCSjJChG/+Wqua9fYZmNZWxcTHBq8BCovrTT6hg=; b=u05hZVXWjt9yOjuvBXfJGkVqKv Bn/wK+Oe4Hy2EyNzqt5CXsGr6TErAFZ3kWPDdX3YpIy/+26ZxOzuR3MwZd+3eDPWiiRWE6Ta8OJO5 KefgvSuN7yqDhuAN40o2lzXYCpowMtaNfO6U5Jncrc5W8g17cEh4qNb17M17LPI4O9JsOA+8o3vUr aXKvWjbwq7a206Xf6SCa4dOrPnjMKl2wJrTqioDx4aP7IPsFqMCgSSHlvgQYaAcVG6WyQPwW1ja6J jWJfes7DQVODCs7VpJPv0ZQhQpA9TT8RkKUxqL4R+u9gvC52JVF3vDwbB/BbMslU6VuyOPXshXJkf KoQ3Qmrw==; 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 1diGLk-0005TL-23; Thu, 17 Aug 2017 08:40:20 +0000 Received: from foss.arm.com ([217.140.101.70]) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1diGLJ-0003qN-RR for linux-arm-kernel@lists.infradead.org; Thu, 17 Aug 2017 08:39:56 +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 D6599165C; Thu, 17 Aug 2017 01:39:35 -0700 (PDT) Received: from e112298-lin.cambridge.arm.com (usa-sjc-imap-foss1.foss.arm.com [10.72.51.249]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id A1D213F483; Thu, 17 Aug 2017 01:39:34 -0700 (PDT) From: Julien Thierry To: linux-arm-kernel@lists.infradead.org Subject: [PATCH v2 1/2] arm_arch_timer: Expose event stream status Date: Thu, 17 Aug 2017 09:39:19 +0100 Message-Id: <1502959160-30900-2-git-send-email-julien.thierry@arm.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1502959160-30900-1-git-send-email-julien.thierry@arm.com> References: <1502959160-30900-1-git-send-email-julien.thierry@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170817_013954_012099_39A6AE50 X-CRM114-Status: GOOD ( 16.12 ) 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: Mark Rutland , Julien Thierry , Marc Zyngier , Catalin Marinas , Will Deacon , Russell King 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 The arch timer configuration for a CPU might get reset after suspending said CPU. In order to reliably use the event stream in the kernel (e.g. for delays), we keep track of the state where we can safely concider the event stream as properly configured. Signed-off: Julien Thierry Cc: Mark Rutland Cc: Marc Zyngier Cc: Russell King Cc: Catalin Marinas Cc: Will Deacon --- arch/arm/include/asm/arch_timer.h | 1 + arch/arm64/include/asm/arch_timer.h | 1 + drivers/clocksource/arm_arch_timer.c | 32 ++++++++++++++++++++++++++++++-- include/clocksource/arm_arch_timer.h | 6 ++++++ 4 files changed, 38 insertions(+), 2 deletions(-) -- 1.9.1 diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h index d4ebf56..0b6e104 100644 --- a/arch/arm/include/asm/arch_timer.h +++ b/arch/arm/include/asm/arch_timer.h @@ -106,6 +106,7 @@ static inline u32 arch_timer_get_cntkctl(void) static inline void arch_timer_set_cntkctl(u32 cntkctl) { asm volatile("mcr p15, 0, %0, c14, c1, 0" : : "r" (cntkctl)); + isb(); } #endif diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h index 74d08e4..26b3376 100644 --- a/arch/arm64/include/asm/arch_timer.h +++ b/arch/arm64/include/asm/arch_timer.h @@ -144,6 +144,7 @@ static inline u32 arch_timer_get_cntkctl(void) static inline void arch_timer_set_cntkctl(u32 cntkctl) { write_sysreg(cntkctl, cntkctl_el1); + isb(); } static inline u64 arch_counter_get_cntpct(void) diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index aae87c4..866bbf8 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -77,6 +77,7 @@ struct arch_timer { static bool arch_counter_suspend_stop; static bool vdso_default = true; +static DEFINE_PER_CPU(bool, evtstrm_available) = false; static bool evtstrm_enable = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM); static int __init early_evtstrm_cfg(char *buf) @@ -736,6 +737,7 @@ static void arch_timer_evtstrm_enable(int divider) #ifdef CONFIG_COMPAT compat_elf_hwcap |= COMPAT_HWCAP_EVTSTRM; #endif + __this_cpu_write(evtstrm_available, true); } static void arch_timer_configure_evtstream(void) @@ -860,6 +862,26 @@ u32 arch_timer_get_rate(void) return arch_timer_rate; } +bool arch_timer_evtstrm_available(void) +{ + /* + * This function might get called outside of a preempt disable context. + * This is not an issue because the result of this function will stay + * valid for the CPU the caller task will be running on, even if + * preempted. The possible case are as follow: + * - evtstrm_available == false -> either event stream is disabled + * system-wide or event stream is momentarily disabled on this CPU + * meaning we won't be scheduling in/out tasks on this CPU until it + * is reconfigured. Current task is made aware it cannot rely on + * event stream. + * - evtstrm_available == true -> task was running on a CPU with event + * stream enabled, if it gets preempted, it will be resumed on a CPU + * where event stream is configured properly. The task can use the + * event stream. + */ + return this_cpu_read(evtstrm_available); +} + static u64 arch_counter_get_cntvct_mem(void) { u32 vct_lo, vct_hi, tmp_hi; @@ -925,6 +947,8 @@ static int arch_timer_dying_cpu(unsigned int cpu) { struct clock_event_device *clk = this_cpu_ptr(arch_timer_evt); + __this_cpu_write(evtstrm_available, false); + arch_timer_stop(clk); return 0; } @@ -934,10 +958,14 @@ static int arch_timer_dying_cpu(unsigned int cpu) static int arch_timer_cpu_pm_notify(struct notifier_block *self, unsigned long action, void *hcpu) { - if (action == CPU_PM_ENTER) + if (action == CPU_PM_ENTER) { __this_cpu_write(saved_cntkctl, arch_timer_get_cntkctl()); - else if (action == CPU_PM_ENTER_FAILED || action == CPU_PM_EXIT) + __this_cpu_write(evtstrm_available, false); + } + else if (action == CPU_PM_ENTER_FAILED || action == CPU_PM_EXIT) { arch_timer_set_cntkctl(__this_cpu_read(saved_cntkctl)); + __this_cpu_write(evtstrm_available, !!(elf_hwcap & HWCAP_EVTSTRM)); + } return NOTIFY_OK; } diff --git a/include/clocksource/arm_arch_timer.h b/include/clocksource/arm_arch_timer.h index cc805b7..4e28283 100644 --- a/include/clocksource/arm_arch_timer.h +++ b/include/clocksource/arm_arch_timer.h @@ -93,6 +93,7 @@ struct arch_timer_mem { extern u32 arch_timer_get_rate(void); extern u64 (*arch_timer_read_counter)(void); extern struct arch_timer_kvm_info *arch_timer_get_kvm_info(void); +extern bool arch_timer_evtstrm_available(void); #else @@ -106,6 +107,11 @@ static inline u64 arch_timer_read_counter(void) return 0; } +static inline bool arch_timer_evtstrm_available(void) +{ + return false; +} + #endif #endif