linux/include/asm-x86/msr.h
<<
>>
Prefs
   1#ifndef __ASM_X86_MSR_H_
   2#define __ASM_X86_MSR_H_
   3
   4#include <asm/msr-index.h>
   5
   6#ifndef __ASSEMBLY__
   7# include <linux/types.h>
   8#endif
   9
  10#ifdef __KERNEL__
  11#ifndef __ASSEMBLY__
  12
  13#include <asm/asm.h>
  14#include <asm/errno.h>
  15
  16static inline unsigned long long native_read_tscp(unsigned int *aux)
  17{
  18        unsigned long low, high;
  19        asm volatile (".byte 0x0f,0x01,0xf9"
  20                      : "=a" (low), "=d" (high), "=c" (*aux));
  21        return low | ((u64)high >> 32);
  22}
  23
  24/*
  25 * i386 calling convention returns 64-bit value in edx:eax, while
  26 * x86_64 returns at rax. Also, the "A" constraint does not really
  27 * mean rdx:rax in x86_64, so we need specialized behaviour for each
  28 * architecture
  29 */
  30#ifdef CONFIG_X86_64
  31#define DECLARE_ARGS(val, low, high)    unsigned low, high
  32#define EAX_EDX_VAL(val, low, high)     (low | ((u64)(high) << 32))
  33#define EAX_EDX_ARGS(val, low, high)    "a" (low), "d" (high)
  34#define EAX_EDX_RET(val, low, high)     "=a" (low), "=d" (high)
  35#else
  36#define DECLARE_ARGS(val, low, high)    unsigned long long val
  37#define EAX_EDX_VAL(val, low, high)     (val)
  38#define EAX_EDX_ARGS(val, low, high)    "A" (val)
  39#define EAX_EDX_RET(val, low, high)     "=A" (val)
  40#endif
  41
  42static inline unsigned long long native_read_msr(unsigned int msr)
  43{
  44        DECLARE_ARGS(val, low, high);
  45
  46        asm volatile("rdmsr" : EAX_EDX_RET(val, low, high) : "c" (msr));
  47        return EAX_EDX_VAL(val, low, high);
  48}
  49
  50static inline unsigned long long native_read_msr_safe(unsigned int msr,
  51                                                      int *err)
  52{
  53        DECLARE_ARGS(val, low, high);
  54
  55        asm volatile("2: rdmsr ; xor %0,%0\n"
  56                     "1:\n\t"
  57                     ".section .fixup,\"ax\"\n\t"
  58                     "3:  mov %3,%0 ; jmp 1b\n\t"
  59                     ".previous\n\t"
  60                     _ASM_EXTABLE(2b,3b)
  61                     : "=r" (*err), EAX_EDX_RET(val, low, high)
  62                     : "c" (msr), "i" (-EFAULT));
  63        return EAX_EDX_VAL(val, low, high);
  64}
  65
  66static inline void native_write_msr(unsigned int msr,
  67                                    unsigned low, unsigned high)
  68{
  69        asm volatile("wrmsr" : : "c" (msr), "a"(low), "d" (high));
  70}
  71
  72static inline int native_write_msr_safe(unsigned int msr,
  73                                        unsigned low, unsigned high)
  74{
  75        int err;
  76        asm volatile("2: wrmsr ; xor %0,%0\n"
  77                     "1:\n\t"
  78                     ".section .fixup,\"ax\"\n\t"
  79                     "3:  mov %4,%0 ; jmp 1b\n\t"
  80                     ".previous\n\t"
  81                     _ASM_EXTABLE(2b,3b)
  82                     : "=a" (err)
  83                     : "c" (msr), "0" (low), "d" (high),
  84                       "i" (-EFAULT));
  85        return err;
  86}
  87
  88extern unsigned long long native_read_tsc(void);
  89
  90static __always_inline unsigned long long __native_read_tsc(void)
  91{
  92        DECLARE_ARGS(val, low, high);
  93
  94        rdtsc_barrier();
  95        asm volatile("rdtsc" : EAX_EDX_RET(val, low, high));
  96        rdtsc_barrier();
  97
  98        return EAX_EDX_VAL(val, low, high);
  99}
 100
 101static inline unsigned long long native_read_pmc(int counter)
 102{
 103        DECLARE_ARGS(val, low, high);
 104
 105        asm volatile("rdpmc" : EAX_EDX_RET(val, low, high) : "c" (counter));
 106        return EAX_EDX_VAL(val, low, high);
 107}
 108
 109#ifdef CONFIG_PARAVIRT
 110#include <asm/paravirt.h>
 111#else
 112#include <linux/errno.h>
 113/*
 114 * Access to machine-specific registers (available on 586 and better only)
 115 * Note: the rd* operations modify the parameters directly (without using
 116 * pointer indirection), this allows gcc to optimize better
 117 */
 118
 119#define rdmsr(msr,val1,val2)                                            \
 120        do {                                                            \
 121                u64 __val = native_read_msr(msr);                       \
 122                (val1) = (u32)__val;                                    \
 123                (val2) = (u32)(__val >> 32);                            \
 124        } while(0)
 125
 126static inline void wrmsr(unsigned msr, unsigned low, unsigned high)
 127{
 128        native_write_msr(msr, low, high);
 129}
 130
 131#define rdmsrl(msr,val)                                                 \
 132        ((val) = native_read_msr(msr))
 133
 134#define wrmsrl(msr, val)                                                \
 135        native_write_msr(msr, (u32)((u64)(val)), (u32)((u64)(val) >> 32))
 136
 137/* wrmsr with exception handling */
 138static inline int wrmsr_safe(unsigned msr, unsigned low, unsigned high)
 139{
 140        return native_write_msr_safe(msr, low, high);
 141}
 142
 143/* rdmsr with exception handling */
 144#define rdmsr_safe(msr,p1,p2)                                           \
 145        ({                                                              \
 146                int __err;                                              \
 147                u64 __val = native_read_msr_safe(msr, &__err);          \
 148                (*p1) = (u32)__val;                                     \
 149                (*p2) = (u32)(__val >> 32);                             \
 150                __err;                                                  \
 151        })
 152
 153#define rdtscl(low)                                             \
 154        ((low) = (u32)native_read_tsc())
 155
 156#define rdtscll(val)                                            \
 157        ((val) = native_read_tsc())
 158
 159#define rdpmc(counter,low,high)                                 \
 160        do {                                                    \
 161                u64 _l = native_read_pmc(counter);              \
 162                (low)  = (u32)_l;                               \
 163                (high) = (u32)(_l >> 32);                       \
 164        } while(0)
 165
 166#define rdtscp(low, high, aux)                                          \
 167       do {                                                            \
 168                unsigned long long _val = native_read_tscp(&(aux));     \
 169                (low) = (u32)_val;                                      \
 170                (high) = (u32)(_val >> 32);                             \
 171       } while (0)
 172
 173#define rdtscpll(val, aux) (val) = native_read_tscp(&(aux))
 174
 175#endif  /* !CONFIG_PARAVIRT */
 176
 177
 178#define checking_wrmsrl(msr,val) wrmsr_safe(msr,(u32)(val),(u32)((val)>>32))
 179
 180#define write_tsc(val1,val2) wrmsr(0x10, val1, val2)
 181
 182#define write_rdtscp_aux(val) wrmsr(0xc0000103, val, 0)
 183
 184#ifdef CONFIG_SMP
 185void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
 186void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
 187int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
 188int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
 189#else  /*  CONFIG_SMP  */
 190static inline void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
 191{
 192        rdmsr(msr_no, *l, *h);
 193}
 194static inline void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
 195{
 196        wrmsr(msr_no, l, h);
 197}
 198static inline int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
 199{
 200        return rdmsr_safe(msr_no, l, h);
 201}
 202static inline int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
 203{
 204        return wrmsr_safe(msr_no, l, h);
 205}
 206#endif  /* CONFIG_SMP */
 207#endif /* __ASSEMBLY__ */
 208#endif /* __KERNEL__ */
 209
 210
 211#endif
 212
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.