0001
0002 #include <linux/export.h>
0003 #include <linux/percpu.h>
0004 #include <linux/preempt.h>
0005 #include <asm/msr.h>
0006 #define CREATE_TRACE_POINTS
0007 #include <asm/msr-trace.h>
0008
0009 struct msr *msrs_alloc(void)
0010 {
0011 struct msr *msrs = NULL;
0012
0013 msrs = alloc_percpu(struct msr);
0014 if (!msrs) {
0015 pr_warn("%s: error allocating msrs\n", __func__);
0016 return NULL;
0017 }
0018
0019 return msrs;
0020 }
0021 EXPORT_SYMBOL(msrs_alloc);
0022
0023 void msrs_free(struct msr *msrs)
0024 {
0025 free_percpu(msrs);
0026 }
0027 EXPORT_SYMBOL(msrs_free);
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 static int msr_read(u32 msr, struct msr *m)
0040 {
0041 int err;
0042 u64 val;
0043
0044 err = rdmsrl_safe(msr, &val);
0045 if (!err)
0046 m->q = val;
0047
0048 return err;
0049 }
0050
0051
0052
0053
0054
0055
0056
0057 static int msr_write(u32 msr, struct msr *m)
0058 {
0059 return wrmsrl_safe(msr, m->q);
0060 }
0061
0062 static inline int __flip_bit(u32 msr, u8 bit, bool set)
0063 {
0064 struct msr m, m1;
0065 int err = -EINVAL;
0066
0067 if (bit > 63)
0068 return err;
0069
0070 err = msr_read(msr, &m);
0071 if (err)
0072 return err;
0073
0074 m1 = m;
0075 if (set)
0076 m1.q |= BIT_64(bit);
0077 else
0078 m1.q &= ~BIT_64(bit);
0079
0080 if (m1.q == m.q)
0081 return 0;
0082
0083 err = msr_write(msr, &m1);
0084 if (err)
0085 return err;
0086
0087 return 1;
0088 }
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098 int msr_set_bit(u32 msr, u8 bit)
0099 {
0100 return __flip_bit(msr, bit, true);
0101 }
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111 int msr_clear_bit(u32 msr, u8 bit)
0112 {
0113 return __flip_bit(msr, bit, false);
0114 }
0115
0116 #ifdef CONFIG_TRACEPOINTS
0117 void do_trace_write_msr(unsigned int msr, u64 val, int failed)
0118 {
0119 trace_write_msr(msr, val, failed);
0120 }
0121 EXPORT_SYMBOL(do_trace_write_msr);
0122 EXPORT_TRACEPOINT_SYMBOL(write_msr);
0123
0124 void do_trace_read_msr(unsigned int msr, u64 val, int failed)
0125 {
0126 trace_read_msr(msr, val, failed);
0127 }
0128 EXPORT_SYMBOL(do_trace_read_msr);
0129 EXPORT_TRACEPOINT_SYMBOL(read_msr);
0130
0131 void do_trace_rdpmc(unsigned counter, u64 val, int failed)
0132 {
0133 trace_rdpmc(counter, val, failed);
0134 }
0135 EXPORT_SYMBOL(do_trace_rdpmc);
0136 EXPORT_TRACEPOINT_SYMBOL(rdpmc);
0137
0138 #endif