Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
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  * Read an MSR with error handling
0031  *
0032  * @msr: MSR to read
0033  * @m: value to read into
0034  *
0035  * It returns read data only on success, otherwise it doesn't change the output
0036  * argument @m.
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  * Write an MSR with error handling
0053  *
0054  * @msr: MSR to write
0055  * @m: value to write
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  * Set @bit in a MSR @msr.
0092  *
0093  * Retval:
0094  * < 0: An error was encountered.
0095  * = 0: Bit was already set.
0096  * > 0: Hardware accepted the MSR write.
0097  */
0098 int msr_set_bit(u32 msr, u8 bit)
0099 {
0100     return __flip_bit(msr, bit, true);
0101 }
0102 
0103 /**
0104  * Clear @bit in a MSR @msr.
0105  *
0106  * Retval:
0107  * < 0: An error was encountered.
0108  * = 0: Bit was already cleared.
0109  * > 0: Hardware accepted the MSR write.
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