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