Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752851AbdC0QCx (ORCPT ); Mon, 27 Mar 2017 12:02:53 -0400 Received: from mga03.intel.com ([134.134.136.65]:56938 "EHLO mga03.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752284AbdC0QCo (ORCPT ); Mon, 27 Mar 2017 12:02:44 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.36,232,1486454400"; d="scan'208";a="81480672" From: kan.liang@intel.com To: peterz@infradead.org, tglx@linutronix.de, mingo@redhat.com, linux-kernel@vger.kernel.org Cc: acme@kernel.org, eranian@google.com, jolsa@kernel.org, ak@linux.intel.com, Kan Liang Subject: [PATCH V2 1/2] x86/msr: add msr_set/clear_bit_on_cpu/cpus access functions Date: Mon, 27 Mar 2017 08:47:37 -0700 Message-Id: <1490629658-4308-2-git-send-email-kan.liang@intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1490629658-4308-1-git-send-email-kan.liang@intel.com> References: <1490629658-4308-1-git-send-email-kan.liang@intel.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 4086 Lines: 157 From: Kan Liang Having msr_set/clear_bit on many cpus or given CPU can avoid extra unnecessory IPIs and simplify MSR content manipulation, when it only needs to flip a bit. There is already msr_set/clear_bit, but missing the _on_cpu and _on_cpus version. Signed-off-by: Kan Liang --- arch/x86/include/asm/msr.h | 29 ++++++++++++++++++ arch/x86/lib/msr-smp.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+) diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h index 898dba2..9bc999b 100644 --- a/arch/x86/include/asm/msr.h +++ b/arch/x86/include/asm/msr.h @@ -20,6 +20,11 @@ struct msr { }; }; +struct msr_bit_info { + u32 msr_no; + u8 bit; +}; + struct msr_info { u32 msr_no; struct msr reg; @@ -314,6 +319,10 @@ int msr_set_bit(u32 msr, u8 bit); int msr_clear_bit(u32 msr, u8 bit); #ifdef CONFIG_SMP +int msr_set_bit_on_cpu(unsigned int cpu, u32 msr, u8 bit); +int msr_clear_bit_on_cpu(unsigned int cpu, u32 msr, u8 bit); +void msr_set_bit_on_cpus(const struct cpumask *mask, u32 msr, u8 bit); +void msr_clear_bit_on_cpus(const struct cpumask *mask, u32 msr, u8 bit); int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); int rdmsrl_on_cpu(unsigned int cpu, u32 msr_no, u64 *q); @@ -327,6 +336,26 @@ int wrmsrl_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 q); int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]); int wrmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]); #else /* CONFIG_SMP */ +static inline int msr_set_bit_on_cpu(unsigned int cpu, u32 msr, u8 bit) +{ + return msr_set_bit(msr, bit); +} + +static inline int msr_clear_bit_on_cpu(unsigned int cpu, u32 msr, u8 bit) +{ + return msr_clear_bit(msr, bit); +} + +static inline void msr_set_bit_on_cpus(const struct cpumask *mask, u32 msr, u8 bit) +{ + msr_set_bit(msr, bit); +} + +static inline void msr_clear_bit_on_cpus(const struct cpumask *mask, u32 msr, u8 bit) +{ + msr_clear_bit(msr, bit); +} + static inline int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) { rdmsr(msr_no, *l, *h); diff --git a/arch/x86/lib/msr-smp.c b/arch/x86/lib/msr-smp.c index ce68b6a..100b3cb 100644 --- a/arch/x86/lib/msr-smp.c +++ b/arch/x86/lib/msr-smp.c @@ -3,6 +3,82 @@ #include #include +static void __msr_set_bit_on_cpu(void *info) +{ + struct msr_bit_info *bit_info = info; + + msr_set_bit(bit_info->msr_no, bit_info->bit); +} + +static void __msr_clear_bit_on_cpu(void *info) +{ + struct msr_bit_info *bit_info = info; + + msr_clear_bit(bit_info->msr_no, bit_info->bit); +} + +int msr_set_bit_on_cpu(unsigned int cpu, u32 msr, u8 bit) +{ + struct msr_bit_info info; + int err; + + info.msr_no = msr; + info.bit = bit; + + err = smp_call_function_single(cpu, __msr_set_bit_on_cpu, &info, 1); + + return err; +} +EXPORT_SYMBOL(msr_set_bit_on_cpu); + +int msr_clear_bit_on_cpu(unsigned int cpu, u32 msr, u8 bit) +{ + struct msr_bit_info info; + int err; + + info.msr_no = msr; + info.bit = bit; + + err = smp_call_function_single(cpu, __msr_clear_bit_on_cpu, &info, 1); + + return err; +} +EXPORT_SYMBOL(msr_clear_bit_on_cpu); + +void msr_set_bit_on_cpus(const struct cpumask *mask, u32 msr, u8 bit) +{ + struct msr_bit_info info; + int this_cpu; + + info.msr_no = msr; + info.bit = bit; + + this_cpu = get_cpu(); + if (cpumask_test_cpu(this_cpu, mask)) + __msr_set_bit_on_cpu(&info); + + smp_call_function_many(mask, __msr_set_bit_on_cpu, &info, 1); + put_cpu(); +} +EXPORT_SYMBOL(msr_set_bit_on_cpus); + +void msr_clear_bit_on_cpus(const struct cpumask *mask, u32 msr, u8 bit) +{ + struct msr_bit_info info; + int this_cpu; + + info.msr_no = msr; + info.bit = bit; + + this_cpu = get_cpu(); + if (cpumask_test_cpu(this_cpu, mask)) + __msr_clear_bit_on_cpu(&info); + + smp_call_function_many(mask, __msr_clear_bit_on_cpu, &info, 1); + put_cpu(); +} +EXPORT_SYMBOL(msr_clear_bit_on_cpus); + static void __rdmsr_on_cpu(void *info) { struct msr_info *rv = info; -- 2.7.4