uboot/arch/x86/include/asm/msr.h
<<
>>
Prefs
   1/*
   2 * Taken from the linux kernel file of the same name
   3 *
   4 * (C) Copyright 2012
   5 * Graeme Russ, <graeme.russ@gmail.com>
   6 *
   7 * SPDX-License-Identifier:     GPL-2.0+
   8 */
   9
  10#ifndef _ASM_X86_MSR_H
  11#define _ASM_X86_MSR_H
  12
  13#include <asm/msr-index.h>
  14
  15#ifndef __ASSEMBLY__
  16
  17#include <linux/types.h>
  18#include <linux/ioctl.h>
  19
  20#define X86_IOC_RDMSR_REGS      _IOWR('c', 0xA0, __u32[8])
  21#define X86_IOC_WRMSR_REGS      _IOWR('c', 0xA1, __u32[8])
  22
  23#ifdef __KERNEL__
  24
  25#include <linux/errno.h>
  26
  27struct msr {
  28        union {
  29                struct {
  30                        u32 l;
  31                        u32 h;
  32                };
  33                u64 q;
  34        };
  35};
  36
  37struct msr_info {
  38        u32 msr_no;
  39        struct msr reg;
  40        struct msr *msrs;
  41        int err;
  42};
  43
  44struct msr_regs_info {
  45        u32 *regs;
  46        int err;
  47};
  48
  49static inline unsigned long long native_read_tscp(unsigned int *aux)
  50{
  51        unsigned long low, high;
  52        asm volatile(".byte 0x0f,0x01,0xf9"
  53                     : "=a" (low), "=d" (high), "=c" (*aux));
  54        return low | ((u64)high << 32);
  55}
  56
  57/*
  58 * both i386 and x86_64 returns 64-bit value in edx:eax, but gcc's "A"
  59 * constraint has different meanings. For i386, "A" means exactly
  60 * edx:eax, while for x86_64 it doesn't mean rdx:rax or edx:eax. Instead,
  61 * it means rax *or* rdx.
  62 */
  63#ifdef CONFIG_X86_64
  64#define DECLARE_ARGS(val, low, high)    unsigned low, high
  65#define EAX_EDX_VAL(val, low, high)     ((low) | ((u64)(high) << 32))
  66#define EAX_EDX_ARGS(val, low, high)    "a" (low), "d" (high)
  67#define EAX_EDX_RET(val, low, high)     "=a" (low), "=d" (high)
  68#else
  69#define DECLARE_ARGS(val, low, high)    unsigned long long val
  70#define EAX_EDX_VAL(val, low, high)     (val)
  71#define EAX_EDX_ARGS(val, low, high)    "A" (val)
  72#define EAX_EDX_RET(val, low, high)     "=A" (val)
  73#endif
  74
  75static inline __attribute__((no_instrument_function))
  76        unsigned long long native_read_msr(unsigned int msr)
  77{
  78        DECLARE_ARGS(val, low, high);
  79
  80        asm volatile("rdmsr" : EAX_EDX_RET(val, low, high) : "c" (msr));
  81        return EAX_EDX_VAL(val, low, high);
  82}
  83
  84static inline void native_write_msr(unsigned int msr,
  85                                    unsigned low, unsigned high)
  86{
  87        asm volatile("wrmsr" : : "c" (msr), "a"(low), "d" (high) : "memory");
  88}
  89
  90extern unsigned long long native_read_tsc(void);
  91
  92extern int native_rdmsr_safe_regs(u32 regs[8]);
  93extern int native_wrmsr_safe_regs(u32 regs[8]);
  94
  95static inline unsigned long long native_read_pmc(int counter)
  96{
  97        DECLARE_ARGS(val, low, high);
  98
  99        asm volatile("rdpmc" : EAX_EDX_RET(val, low, high) : "c" (counter));
 100        return EAX_EDX_VAL(val, low, high);
 101}
 102
 103#ifdef CONFIG_PARAVIRT
 104#include <asm/paravirt.h>
 105#else
 106#include <errno.h>
 107/*
 108 * Access to machine-specific registers (available on 586 and better only)
 109 * Note: the rd* operations modify the parameters directly (without using
 110 * pointer indirection), this allows gcc to optimize better
 111 */
 112
 113#define rdmsr(msr, val1, val2)                                  \
 114do {                                                            \
 115        u64 __val = native_read_msr((msr));                     \
 116        (void)((val1) = (u32)__val);                            \
 117        (void)((val2) = (u32)(__val >> 32));                    \
 118} while (0)
 119
 120static inline void wrmsr(unsigned msr, unsigned low, unsigned high)
 121{
 122        native_write_msr(msr, low, high);
 123}
 124
 125#define rdmsrl(msr, val)                        \
 126        ((val) = native_read_msr((msr)))
 127
 128#define wrmsrl(msr, val)                                                \
 129        native_write_msr((msr), (u32)((u64)(val)), (u32)((u64)(val) >> 32))
 130
 131static inline void msr_clrsetbits_64(unsigned msr, u64 clear, u64 set)
 132{
 133        u64 val;
 134
 135        val = native_read_msr(msr);
 136        val &= ~clear;
 137        val |= set;
 138        wrmsrl(msr, val);
 139}
 140
 141static inline void msr_setbits_64(unsigned msr, u64 set)
 142{
 143        u64 val;
 144
 145        val = native_read_msr(msr);
 146        val |= set;
 147        wrmsrl(msr, val);
 148}
 149
 150static inline void msr_clrbits_64(unsigned msr, u64 clear)
 151{
 152        u64 val;
 153
 154        val = native_read_msr(msr);
 155        val &= ~clear;
 156        wrmsrl(msr, val);
 157}
 158
 159/* rdmsr with exception handling */
 160#define rdmsr_safe(msr, p1, p2)                                 \
 161({                                                              \
 162        int __err;                                              \
 163        u64 __val = native_read_msr_safe((msr), &__err);        \
 164        (*p1) = (u32)__val;                                     \
 165        (*p2) = (u32)(__val >> 32);                             \
 166        __err;                                                  \
 167})
 168
 169static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p)
 170{
 171        u32 gprs[8] = { 0 };
 172        int err;
 173
 174        gprs[1] = msr;
 175        gprs[7] = 0x9c5a203a;
 176
 177        err = native_rdmsr_safe_regs(gprs);
 178
 179        *p = gprs[0] | ((u64)gprs[2] << 32);
 180
 181        return err;
 182}
 183
 184static inline int wrmsrl_amd_safe(unsigned msr, unsigned long long val)
 185{
 186        u32 gprs[8] = { 0 };
 187
 188        gprs[0] = (u32)val;
 189        gprs[1] = msr;
 190        gprs[2] = val >> 32;
 191        gprs[7] = 0x9c5a203a;
 192
 193        return native_wrmsr_safe_regs(gprs);
 194}
 195
 196static inline int rdmsr_safe_regs(u32 regs[8])
 197{
 198        return native_rdmsr_safe_regs(regs);
 199}
 200
 201static inline int wrmsr_safe_regs(u32 regs[8])
 202{
 203        return native_wrmsr_safe_regs(regs);
 204}
 205
 206typedef struct msr_t {
 207        uint32_t lo;
 208        uint32_t hi;
 209} msr_t;
 210
 211static inline struct msr_t msr_read(unsigned msr_num)
 212{
 213        struct msr_t msr;
 214
 215        rdmsr(msr_num, msr.lo, msr.hi);
 216
 217        return msr;
 218}
 219
 220static inline void msr_write(unsigned msr_num, msr_t msr)
 221{
 222        wrmsr(msr_num, msr.lo, msr.hi);
 223}
 224
 225#define rdtscl(low)                                             \
 226        ((low) = (u32)__native_read_tsc())
 227
 228#define rdtscll(val)                                            \
 229        ((val) = __native_read_tsc())
 230
 231#define rdpmc(counter, low, high)                       \
 232do {                                                    \
 233        u64 _l = native_read_pmc((counter));            \
 234        (low)  = (u32)_l;                               \
 235        (high) = (u32)(_l >> 32);                       \
 236} while (0)
 237
 238#define rdtscp(low, high, aux)                                  \
 239do {                                                            \
 240        unsigned long long _val = native_read_tscp(&(aux));     \
 241        (low) = (u32)_val;                                      \
 242        (high) = (u32)(_val >> 32);                             \
 243} while (0)
 244
 245#define rdtscpll(val, aux) (val) = native_read_tscp(&(aux))
 246
 247#endif  /* !CONFIG_PARAVIRT */
 248
 249
 250#define checking_wrmsrl(msr, val) wrmsr_safe((msr), (u32)(val),         \
 251                                             (u32)((val) >> 32))
 252
 253#define write_tsc(val1, val2) wrmsr(MSR_IA32_TSC, (val1), (val2))
 254
 255#define write_rdtscp_aux(val) wrmsr(MSR_TSC_AUX, (val), 0)
 256
 257struct msr *msrs_alloc(void);
 258void msrs_free(struct msr *msrs);
 259
 260#endif /* __KERNEL__ */
 261#endif /* __ASSEMBLY__ */
 262#endif /* _ASM_X86_MSR_H */
 263