x86, msr: msrs_alloc/free for CONFIG_SMP=n
authorBorislav Petkov <petkovbb@googlemail.com>
Wed, 16 Dec 2009 23:16:25 +0000 (00:16 +0100)
committerH. Peter Anvin <hpa@zytor.com>
Wed, 16 Dec 2009 23:36:32 +0000 (15:36 -0800)
Randy Dunlap reported the following build error:

"When CONFIG_SMP=n, CONFIG_X86_MSR=m:

ERROR: "msrs_free" [drivers/edac/amd64_edac_mod.ko] undefined!
ERROR: "msrs_alloc" [drivers/edac/amd64_edac_mod.ko] undefined!"

This is due to the fact that <arch/x86/lib/msr.c> is conditioned on
CONFIG_SMP and in the UP case we have only the stubs in the header.
Fork off SMP functionality into a new file (msr-smp.c) and build
msrs_{alloc,free} unconditionally.

Reported-by: Randy Dunlap <randy.dunlap@oracle.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Signed-off-by: Borislav Petkov <petkovbb@gmail.com>
LKML-Reference: <20091216231625.GD27228@liondog.tnic>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
arch/x86/include/asm/msr.h
arch/x86/lib/Makefile
arch/x86/lib/msr-smp.c [new file with mode: 0644]
arch/x86/lib/msr.c

index cf985aa..c5bc4c2 100644 (file)
@@ -27,6 +27,18 @@ struct msr {
        };
 };
 
