lkml.org 
[lkml]   [2009]   [May]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    SubjectRe: [PATCH 01/21] x86: add methods for writing of an MSR on several CPUs
    Hi,

    (adding Mauro to CC)

    On Wed, Apr 29, 2009 at 10:39:28AM -0700, H. Peter Anvin wrote:
    > Borislav Petkov wrote:
    > > +}
    > > +
    > > +/* rdmsr on a bunch of cpus
    > > + *
    > > + * @mask: which cpus
    > > + * @msr_no: which MSR
    > > + * @l: array of the lower 32-bit MSR values
    > > + * @h: array of the higher 32-bit MSR values
    > > + *
    >
    > Urk!
    >
    > Please, for the love of God, no!
    >
    > Make it an array of u64s or (equivalently!) an array of (l,h)
    > structures, not separate arrays for the halves of the register.

    how about something like the following then? If there's agreement I could
    convert all users to struct msr later.

    @Mauro: here's 1/21.

    --
    From: Borislav Petkov <borislav.petkov@amd.com>
    Date: Wed, 29 Apr 2009 15:20:11 +0200
    Subject: [PATCH] x86: add methods for writing of an MSR on several CPUs

    Add a struct representing a 64bit MSR pair consisting of a low and high
    register part.

    Also, rename msr-on-cpu.c to msr.c accordingly.

    Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
    ---
    arch/x86/include/asm/msr.h | 16 +++++
    arch/x86/lib/Makefile | 2 +-
    arch/x86/lib/msr-on-cpu.c | 97 ----------------------------
    arch/x86/lib/msr.c | 152 ++++++++++++++++++++++++++++++++++++++++++++
    4 files changed, 169 insertions(+), 98 deletions(-)
    delete mode 100644 arch/x86/lib/msr-on-cpu.c
    create mode 100644 arch/x86/lib/msr.c

    diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h
    index 638bf62..7f117a6 100644
    --- a/arch/x86/include/asm/msr.h
    +++ b/arch/x86/include/asm/msr.h
    @@ -2,6 +2,7 @@
    #define _ASM_X86_MSR_H

    #include <asm/msr-index.h>
    +#include <asm/cpumask.h>

    #ifndef __ASSEMBLY__
    # include <linux/types.h>
    @@ -13,6 +14,11 @@
    #include <asm/asm.h>
    #include <asm/errno.h>

    +struct msr {
    + u32 l;
    + u32 h;
    +};
    +
    static inline unsigned long long native_read_tscp(unsigned int *aux)
    {
    unsigned long low, high;
    @@ -216,6 +222,8 @@ do { \
    #ifdef CONFIG_SMP
    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 rdmsr_on_cpus(const cpumask_t *mask, u32 msr_no, struct msr *msrs);
    +int wrmsr_on_cpus(const cpumask_t *mask, u32 msr_no, struct msr *msrs);
    int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
    int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
    #else /* CONFIG_SMP */
    @@ -229,6 +237,14 @@ static inline int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
    wrmsr(msr_no, l, h);
    return 0;
    }
    +static inline int rdmsr_on_cpus(const cpumask_t *m, u32 msr_no, struct msr **msrs)
    +{
    + return rdmsr_on_cpu(msr_no, &(msrs[0].l), &(msrs[0].h));
    +}
    +static inline int wrmsr_on_cpus(const cpumask_t *m, u32 msr_no, struct msr **msrs)
    +{
    + return wrmsr_on_cpu(msr_no, msrs[0].l, msrs[0].h);
    +}
    static inline int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no,
    u32 *l, u32 *h)
    {
    diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
    index 55e11aa..f9d3563 100644
    --- a/arch/x86/lib/Makefile
    +++ b/arch/x86/lib/Makefile
    @@ -2,7 +2,7 @@
    # Makefile for x86 specific library files.
    #

    -obj-$(CONFIG_SMP) := msr-on-cpu.o
    +obj-$(CONFIG_SMP) := msr.o

    lib-y := delay.o
    lib-y += thunk_$(BITS).o
    diff --git a/arch/x86/lib/msr-on-cpu.c b/arch/x86/lib/msr-on-cpu.c
    deleted file mode 100644
    index 321cf72..0000000
    --- a/arch/x86/lib/msr-on-cpu.c
    +++ /dev/null
    @@ -1,97 +0,0 @@
    -#include <linux/module.h>
    -#include <linux/preempt.h>
    -#include <linux/smp.h>
    -#include <asm/msr.h>
    -
    -struct msr_info {
    - u32 msr_no;
    - u32 l, h;
    - int err;
    -};
    -
    -static void __rdmsr_on_cpu(void *info)
    -{
    - struct msr_info *rv = info;
    -
    - rdmsr(rv->msr_no, rv->l, rv->h);
    -}
    -
    -static void __wrmsr_on_cpu(void *info)
    -{
    - struct msr_info *rv = info;
    -
    - wrmsr(rv->msr_no, rv->l, rv->h);
    -}
    -
    -int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
    -{
    - int err;
    - struct msr_info rv;
    -
    - rv.msr_no = msr_no;
    - err = smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 1);
    - *l = rv.l;
    - *h = rv.h;
    -
    - return err;
    -}
    -
    -int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
    -{
    - int err;
    - struct msr_info rv;
    -
    - rv.msr_no = msr_no;
    - rv.l = l;
    - rv.h = h;
    - err = smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 1);
    -
    - return err;
    -}
    -
    -/* These "safe" variants are slower and should be used when the target MSR
    - may not actually exist. */
    -static void __rdmsr_safe_on_cpu(void *info)
    -{
    - struct msr_info *rv = info;
    -
    - rv->err = rdmsr_safe(rv->msr_no, &rv->l, &rv->h);
    -}
    -
    -static void __wrmsr_safe_on_cpu(void *info)
    -{
    - struct msr_info *rv = info;
    -
    - rv->err = wrmsr_safe(rv->msr_no, rv->l, rv->h);
    -}
    -
    -int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
    -{
    - int err;
    - struct msr_info rv;
    -
    - rv.msr_no = msr_no;
    - err = smp_call_function_single(cpu, __rdmsr_safe_on_cpu, &rv, 1);
    - *l = rv.l;
    - *h = rv.h;
    -
    - return err ? err : rv.err;
    -}
    -
    -int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
    -{
    - int err;
    - struct msr_info rv;
    -
    - rv.msr_no = msr_no;
    - rv.l = l;
    - rv.h = h;
    - err = smp_call_function_single(cpu, __wrmsr_safe_on_cpu, &rv, 1);
    -
    - return err ? err : rv.err;
    -}
    -
    -EXPORT_SYMBOL(rdmsr_on_cpu);
    -EXPORT_SYMBOL(wrmsr_on_cpu);
    -EXPORT_SYMBOL(rdmsr_safe_on_cpu);
    -EXPORT_SYMBOL(wrmsr_safe_on_cpu);
    diff --git a/arch/x86/lib/msr.c b/arch/x86/lib/msr.c
    new file mode 100644
    index 0000000..0ba5402
    --- /dev/null
    +++ b/arch/x86/lib/msr.c
    @@ -0,0 +1,152 @@
    +#include <linux/module.h>
    +#include <linux/preempt.h>
    +#include <linux/smp.h>
    +#include <asm/msr.h>
    +
    +struct msr_info {
    + u32 msr_no;
    + u32 l, h;
    + int err;
    +};
    +
    +static void __rdmsr_on_cpu(void *info)
    +{
    + struct msr_info *rv = info;
    +
    + rdmsr(rv->msr_no, rv->l, rv->h);
    +}
    +
    +static void __wrmsr_on_cpu(void *info)
    +{
    + struct msr_info *rv = info;
    +
    + wrmsr(rv->msr_no, rv->l, rv->h);
    +}
    +
    +int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
    +{
    + int err;
    + struct msr_info rv;
    +
    + rv.msr_no = msr_no;
    + err = smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 1);
    + *l = rv.l;
    + *h = rv.h;
    +
    + return err;
    +}
    +
    +int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
    +{
    + int err;
    + struct msr_info rv;
    +
    + rv.msr_no = msr_no;
    + rv.l = l;
    + rv.h = h;
    + err = smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 1);
    +
    + return err;
    +}
    +
    +/* rdmsr on a bunch of CPUs
    + *
    + * @mask: which CPUs
    + * @msr_no: which MSR
    + * @msrs: array of MSR values
    + *
    + * Returns:
    + * 0 - success
    + * <0 - read failed on at least one CPU (latter in the mask)
    + */
    +int rdmsr_on_cpus(const cpumask_t *mask, u32 msr_no, struct msr *msrs)
    +{
    + struct msr reg;
    + int cpu, tmp, err = 0;
    + int off = cpumask_first(mask);
    +
    + for_each_cpu(cpu, mask) {
    + reg = msrs[cpu - off];
    +
    + tmp = rdmsr_on_cpu(cpu, msr_no, &reg.l, &reg.h);
    + if (tmp)
    + err = tmp;
    + }
    + return err;
    +}
    +
    +/*
    + * wrmsr of a bunch of CPUs
    + *
    + * @mask: which CPUs
    + * @msr_no: which MSR
    + * @msrs: array of MSR values
    + *
    + * Returns:
    + * 0 - success
    + * <0 - write failed on at least one CPU (latter in the mask)
    + */
    +int wrmsr_on_cpus(const cpumask_t *mask, u32 msr_no, struct msr *msrs)
    +{
    + struct msr reg;
    + int cpu, tmp, err = 0;
    + int off = cpumask_first(mask);
    +
    + for_each_cpu(cpu, mask) {
    + reg = msrs[cpu - off];
    +
    + tmp = wrmsr_on_cpu(cpu, msr_no, reg.l, reg.h);
    + if (tmp)
    + err = tmp;
    + }
    + return err;
    +}
    +
    +/* These "safe" variants are slower and should be used when the target MSR
    + may not actually exist. */
    +static void __rdmsr_safe_on_cpu(void *info)
    +{
    + struct msr_info *rv = info;
    +
    + rv->err = rdmsr_safe(rv->msr_no, &rv->l, &rv->h);
    +}
    +
    +static void __wrmsr_safe_on_cpu(void *info)
    +{
    + struct msr_info *rv = info;
    +
    + rv->err = wrmsr_safe(rv->msr_no, rv->l, rv->h);
    +}
    +
    +int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
    +{
    + int err;
    + struct msr_info rv;
    +
    + rv.msr_no = msr_no;
    + err = smp_call_function_single(cpu, __rdmsr_safe_on_cpu, &rv, 1);
    + *l = rv.l;
    + *h = rv.h;
    +
    + return err ? err : rv.err;
    +}
    +
    +int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
    +{
    + int err;
    + struct msr_info rv;
    +
    + rv.msr_no = msr_no;
    + rv.l = l;
    + rv.h = h;
    + err = smp_call_function_single(cpu, __wrmsr_safe_on_cpu, &rv, 1);
    +
    + return err ? err : rv.err;
    +}
    +
    +EXPORT_SYMBOL(rdmsr_on_cpu);
    +EXPORT_SYMBOL(wrmsr_on_cpu);
    +EXPORT_SYMBOL(rdmsr_on_cpus);
    +EXPORT_SYMBOL(wrmsr_on_cpus);
    +EXPORT_SYMBOL(rdmsr_safe_on_cpu);
    +EXPORT_SYMBOL(wrmsr_safe_on_cpu);
    --
    1.6.2.4

    --
    Regards/Gruss,
    Boris.

    Operating | Advanced Micro Devices GmbH
    System | Karl-Hammerschmidt-Str. 34, 85609 Dornach b. München, Germany
    Research | Geschäftsführer: Thomas M. McCoy, Giuliano Meroni
    Center | Sitz: Dornach, Gemeinde Aschheim, Landkreis München
    (OSRC) | Registergericht München, HRB Nr. 43632
    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2009-05-04 18:49    [W:4.588 / U:0.512 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site