blob: 872834177937231b5ff9c55965e77929b0d55b98 [file] [log] [blame]
Alexey Dobriyanb077ffb2007-02-16 01:48:11 -08001#include <linux/module.h>
2#include <linux/preempt.h>
3#include <linux/smp.h>
4#include <asm/msr.h>
5
Alexey Dobriyanb077ffb2007-02-16 01:48:11 -08006struct msr_info {
7 u32 msr_no;
Borislav Petkov6bc10962009-05-22 12:12:01 +02008 struct msr reg;
Borislav Petkovb034c192009-05-22 13:52:19 +02009 struct msr *msrs;
Rudolf Marek4e9baad2007-05-08 17:22:01 +020010 int err;
Alexey Dobriyanb077ffb2007-02-16 01:48:11 -080011};
12
13static void __rdmsr_on_cpu(void *info)
14{
15 struct msr_info *rv = info;
Borislav Petkovb034c192009-05-22 13:52:19 +020016 struct msr *reg;
17 int this_cpu = raw_smp_processor_id();
Alexey Dobriyanb077ffb2007-02-16 01:48:11 -080018
Borislav Petkovb034c192009-05-22 13:52:19 +020019 if (rv->msrs)
Borislav Petkov50542252009-12-11 18:14:40 +010020 reg = per_cpu_ptr(rv->msrs, this_cpu);
Borislav Petkovb034c192009-05-22 13:52:19 +020021 else
22 reg = &rv->reg;
23
24 rdmsr(rv->msr_no, reg->l, reg->h);
Alexey Dobriyanb077ffb2007-02-16 01:48:11 -080025}
26
H. Peter Anvinbdd31462008-08-25 17:44:03 -070027static void __wrmsr_on_cpu(void *info)
Alexey Dobriyanb077ffb2007-02-16 01:48:11 -080028{
Rudolf Marek4e9baad2007-05-08 17:22:01 +020029 struct msr_info *rv = info;
Borislav Petkovb034c192009-05-22 13:52:19 +020030 struct msr *reg;
31 int this_cpu = raw_smp_processor_id();
Rudolf Marek4e9baad2007-05-08 17:22:01 +020032
Borislav Petkovb034c192009-05-22 13:52:19 +020033 if (rv->msrs)
Borislav Petkov50542252009-12-11 18:14:40 +010034 reg = per_cpu_ptr(rv->msrs, this_cpu);
Borislav Petkovb034c192009-05-22 13:52:19 +020035 else
36 reg = &rv->reg;
37
38 wrmsr(rv->msr_no, reg->l, reg->h);
Rudolf Marek4e9baad2007-05-08 17:22:01 +020039}
40
H. Peter Anvinbdd31462008-08-25 17:44:03 -070041int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
Rudolf Marek4e9baad2007-05-08 17:22:01 +020042{
H. Peter Anvinbdd31462008-08-25 17:44:03 -070043 int err;
Avi Kivity5f1f9352007-10-17 18:04:38 +020044 struct msr_info rv;
Alexey Dobriyanb077ffb2007-02-16 01:48:11 -080045
Borislav Petkovb034c192009-05-22 13:52:19 +020046 memset(&rv, 0, sizeof(rv));
47
Avi Kivity5f1f9352007-10-17 18:04:38 +020048 rv.msr_no = msr_no;
H. Peter Anvinbdd31462008-08-25 17:44:03 -070049 err = smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 1);
Borislav Petkov6bc10962009-05-22 12:12:01 +020050 *l = rv.reg.l;
51 *h = rv.reg.h;
Avi Kivity5f1f9352007-10-17 18:04:38 +020052
Rudolf Marek4e9baad2007-05-08 17:22:01 +020053 return err;
Alexey Dobriyanb077ffb2007-02-16 01:48:11 -080054}
Borislav Petkovb034c192009-05-22 13:52:19 +020055EXPORT_SYMBOL(rdmsr_on_cpu);
Alexey Dobriyanb077ffb2007-02-16 01:48:11 -080056
H. Peter Anvinbdd31462008-08-25 17:44:03 -070057int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
58{
59 int err;
60 struct msr_info rv;
61
Borislav Petkovb034c192009-05-22 13:52:19 +020062 memset(&rv, 0, sizeof(rv));
63
H. Peter Anvinbdd31462008-08-25 17:44:03 -070064 rv.msr_no = msr_no;
Borislav Petkov6bc10962009-05-22 12:12:01 +020065 rv.reg.l = l;
66 rv.reg.h = h;
H. Peter Anvinbdd31462008-08-25 17:44:03 -070067 err = smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 1);
68
69 return err;
70}
Borislav Petkovb034c192009-05-22 13:52:19 +020071EXPORT_SYMBOL(wrmsr_on_cpu);
72
Borislav Petkovb8a47542009-07-30 11:10:02 +020073static void __rwmsr_on_cpus(const struct cpumask *mask, u32 msr_no,
74 struct msr *msrs,
75 void (*msr_func) (void *info))
Borislav Petkovb034c192009-05-22 13:52:19 +020076{
77 struct msr_info rv;
78 int this_cpu;
79
80 memset(&rv, 0, sizeof(rv));
81
Borislav Petkovb034c192009-05-22 13:52:19 +020082 rv.msrs = msrs;
83 rv.msr_no = msr_no;
84
Borislav Petkovbab9a3d2009-07-30 11:10:01 +020085 this_cpu = get_cpu();
86
87 if (cpumask_test_cpu(this_cpu, mask))
Borislav Petkovb8a47542009-07-30 11:10:02 +020088 msr_func(&rv);
Borislav Petkovb034c192009-05-22 13:52:19 +020089
Borislav Petkovb8a47542009-07-30 11:10:02 +020090 smp_call_function_many(mask, msr_func, &rv, 1);
Borislav Petkovbab9a3d2009-07-30 11:10:01 +020091 put_cpu();
Borislav Petkovb034c192009-05-22 13:52:19 +020092}
Borislav Petkovb8a47542009-07-30 11:10:02 +020093
94/* rdmsr on a bunch of CPUs
95 *
96 * @mask: which CPUs
97 * @msr_no: which MSR
98 * @msrs: array of MSR values
99 *
100 */
101void rdmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs)
102{
103 __rwmsr_on_cpus(mask, msr_no, msrs, __rdmsr_on_cpu);
104}
Borislav Petkovb034c192009-05-22 13:52:19 +0200105EXPORT_SYMBOL(rdmsr_on_cpus);
106
107/*
108 * wrmsr on a bunch of CPUs
109 *
110 * @mask: which CPUs
111 * @msr_no: which MSR
112 * @msrs: array of MSR values
113 *
114 */
Borislav Petkovb8a47542009-07-30 11:10:02 +0200115void wrmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs)
Borislav Petkovb034c192009-05-22 13:52:19 +0200116{
Borislav Petkovb8a47542009-07-30 11:10:02 +0200117 __rwmsr_on_cpus(mask, msr_no, msrs, __wrmsr_on_cpu);
Borislav Petkovb034c192009-05-22 13:52:19 +0200118}
119EXPORT_SYMBOL(wrmsr_on_cpus);
H. Peter Anvinbdd31462008-08-25 17:44:03 -0700120
Borislav Petkov50542252009-12-11 18:14:40 +0100121struct msr *msrs_alloc(void)
122{
123 struct msr *msrs = NULL;
124
125 msrs = alloc_percpu(struct msr);
126 if (!msrs) {
127 pr_warning("%s: error allocating msrs\n", __func__);
128 return NULL;
129 }
130
131 return msrs;
132}
133EXPORT_SYMBOL(msrs_alloc);
134
135void msrs_free(struct msr *msrs)
136{
137 free_percpu(msrs);
138}
139EXPORT_SYMBOL(msrs_free);
140
H. Peter Anvinbdd31462008-08-25 17:44:03 -0700141/* These "safe" variants are slower and should be used when the target MSR
142 may not actually exist. */
143static void __rdmsr_safe_on_cpu(void *info)
Alexey Dobriyanb077ffb2007-02-16 01:48:11 -0800144{
145 struct msr_info *rv = info;
146
Borislav Petkov6bc10962009-05-22 12:12:01 +0200147 rv->err = rdmsr_safe(rv->msr_no, &rv->reg.l, &rv->reg.h);
Alexey Dobriyanb077ffb2007-02-16 01:48:11 -0800148}
149
Rudolf Marek4e9baad2007-05-08 17:22:01 +0200150static void __wrmsr_safe_on_cpu(void *info)
Alexey Dobriyanb077ffb2007-02-16 01:48:11 -0800151{
Rudolf Marek4e9baad2007-05-08 17:22:01 +0200152 struct msr_info *rv = info;
153
Borislav Petkov6bc10962009-05-22 12:12:01 +0200154 rv->err = wrmsr_safe(rv->msr_no, rv->reg.l, rv->reg.h);
Rudolf Marek4e9baad2007-05-08 17:22:01 +0200155}
156
H. Peter Anvinbdd31462008-08-25 17:44:03 -0700157int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
Rudolf Marek4e9baad2007-05-08 17:22:01 +0200158{
H. Peter Anvinbdd31462008-08-25 17:44:03 -0700159 int err;
160 struct msr_info rv;
161
Borislav Petkovb034c192009-05-22 13:52:19 +0200162 memset(&rv, 0, sizeof(rv));
163
H. Peter Anvinbdd31462008-08-25 17:44:03 -0700164 rv.msr_no = msr_no;
165 err = smp_call_function_single(cpu, __rdmsr_safe_on_cpu, &rv, 1);
Borislav Petkov6bc10962009-05-22 12:12:01 +0200166 *l = rv.reg.l;
167 *h = rv.reg.h;
H. Peter Anvinbdd31462008-08-25 17:44:03 -0700168
169 return err ? err : rv.err;
170}
Borislav Petkovb034c192009-05-22 13:52:19 +0200171EXPORT_SYMBOL(rdmsr_safe_on_cpu);
H. Peter Anvinbdd31462008-08-25 17:44:03 -0700172
173int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
174{
175 int err;
Avi Kivity5f1f9352007-10-17 18:04:38 +0200176 struct msr_info rv;
Alexey Dobriyanb077ffb2007-02-16 01:48:11 -0800177
Borislav Petkovb034c192009-05-22 13:52:19 +0200178 memset(&rv, 0, sizeof(rv));
179
Avi Kivity5f1f9352007-10-17 18:04:38 +0200180 rv.msr_no = msr_no;
Borislav Petkov6bc10962009-05-22 12:12:01 +0200181 rv.reg.l = l;
182 rv.reg.h = h;
H. Peter Anvinbdd31462008-08-25 17:44:03 -0700183 err = smp_call_function_single(cpu, __wrmsr_safe_on_cpu, &rv, 1);
Avi Kivity5f1f9352007-10-17 18:04:38 +0200184
H. Peter Anvinbdd31462008-08-25 17:44:03 -0700185 return err ? err : rv.err;
Alexey Dobriyanb077ffb2007-02-16 01:48:11 -0800186}
Rudolf Marek4e9baad2007-05-08 17:22:01 +0200187EXPORT_SYMBOL(wrmsr_safe_on_cpu);
H. Peter Anvin8b956bf2009-08-31 14:13:48 -0700188
189/*
190 * These variants are significantly slower, but allows control over
191 * the entire 32-bit GPR set.
192 */
193struct msr_regs_info {
194 u32 *regs;
195 int err;
196};
197
198static void __rdmsr_safe_regs_on_cpu(void *info)
199{
200 struct msr_regs_info *rv = info;
201
202 rv->err = rdmsr_safe_regs(rv->regs);
203}
204
205static void __wrmsr_safe_regs_on_cpu(void *info)
206{
207 struct msr_regs_info *rv = info;
208
209 rv->err = wrmsr_safe_regs(rv->regs);
210}
211
212int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 *regs)
213{
214 int err;
215 struct msr_regs_info rv;
216
217 rv.regs = regs;
218 rv.err = -EIO;
219 err = smp_call_function_single(cpu, __rdmsr_safe_regs_on_cpu, &rv, 1);
220
221 return err ? err : rv.err;
222}
223EXPORT_SYMBOL(rdmsr_safe_regs_on_cpu);
224
225int wrmsr_safe_regs_on_cpu(unsigned int cpu, u32 *regs)
226{
227 int err;
228 struct msr_regs_info rv;
229
230 rv.regs = regs;
231 rv.err = -EIO;
232 err = smp_call_function_single(cpu, __wrmsr_safe_regs_on_cpu, &rv, 1);
233
234 return err ? err : rv.err;
235}
236EXPORT_SYMBOL(wrmsr_safe_regs_on_cpu);