+struct msr_info {
+       u32 msr_no;
+       struct msr reg;
+       struct msr *msrs;
+       int err;
+};
+
+struct msr_regs_info {
+       u32 *regs;
+       int err;
+};
+
 static inline unsigned long long native_read_tscp(unsigned int *aux)
 {
        unsigned long low, high;
index a2d6472..706be8b 100644 (file)
@@ -14,7 +14,7 @@ $(obj)/inat.o: $(obj)/inat-tables.c
 
 clean-files := inat-tables.c
 
-obj-$(CONFIG_SMP) := msr.o
+obj-$(CONFIG_SMP) += msr-smp.o
 
 lib-y := delay.o
 lib-y += thunk_$(BITS).o
@@ -22,7 +22,7 @@ lib-y += usercopy_$(BITS).o getuser.o putuser.o
 lib-y += memcpy_$(BITS).o
 lib-y += insn.o inat.o
 
-obj-y += msr-reg.o msr-reg-export.o
+obj-y += msr.o msr-reg.o msr-reg-export.o
 
 ifeq ($(CONFIG_X86_32),y)
         obj-y += atomic64_32.o
diff --git a/arch/x86/lib/msr-smp.c b/arch/x86/lib/msr-smp.c
new file mode 100644 (file)
index 0000000..a6b1b86
--- /dev/null
@@ -0,0 +1,204 @@
+#include <linux/module.h>
+#include <linux/preempt.h>
+#include <linux/smp.h>
+#include <asm/msr.h>
+
+static void __rdmsr_on_cpu(void *info)
+{
+       struct msr_info *rv = info;
+       struct msr *reg;
+       int this_cpu = raw_smp_processor_id();
+
+       if (rv->msrs)
+               reg = per_cpu_ptr(rv->msrs, this_cpu);
+       else
+               reg = &rv->reg;
+
+       rdmsr(rv->msr_no, reg->l, reg->h);
+}
+
+static void __wrmsr_on_cpu(void *info)
+{
+       struct msr_info *rv = info;
+       struct msr *reg;
+       int this_cpu = raw_smp_processor_id();
+
+       if (rv->msrs)
+               reg = per_cpu_ptr(rv->msrs, this_cpu);
+       else
+               reg = &rv->reg;
+
+       wrmsr(rv->msr_no, reg->l, reg->h);
+}
+
+int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
+{
+       int err;
+       struct msr_info rv;
+
+       memset(&rv, 0, sizeof(rv));
+
+       rv.msr_no = msr_no;
+       err = smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 1);
+       *l = rv.reg.l;
+       *h = rv.reg.h;
+
+       return err;
+}
+EXPORT_SYMBOL(rdmsr_on_cpu);
+
+int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
+{
+       int err;
+       struct msr_info rv;
+
+       memset(&rv, 0, sizeof(rv));
+
+       rv.msr_no = msr_no;
+       rv.reg.l = l;
+       rv.reg.h = h;
+       err = smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 1);
+
+       return err;
+}
+EXPORT_SYMBOL(wrmsr_on_cpu);
+
+static void __rwmsr_on_cpus(const struct cpumask *mask, u32 msr_no,
+                           struct msr *msrs,
+                           void (*msr_func) (void *info))
+{
+       struct msr_info rv;
+       int this_cpu;
+
+       memset(&rv, 0, sizeof(rv));
+
+       rv.msrs   = msrs;
+       rv.msr_no = msr_no;
+
+       this_cpu = get_cpu();
+
+       if (cpumask_test_cpu(this_cpu, mask))
+               msr_func(&rv);
+
+       smp_call_function_many(mask, msr_func, &rv, 1);
+       put_cpu();
+}
+
+/* rdmsr on a bunch of CPUs
+ *
+ * @mask:       which CPUs
+ * @msr_no:     which MSR
+ * @msrs:       array of MSR values
+ *
+ */
+void rdmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs)
+{
+       __rwmsr_on_cpus(mask, msr_no, msrs, __rdmsr_on_cpu);
+}
+EXPORT_SYMBOL(rdmsr_on_cpus);
+
+/*
+ * wrmsr on a bunch of CPUs
+ *
+ * @mask:       which CPUs
+ * @msr_no:     which MSR
+ * @msrs:       array of MSR values
+ *
+ */
+void wrmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs)
+{
+       __rwmsr_on_cpus(mask, msr_no, msrs, __wrmsr_on_cpu);
+}
+EXPORT_SYMBOL(wrmsr_on_cpus);
+
+/* 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->reg.l, &rv->reg.h);
+}
+
+static void __wrmsr_safe_on_cpu(void *info)
+{
+       struct msr_info *rv = info;
+
+       rv->err = wrmsr_safe(rv->msr_no, rv->reg.l, rv->reg.h);
+}
+
+int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
+{
+       int err;
+       struct msr_info rv;
+
+       memset(&rv, 0, sizeof(rv));
+
+       rv.msr_no = msr_no;
+       err = smp_call_function_single(cpu, __rdmsr_safe_on_cpu, &rv, 1);
+       *l = rv.reg.l;
+       *h = rv.reg.h;
+
+       return err ? err : rv.err;
+}
+EXPORT_SYMBOL(rdmsr_safe_on_cpu);
+
+int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
+{
+       int err;
+       struct msr_info rv;
+
+       memset(&rv, 0, sizeof(rv));
+
+       rv.msr_no = msr_no;
+       rv.reg.l = l;
+       rv.reg.h = h;
+       err = smp_call_function_single(cpu, __wrmsr_safe_on_cpu, &rv, 1);
+
+       return err ? err : rv.err;
+}
+EXPORT_SYMBOL(wrmsr_safe_on_cpu);
+
+/*
+ * These variants are significantly slower, but allows control over
+ * the entire 32-bit GPR set.
+ */
+static void __rdmsr_safe_regs_on_cpu(void *info)
+{
+       struct msr_regs_info *rv = info;
+
+       rv->err = rdmsr_safe_regs(rv->regs);
+}
+
+static void __wrmsr_safe_regs_on_cpu(void *info)
+{
+       struct msr_regs_info *rv = info;
+
+       rv->err = wrmsr_safe_regs(rv->regs);
+}
+
+int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 *regs)
+{
+       int err;
+       struct msr_regs_info rv;
+
+       rv.regs   = regs;
+       rv.err    = -EIO;
+       err = smp_call_function_single(cpu, __rdmsr_safe_regs_on_cpu, &rv, 1);
+
+       return err ? err : rv.err;
+}
+EXPORT_SYMBOL(rdmsr_safe_regs_on_cpu);
+
+int wrmsr_safe_regs_on_cpu(unsigned int cpu, u32 *regs)
+{
+       int err;
+       struct msr_regs_info rv;
+
+       rv.regs = regs;
+       rv.err  = -EIO;
+       err = smp_call_function_single(cpu, __wrmsr_safe_regs_on_cpu, &rv, 1);
+
+       return err ? err : rv.err;
+}
+EXPORT_SYMBOL(wrmsr_safe_regs_on_cpu);
index 8728341..8f8eebd 100644 (file)
@@ -1,123 +1,7 @@
 #include <linux/module.h>
 #include <linux/preempt.h>
-#include <linux/smp.h>
 #include <asm/msr.h>
 
