msr.h 5.5 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
		     ".previous\n\t"
60
		     _ASM_EXTABLE(2b,3b)
61
		     : "=r" (*err), EAX_EDX_RET(val, low, high)
T
Thomas Gleixner 已提交
62
		     : "c" (msr), "i" (-EFAULT));
63
	return EAX_EDX_VAL(val, low, high);
T
Thomas Gleixner 已提交
64 65
}

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

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

88
extern unsigned long long native_read_tsc(void);
T
Thomas Gleixner 已提交
89

I
Ingo Molnar 已提交
90 91 92 93 94 95 96 97 98 99 100
static __always_inline unsigned long long __native_read_tsc(void)
{
	DECLARE_ARGS(val, low, high);

	rdtsc_barrier();
	asm volatile("rdtsc" : EAX_EDX_RET(val, low, high));
	rdtsc_barrier();

	return EAX_EDX_VAL(val, low, high);
}

101
static inline unsigned long long native_read_pmc(int counter)
T
Thomas Gleixner 已提交
102
{
103 104 105 106
	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 已提交
107 108 109 110
}

#ifdef CONFIG_PARAVIRT
#include <asm/paravirt.h>
111
#else
T
Thomas Gleixner 已提交
112 113 114 115 116 117 118 119 120 121 122 123 124 125
#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)

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

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

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

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

/* 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 {							\
161
		u64 _l = native_read_pmc(counter);		\
T
Thomas Gleixner 已提交
162 163 164 165
		(low)  = (u32)_l;				\
		(high) = (u32)(_l >> 32);			\
	} while(0)

166 167 168 169 170 171
#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 已提交
172

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

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


178
#define checking_wrmsrl(msr,val) wrmsr_safe(msr,(u32)(val),(u32)((val)>>32))
T
Thomas Gleixner 已提交
179 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

#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 */
207
#endif /* __ASSEMBLY__ */
208 209
#endif /* __KERNEL__ */

T
Thomas Gleixner 已提交
210

211
#endif