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