msr.h 5.6 KB
Newer Older
T
Thomas Gleixner 已提交
1 2 3 4 5
#ifndef __ASM_X86_MSR_H_
#define __ASM_X86_MSR_H_

#include <asm/msr-index.h>

6 7 8 9
#ifndef __ASSEMBLY__
# include <linux/types.h>
#endif

10 11
#ifdef __KERNEL__
#ifndef __ASSEMBLY__
12 13 14 15

#include <asm/asm.h>
#include <asm/errno.h>

A
Andrew Morton 已提交
16
static inline unsigned long long native_read_tscp(unsigned int *aux)
17 18 19 20 21 22 23
{
	unsigned long low, high;
	asm volatile (".byte 0x0f,0x01,0xf9"
		      : "=a" (low), "=d" (high), "=c" (*aux));
	return low | ((u64)high >> 32);
}

24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
/*
 * i386 calling convention returns 64-bit value in edx:eax, while
 * x86_64 returns at rax. Also, the "A" constraint does not really
 * mean rdx:rax in x86_64, so we need specialized behaviour for each
 * architecture
 */
#ifdef CONFIG_X86_64
#define DECLARE_ARGS(val, low, high)	unsigned low, high
#define EAX_EDX_VAL(val, low, high)	(low | ((u64)(high) << 32))
#define EAX_EDX_ARGS(val, low, high)	"a" (low), "d" (high)
#define EAX_EDX_RET(val, low, high)	"=a" (low), "=d" (high)
#else
#define DECLARE_ARGS(val, low, high)	unsigned long long val
#define EAX_EDX_VAL(val, low, high)	(val)
#define EAX_EDX_ARGS(val, low, high)	"A" (val)
#define EAX_EDX_RET(val, low, high)	"=A" (val)
40 41
#endif

T
Thomas Gleixner 已提交
42 43
static inline unsigned long long native_read_msr(unsigned int msr)
{
44
	DECLARE_ARGS(val, low, high);
T
Thomas Gleixner 已提交
45

46 47
	asm volatile("rdmsr" : EAX_EDX_RET(val, low, high) : "c" (msr));
	return EAX_EDX_VAL(val, low, high);
T
Thomas Gleixner 已提交
48 49 50 51 52
}

static inline unsigned long long native_read_msr_safe(unsigned int msr,
						      int *err)
{
53
	DECLARE_ARGS(val, low, high);
T
Thomas Gleixner 已提交
54

55
	asm volatile("2: rdmsr ; xor %0,%0\n"
T
Thomas Gleixner 已提交
56 57
		     "1:\n\t"
		     ".section .fixup,\"ax\"\n\t"
58
		     "3:  mov %3,%0 ; jmp 1b\n\t"
T
Thomas Gleixner 已提交
59 60
		     ".previous\n\t"
		     ".section __ex_table,\"a\"\n"
61 62
		     _ASM_ALIGN "\n\t"
		     _ASM_PTR " 2b,3b\n\t"
T
Thomas Gleixner 已提交
63
		     ".previous"
64
		     : "=r" (*err), EAX_EDX_RET(val, low, high)
T
Thomas Gleixner 已提交
65
		     : "c" (msr), "i" (-EFAULT));
66
	return EAX_EDX_VAL(val, low, high);
T
Thomas Gleixner 已提交
67 68
}

69 70
static inline void native_write_msr(unsigned int msr,
				    unsigned low, unsigned high)
T
Thomas Gleixner 已提交
71
{
72
	asm volatile("wrmsr" : : "c" (msr), "a"(low), "d" (high));
T
Thomas Gleixner 已提交
73 74 75
}

static inline int native_write_msr_safe(unsigned int msr,
76
					unsigned low, unsigned high)
T
Thomas Gleixner 已提交
77 78
{
	int err;
79
	asm volatile("2: wrmsr ; xor %0,%0\n"
T
Thomas Gleixner 已提交
80 81
		     "1:\n\t"
		     ".section .fixup,\"ax\"\n\t"
82
		     "3:  mov %4,%0 ; jmp 1b\n\t"
T
Thomas Gleixner 已提交
83 84
		     ".previous\n\t"
		     ".section __ex_table,\"a\"\n"
85 86
		     _ASM_ALIGN "\n\t"
		     _ASM_PTR " 2b,3b\n\t"
T
Thomas Gleixner 已提交
87 88
		     ".previous"
		     : "=a" (err)
89
		     : "c" (msr), "0" (low), "d" (high),
T
Thomas Gleixner 已提交
90 91 92 93 94 95
		       "i" (-EFAULT));
	return err;
}

