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