1#include <linux/module.h> 2#include <linux/preempt.h> 3#include <asm/msr.h> 4 5struct msr *msrs_alloc(void) 6{ 7 struct msr *msrs = NULL; 8 9 msrs = alloc_percpu(struct msr); 10 if (!msrs) { 11 pr_warn("%s: error allocating msrs\n", __func__); 12 return NULL; 13 } 14 15 return msrs; 16} 17EXPORT_SYMBOL(msrs_alloc); 18 19void msrs_free(struct msr *msrs) 20{ 21 free_percpu(msrs); 22} 23EXPORT_SYMBOL(msrs_free); 24 25/** 26 * Read an MSR with error handling 27 * 28 * @msr: MSR to read 29 * @m: value to read into 30 * 31 * It returns read data only on success, otherwise it doesn't change the output 32 * argument @m. 33 * 34 */ 35int msr_read(u32 msr, struct msr *m) 36{ 37 int err; 38 u64 val; 39 40 err = rdmsrl_safe(msr, &val); 41 if (!err) 42 m->q = val; 43 44 return err; 45} 46 47/** 48 * Write an MSR with error handling 49 * 50 * @msr: MSR to write 51 * @m: value to write 52 */ 53int msr_write(u32 msr, struct msr *m) 54{ 55 return wrmsrl_safe(msr, m->q); 56} 57 58static inline int __flip_bit(u32 msr, u8 bit, bool set) 59{ 60 struct msr m, m1; 61 int err = -EINVAL; 62 63 if (bit > 63) 64 return err; 65 66 err = msr_read(msr, &m); 67 if (err) 68 return err; 69 70 m1 = m; 71 if (set) 72 m1.q |= BIT_64(bit); 73 else 74 m1.q &= ~BIT_64(bit); 75 76 if (m1.q == m.q) 77 return 0; 78 79 err = msr_write(msr, &m1); 80 if (err) 81 return err; 82 83 return 1; 84} 85 86/** 87 * Set @bit in a MSR @msr. 88 * 89 * Retval: 90 * < 0: An error was encountered. 91 * = 0: Bit was already set. 92 * > 0: Hardware accepted the MSR write. 93 */ 94int msr_set_bit(u32 msr, u8 bit) 95{ 96 return __flip_bit(msr, bit, true); 97} 98 99/** 100 * Clear @bit in a MSR @msr. 101 * 102 * Retval: 103 * < 0: An error was encountered. 104 * = 0: Bit was already cleared. 105 * > 0: Hardware accepted the MSR write. 106 */ 107int msr_clear_bit(u32 msr, u8 bit) 108{ 109 return __flip_bit(msr, bit, false); 110} 111