File Index
Files and directories
Sign in
FILE

msr.c

File preview with syntax highlighting.

linux-6.19.14/arch/x86/lib/msr.c 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.