-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
yaml --- r: 178051 b: refs/heads/master c: 6ede31e h: refs/heads/master i: 178049: 0df3d7a 178047: cffdf18 v: v3
- Loading branch information
Borislav Petkov
authored and
H. Peter Anvin
committed
Dec 16, 2009
1 parent
47b292d
commit 13cbeb8
Showing
5 changed files
with
219 additions
and
216 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
--- | ||
refs/heads/master: 9d260ebc09a0ad6b5c73e17676df42c7bc75ff64 | ||
refs/heads/master: 6ede31e03084ee084bcee073ef3d1136f68d0906 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); |
Oops, something went wrong.