1#include <linux/module.h> 2#include <linux/preempt.h> 3#include <linux/smp.h> 4#include <asm/msr.h> 5 6struct msr_info { 7 u32 msr_no; 8 u32 l, h; 9 int err; 10}; 11 12static void __rdmsr_on_cpu(void *info) 13{ 14 struct msr_info *rv = info; 15 16 rdmsr(rv->msr_no, rv->l, rv->h); 17} 18 19static void __rdmsr_safe_on_cpu(void *info) 20{ 21 struct msr_info *rv = info; 22 23 rv->err = rdmsr_safe(rv->msr_no, &rv->l, &rv->h); 24} 25 26static int _rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h, int safe) 27{ 28 int err = 0; 29 preempt_disable(); 30 if (smp_processor_id() == cpu) 31 if (safe) 32 err = rdmsr_safe(msr_no, l, h); 33 else 34 rdmsr(msr_no, *l, *h); 35 else { 36 struct msr_info rv; 37 38 rv.msr_no = msr_no; 39 if (safe) { 40 smp_call_function_single(cpu, __rdmsr_safe_on_cpu, 41 &rv, 0, 1); 42 err = rv.err; 43 } else { 44 smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 0, 1); 45 } 46 *l = rv.l; 47 *h = rv.h; 48 } 49 preempt_enable(); 50 return err; 51} 52 53static void __wrmsr_on_cpu(void *info) 54{ 55 struct msr_info *rv = info; 56 57 wrmsr(rv->msr_no, rv->l, rv->h); 58} 59 60static void __wrmsr_safe_on_cpu(void *info) 61{ 62 struct msr_info *rv = info; 63 64 rv->err = wrmsr_safe(rv->msr_no, rv->l, rv->h); 65} 66 67static int _wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h, int safe) 68{ 69 int err = 0; 70 preempt_disable(); 71 if (smp_processor_id() == cpu) 72 if (safe) 73 err = wrmsr_safe(msr_no, l, h); 74 else 75 wrmsr(msr_no, l, h); 76 else { 77 struct msr_info rv; 78 79 rv.msr_no = msr_no; 80 rv.l = l; 81 rv.h = h; 82 if (safe) { 83 smp_call_function_single(cpu, __wrmsr_safe_on_cpu, 84 &rv, 0, 1); 85 err = rv.err; 86 } else { 87 smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 0, 1); 88 } 89 } 90 preempt_enable(); 91 return err; 92} 93 94void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) 95{ 96 _wrmsr_on_cpu(cpu, msr_no, l, h, 0); 97} 98 99void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) 100{ 101 _rdmsr_on_cpu(cpu, msr_no, l, h, 0); 102} 103 104/* These "safe" variants are slower and should be used when the target MSR 105 may not actually exist. */ 106int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) 107{ 108 return _wrmsr_on_cpu(cpu, msr_no, l, h, 1); 109} 110 111int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) 112{ 113 return _rdmsr_on_cpu(cpu, msr_no, l, h, 1); 114} 115 116EXPORT_SYMBOL(rdmsr_on_cpu); 117EXPORT_SYMBOL(wrmsr_on_cpu); 118EXPORT_SYMBOL(rdmsr_safe_on_cpu); 119EXPORT_SYMBOL(wrmsr_safe_on_cpu); 120