static inline unsigned long long native_read_tsc(void)
{
96 97 98 99
	DECLARE_ARGS(val, low, high);

	asm volatile("rdtsc" : EAX_EDX_RET(val, low, high));
	return EAX_EDX_VAL(val, low, high);
T
Thomas Gleixner 已提交
100 101
}

102
static inline unsigned long long native_read_pmc(int counter)
T
Thomas Gleixner 已提交
103
{
104 105 106 107
	DECLARE_ARGS(val, low, high);

	asm volatile("rdpmc" : EAX_EDX_RET(val, low, high) : "c" (counter));
	return EAX_EDX_VAL(val, low, high);
T
Thomas Gleixner 已提交
108 109 110 111
}

#ifdef CONFIG_PARAVIRT
#include <asm/paravirt.h>
112
#else
T
Thomas Gleixner 已提交
113 114 115 116 117 118 119 120 121 122 123 124 125 126
#include <linux/errno.h>
/*
 * Access to machine-specific registers (available on 586 and better only)
 * Note: the rd* operations modify the parameters directly (without using
 * pointer indirection), this allows gcc to optimize better
 */

#define rdmsr(msr,val1,val2)						\
	do {								\
		u64 __val = native_read_msr(msr);			\
		(val1) = (u32)__val;					\
		(val2) = (u32)(__val >> 32);				\
	} while(0)

127
static inline void wrmsr(unsigned msr, unsigned low, unsigned high)
T
Thomas Gleixner 已提交
128
{
129
	native_write_msr(msr, low, high);
T
Thomas Gleixner 已提交
130 131 132 133 134
}

#define rdmsrl(msr,val)							\
	((val) = native_read_msr(msr))

135 136
#define wrmsrl(msr, val)						\
	native_write_msr(msr, (u32)((u64)(val)), (u32)((u64)(val) >> 32))
T
Thomas Gleixner 已提交
137 138

/* wrmsr with exception handling */
139
static inline int wrmsr_safe(unsigned msr, unsigned low, unsigned high)
T
Thomas Gleixner 已提交
140
{
141
	return native_write_msr_safe(msr, low, high);
T
Thomas Gleixner 已提交
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
}

/* rdmsr with exception handling */
#define rdmsr_safe(msr,p1,p2)						\
	({								\
		int __err;						\
		u64 __val = native_read_msr_safe(msr, &__err);		\
		(*p1) = (u32)__val;					\
		(*p2) = (u32)(__val >> 32);				\
		__err;							\
	})

#define rdtscl(low)						\
	((low) = (u32)native_read_tsc())

#define rdtscll(val)						\
	((val) = native_read_tsc())

#define rdpmc(counter,low,high)					\
	do {							\
162
		u64 _l = native_read_pmc(counter);		\
T
Thomas Gleixner 已提交
163 164 165 166
		(low)  = (u32)_l;				\
		(high) = (u32)(_l >> 32);			\
	} while(0)

167 168 169 170 171 172
#define rdtscp(low, high, aux)						\
       do {                                                            \
		unsigned long long _val = native_read_tscp(&(aux));     \
		(low) = (u32)_val;                                      \
		(high) = (u32)(_val >> 32);                             \
       } while (0)
T
Thomas Gleixner 已提交
173

174
#define rdtscpll(val, aux) (val) = native_read_tscp(&(aux))
T
Thomas Gleixner 已提交
175

176
#endif	/* !CONFIG_PARAVIRT */
T
Thomas Gleixner 已提交
177 178


179
#define checking_wrmsrl(msr,val) wrmsr_safe(msr,(u32)(val),(u32)((val)>>32))
T
Thomas Gleixner 已提交
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207

#define write_tsc(val1,val2) wrmsr(0x10, val1, val2)

#define write_rdtscp_aux(val) wrmsr(0xc0000103, val, 0)

#ifdef CONFIG_SMP
void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
#else  /*  CONFIG_SMP  */
static inline void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
{
	rdmsr(msr_no, *l, *h);
}
static inline void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
{
	wrmsr(msr_no, l, h);
}
static inline int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
{
	return rdmsr_safe(msr_no, l, h);
}
static inline int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
{
	return wrmsr_safe(msr_no, l, h);
}
#endif  /* CONFIG_SMP */
208
#endif /* __ASSEMBLY__ */
209 210
#endif /* __KERNEL__ */

T
Thomas Gleixner 已提交
211

212
#endif