-struct msr_info {
-       u32 msr_no;
-       struct msr reg;
-       struct msr *msrs;
-       int err;
-};
-
-static void __rdmsr_on_cpu(void *info)
-{
-       struct msr_info *rv = info;
-       struct msr *reg;
-       int this_cpu = raw_smp_processor_id();
-
-       if (rv->msrs)
-               reg = per_cpu_ptr(rv->msrs, this_cpu);
-       else
-               reg = &rv->reg;
-
-       rdmsr(rv->msr_no, reg->l, reg->h);
-}
-
-static void __wrmsr_on_cpu(void *info)
-{
-       struct msr_info *rv = info;
-       struct msr *reg;
-       int this_cpu = raw_smp_processor_id();
-
-       if (rv->msrs)
-               reg = per_cpu_ptr(rv->msrs, this_cpu);
-       else
-               reg = &rv->reg;
-
-       wrmsr(rv->msr_no, reg->l, reg->h);
-}
-
-int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
-{
-       int err;
-       struct msr_info rv;
-
-       memset(&rv, 0, sizeof(rv));
-
-       rv.msr_no = msr_no;
-       err = smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 1);
-       *l = rv.reg.l;
-       *h = rv.reg.h;
-
-       return err;
-}
-EXPORT_SYMBOL(rdmsr_on_cpu);
-
-int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
-{
-       int err;
-       struct msr_info rv;
-
-       memset(&rv, 0, sizeof(rv));
-
-       rv.msr_no = msr_no;
-       rv.reg.l = l;
-       rv.reg.h = h;
-       err = smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 1);
-
-       return err;
-}
-EXPORT_SYMBOL(wrmsr_on_cpu);
-
-static void __rwmsr_on_cpus(const struct cpumask *mask, u32 msr_no,
-                           struct msr *msrs,
-                           void (*msr_func) (void *info))
-{
-       struct msr_info rv;
-       int this_cpu;
-
-       memset(&rv, 0, sizeof(rv));
-
-       rv.msrs   = msrs;
-       rv.msr_no = msr_no;
-
-       this_cpu = get_cpu();
-
-       if (cpumask_test_cpu(this_cpu, mask))
-               msr_func(&rv);
-
-       smp_call_function_many(mask, msr_func, &rv, 1);
-       put_cpu();
-}
-
-/* rdmsr on a bunch of CPUs
- *
- * @mask:       which CPUs
- * @msr_no:     which MSR
- * @msrs:       array of MSR values
- *
- */
-void rdmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs)
-{
-       __rwmsr_on_cpus(mask, msr_no, msrs, __rdmsr_on_cpu);
-}
-EXPORT_SYMBOL(rdmsr_on_cpus);
-
-/*
- * wrmsr on a bunch of CPUs
- *
- * @mask:       which CPUs
- * @msr_no:     which MSR
- * @msrs:       array of MSR values
- *
- */
-void wrmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs)
-{
-       __rwmsr_on_cpus(mask, msr_no, msrs, __wrmsr_on_cpu);
-}
-EXPORT_SYMBOL(wrmsr_on_cpus);
-
 struct msr *msrs_alloc(void)
 {
        struct msr *msrs = NULL;
@@ -137,100 +21,3 @@ void msrs_free(struct msr *msrs)
        free_percpu(msrs);
 }
 EXPORT_SYMBOL(msrs_free);
-
-/* 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->reg.l, &rv->reg.h);
-}
-
-static void __wrmsr_safe_on_cpu(void *info)
-{
-       struct msr_info *rv = info;
-
-       rv->err = wrmsr_safe(rv->msr_no, rv->reg.l, rv->reg.h);
-}
-
-int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
-{
-       int err;
-       struct msr_info rv;
-
-       memset(&rv, 0, sizeof(rv));
-
-       rv.msr_no = msr_no;
-       err = smp_call_function_single(cpu, __rdmsr_safe_on_cpu, &rv, 1);
-       *l = rv.reg.l;
-       *h = rv.reg.h;
-
-       return err ? err : rv.err;
-}
-EXPORT_SYMBOL(rdmsr_safe_on_cpu);
-
-int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
-{
-       int err;
-       struct msr_info rv;
-
-       memset(&rv, 0, sizeof(rv));
-
-       rv.msr_no = msr_no;
-       rv.reg.l = l;
-       rv.reg.h = h;
-       err = smp_call_function_single(cpu, __wrmsr_safe_on_cpu, &rv, 1);
-
-       return err ? err : rv.err;
-}
-EXPORT_SYMBOL(wrmsr_safe_on_cpu);
-
-/*
- * These variants are significantly slower, but allows control over
- * the entire 32-bit GPR set.
- */
-struct msr_regs_info {
-       u32 *regs;
-       int err;
-};
-
-static void __rdmsr_safe_regs_on_cpu(void *info)
-{
-       struct msr_regs_info *rv = info;
-
-       rv->err = rdmsr_safe_regs(rv->regs);
-}
-
-static void __wrmsr_safe_regs_on_cpu(void *info)
-{
-       struct msr_regs_info *rv = info;
-
-       rv->err = wrmsr_safe_regs(rv->regs);
-}
-
-int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 *regs)
-{
-       int err;
-       struct msr_regs_info rv;
-
-       rv.regs   = regs;
-       rv.err    = -EIO;
-       err = smp_call_function_single(cpu, __rdmsr_safe_regs_on_cpu, &rv, 1);
-
-       return err ? err : rv.err;
-}
-EXPORT_SYMBOL(rdmsr_safe_regs_on_cpu);
-
-int wrmsr_safe_regs_on_cpu(unsigned int cpu, u32 *regs)
-{
-       int err;
-       struct msr_regs_info rv;
-
-       rv.regs = regs;
-       rv.err  = -EIO;
-       err = smp_call_function_single(cpu, __wrmsr_safe_regs_on_cpu, &rv, 1);
-
-       return err ? err : rv.err;
-}
-EXPORT_SYMBOL(wrmsr_safe_regs_on_cpu);