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