diff options
| -rw-r--r-- | arch/x86/include/asm/msr.h | 18 | ||||
| -rw-r--r-- | arch/x86/lib/msr.c | 49 |
2 files changed, 63 insertions, 4 deletions
diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h index 943fdd572e16..8e56712aa176 100644 --- a/arch/x86/include/asm/msr.h +++ b/arch/x86/include/asm/msr.h | |||
| @@ -97,8 +97,8 @@ notrace static inline int native_write_msr_safe(unsigned int msr, | |||
| 97 | 97 | ||
| 98 | extern unsigned long long native_read_tsc(void); | 98 | extern unsigned long long native_read_tsc(void); |
| 99 | 99 | ||
| 100 | extern int native_rdmsr_safe_regs(u32 *regs); | 100 | extern int native_rdmsr_safe_regs(u32 regs[8]); |
| 101 | extern int native_wrmsr_safe_regs(u32 *regs); | 101 | extern int native_wrmsr_safe_regs(u32 regs[8]); |
| 102 | 102 | ||
| 103 | static __always_inline unsigned long long __native_read_tsc(void) | 103 | static __always_inline unsigned long long __native_read_tsc(void) |
| 104 | { | 104 | { |
| @@ -196,12 +196,12 @@ static inline int wrmsrl_amd_safe(unsigned msr, unsigned long long val) | |||
| 196 | return native_wrmsr_safe_regs(gprs); | 196 | return native_wrmsr_safe_regs(gprs); |
| 197 | } | 197 | } |
| 198 | 198 | ||
| 199 | static inline int rdmsr_safe_regs(u32 *regs) | 199 | static inline int rdmsr_safe_regs(u32 regs[8]) |
| 200 | { | 200 | { |
| 201 | return native_rdmsr_safe_regs(regs); | 201 | return native_rdmsr_safe_regs(regs); |
| 202 | } | 202 | } |
| 203 | 203 | ||
| 204 | static inline int wrmsr_safe_regs(u32 *regs) | 204 | static inline int wrmsr_safe_regs(u32 regs[8]) |
| 205 | { | 205 | { |
| 206 | return native_wrmsr_safe_regs(regs); | 206 | return native_wrmsr_safe_regs(regs); |
| 207 | } | 207 | } |
| @@ -245,6 +245,8 @@ void rdmsr_on_cpus(const cpumask_t *mask, u32 msr_no, struct msr *msrs); | |||
| 245 | void wrmsr_on_cpus(const cpumask_t *mask, u32 msr_no, struct msr *msrs); | 245 | void wrmsr_on_cpus(const cpumask_t *mask, u32 msr_no, struct msr *msrs); |
| 246 | int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); | 246 | int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); |
| 247 | int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); | 247 | int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); |
| 248 | int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]); | ||
| 249 | int wrmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]); | ||
| 248 | #else /* CONFIG_SMP */ | 250 | #else /* CONFIG_SMP */ |
| 249 | static inline int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) | 251 | static inline int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) |
| 250 | { | 252 | { |
| @@ -275,6 +277,14 @@ static inline int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) | |||
| 275 | { | 277 | { |
| 276 | return wrmsr_safe(msr_no, l, h); | 278 | return wrmsr_safe(msr_no, l, h); |
| 277 | } | 279 | } |
| 280 | static inline int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]) | ||
| 281 | { | ||
| 282 | return rdmsr_safe_regs(regs); | ||
| 283 | } | ||
| 284 | static inline int wrmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]) | ||
| 285 | { | ||
| 286 | return wrmsr_safe_regs(regs); | ||
| 287 | } | ||
| 278 | #endif /* CONFIG_SMP */ | 288 | #endif /* CONFIG_SMP */ |
| 279 | #endif /* __ASSEMBLY__ */ | 289 | #endif /* __ASSEMBLY__ */ |
| 280 | #endif /* __KERNEL__ */ | 290 | #endif /* __KERNEL__ */ |
diff --git a/arch/x86/lib/msr.c b/arch/x86/lib/msr.c index caa24aca8115..33a1e3ca22d8 100644 --- a/arch/x86/lib/msr.c +++ b/arch/x86/lib/msr.c | |||
| @@ -175,3 +175,52 @@ int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) | |||
| 175 | return err ? err : rv.err; | 175 | return err ? err : rv.err; |
| 176 | } | 176 | } |
| 177 | EXPORT_SYMBOL(wrmsr_safe_on_cpu); | 177 | EXPORT_SYMBOL(wrmsr_safe_on_cpu); |
| 178 | |||
| 179 | /* | ||
| 180 | * These variants are significantly slower, but allows control over | ||
| 181 | * the entire 32-bit GPR set. | ||
| 182 | */ | ||
| 183 | struct msr_regs_info { | ||
| 184 | u32 *regs; | ||
| 185 | int err; | ||
| 186 | }; | ||
| 187 | |||
| 188 | static void __rdmsr_safe_regs_on_cpu(void *info) | ||
| 189 | { | ||
| 190 | struct msr_regs_info *rv = info; | ||
| 191 | |||
| 192 | rv->err = rdmsr_safe_regs(rv->regs); | ||
| 193 | } | ||
| 194 | |||
| 195 | static void __wrmsr_safe_regs_on_cpu(void *info) | ||
| 196 | { | ||
| 197 | struct msr_regs_info *rv = info; | ||
| 198 | |||
| 199 | rv->err = wrmsr_safe_regs(rv->regs); | ||
| 200 | } | ||
| 201 | |||
| 202 | int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 *regs) | ||
| 203 | { | ||
| 204 | int err; | ||
| 205 | struct msr_regs_info rv; | ||
| 206 | |||
| 207 | rv.regs = regs; | ||
| 208 | rv.err = -EIO; | ||
| 209 | err = smp_call_function_single(cpu, __rdmsr_safe_regs_on_cpu, &rv, 1); | ||
| 210 | |||
| 211 | return err ? err : rv.err; | ||
| 212 | } | ||
| 213 | EXPORT_SYMBOL(rdmsr_safe_regs_on_cpu); | ||
| 214 | |||
| 215 | int wrmsr_safe_regs_on_cpu(unsigned int cpu, u32 *regs) | ||
| 216 | { | ||
| 217 | int err; | ||
| 218 | struct msr_regs_info rv; | ||
| 219 | |||
| 220 | rv.regs = regs; | ||
| 221 | rv.err = -EIO; | ||
| 222 | err = smp_call_function_single(cpu, __wrmsr_safe_regs_on_cpu, &rv, 1); | ||
| 223 | |||
| 224 | return err ? err : rv.err; | ||
| 225 | } | ||
| 226 | EXPORT_SYMBOL(wrmsr_safe_regs_on_cpu); | ||
