LCOV - code coverage report
Current view: top level - arch/x86/include/asm - msr.h (source / functions) Hit Total Coverage
Test: combined.info Lines: 47 57 82.5 %
Date: 2022-04-01 13:59:58 Functions: 4 5 80.0 %
Branches: 16 42 38.1 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: GPL-2.0 */
       2                 :            : #ifndef _ASM_X86_MSR_H
       3                 :            : #define _ASM_X86_MSR_H
       4                 :            : 
       5                 :            : #include "msr-index.h"
       6                 :            : 
       7                 :            : #ifndef __ASSEMBLY__
       8                 :            : 
       9                 :            : #include <asm/asm.h>
      10                 :            : #include <asm/errno.h>
      11                 :            : #include <asm/cpumask.h>
      12                 :            : #include <uapi/asm/msr.h>
      13                 :            : 
      14                 :            : struct msr {
      15                 :            :         union {
      16                 :            :                 struct {
      17                 :            :                         u32 l;
      18                 :            :                         u32 h;
      19                 :            :                 };
      20                 :            :                 u64 q;
      21                 :            :         };
      22                 :            : };
      23                 :            : 
      24                 :            : struct msr_info {
      25                 :            :         u32 msr_no;
      26                 :            :         struct msr reg;
      27                 :            :         struct msr *msrs;
      28                 :            :         int err;
      29                 :            : };
      30                 :            : 
      31                 :            : struct msr_regs_info {
      32                 :            :         u32 *regs;
      33                 :            :         int err;
      34                 :            : };
      35                 :            : 
      36                 :            : struct saved_msr {
      37                 :            :         bool valid;
      38                 :            :         struct msr_info info;
      39                 :            : };
      40                 :            : 
      41                 :            : struct saved_msrs {
      42                 :            :         unsigned int num;
      43                 :            :         struct saved_msr *array;
      44                 :            : };
      45                 :            : 
      46                 :            : /*
      47                 :            :  * both i386 and x86_64 returns 64-bit value in edx:eax, but gcc's "A"
      48                 :            :  * constraint has different meanings. For i386, "A" means exactly
      49                 :            :  * edx:eax, while for x86_64 it doesn't mean rdx:rax or edx:eax. Instead,
      50                 :            :  * it means rax *or* rdx.
      51                 :            :  */
      52                 :            : #ifdef CONFIG_X86_64
      53                 :            : /* Using 64-bit values saves one instruction clearing the high half of low */
      54                 :            : #define DECLARE_ARGS(val, low, high)    unsigned long low, high
      55                 :            : #define EAX_EDX_VAL(val, low, high)     ((low) | (high) << 32)
      56                 :            : #define EAX_EDX_RET(val, low, high)     "=a" (low), "=d" (high)
      57                 :            : #else
      58                 :            : #define DECLARE_ARGS(val, low, high)    unsigned long long val
      59                 :            : #define EAX_EDX_VAL(val, low, high)     (val)
      60                 :            : #define EAX_EDX_RET(val, low, high)     "=A" (val)
      61                 :            : #endif
      62                 :            : 
      63                 :            : #ifdef CONFIG_TRACEPOINTS
      64                 :            : /*
      65                 :            :  * Be very careful with includes. This header is prone to include loops.
      66                 :            :  */
      67                 :            : #include <asm/atomic.h>
      68                 :            : #include <linux/tracepoint-defs.h>
      69                 :            : 
      70                 :            : extern struct tracepoint __tracepoint_read_msr;
      71                 :            : extern struct tracepoint __tracepoint_write_msr;
      72                 :            : extern struct tracepoint __tracepoint_rdpmc;
      73                 :            : #define msr_tracepoint_active(t) static_key_false(&(t).key)
      74                 :            : extern void do_trace_write_msr(unsigned int msr, u64 val, int failed);
      75                 :            : extern void do_trace_read_msr(unsigned int msr, u64 val, int failed);
      76                 :            : extern void do_trace_rdpmc(unsigned int msr, u64 val, int failed);
      77                 :            : #else
      78                 :            : #define msr_tracepoint_active(t) false
      79                 :            : static inline void do_trace_write_msr(unsigned int msr, u64 val, int failed) {}
      80                 :            : static inline void do_trace_read_msr(unsigned int msr, u64 val, int failed) {}
      81                 :            : static inline void do_trace_rdpmc(unsigned int msr, u64 val, int failed) {}
      82                 :            : #endif
      83                 :            : 
      84                 :            : /*
      85                 :            :  * __rdmsr() and __wrmsr() are the two primitives which are the bare minimum MSR
      86                 :            :  * accessors and should not have any tracing or other functionality piggybacking
      87                 :            :  * on them - those are *purely* for accessing MSRs and nothing more. So don't even
      88                 :            :  * think of extending them - you will be slapped with a stinking trout or a frozen
      89                 :            :  * shark will reach you, wherever you are! You've been warned.
      90                 :            :  */
      91                 :       6090 : static inline unsigned long long notrace __rdmsr(unsigned int msr)
      92                 :            : {
      93                 :       6090 :         DECLARE_ARGS(val, low, high);
      94                 :            : 
      95                 :       6090 :         asm volatile("1: rdmsr\n"
      96                 :            :                      "2:\n"
      97                 :            :                      _ASM_EXTABLE_HANDLE(1b, 2b, ex_handler_rdmsr_unsafe)
      98                 :            :                      : EAX_EDX_RET(val, low, high) : "c" (msr));
      99                 :            : 
     100   [ #  #  #  #  :       6090 :         return EAX_EDX_VAL(val, low, high);
                   #  # ]
     101                 :            : }
     102                 :            : 
     103                 :    1581424 : static inline void notrace __wrmsr(unsigned int msr, u32 low, u32 high)
     104                 :            : {
     105                 :    1581424 :         asm volatile("1: wrmsr\n"
     106                 :            :                      "2:\n"
     107                 :            :                      _ASM_EXTABLE_HANDLE(1b, 2b, ex_handler_wrmsr_unsafe)
     108                 :            :                      : : "c" (msr), "a"(low), "d" (high) : "memory");
     109                 :            : }
     110                 :            : 
     111                 :            : #define native_rdmsr(msr, val1, val2)                   \
     112                 :            : do {                                                    \
     113                 :            :         u64 __val = __rdmsr((msr));                     \
     114                 :            :         (void)((val1) = (u32)__val);                    \
     115                 :            :         (void)((val2) = (u32)(__val >> 32));              \
     116                 :            : } while (0)
     117                 :            : 
     118                 :            : #define native_wrmsr(msr, low, high)                    \
     119                 :            :         __wrmsr(msr, low, high)
     120                 :            : 
     121                 :            : #define native_wrmsrl(msr, val)                         \
     122                 :            :         __wrmsr((msr), (u32)((u64)(val)),               \
     123                 :            :                        (u32)((u64)(val) >> 32))
     124                 :            : 
     125                 :       6090 : static inline unsigned long long native_read_msr(unsigned int msr)
     126                 :            : {
     127                 :       6090 :         unsigned long long val;
     128                 :            : 
     129                 :       6090 :         val = __rdmsr(msr);
     130                 :            : 
     131         [ -  + ]:       6090 :         if (msr_tracepoint_active(__tracepoint_read_msr))
     132                 :          0 :                 do_trace_read_msr(msr, val, 0);
     133                 :            : 
     134                 :       6090 :         return val;
     135                 :            : }
     136                 :            : 
     137                 :       2340 : static inline unsigned long long native_read_msr_safe(unsigned int msr,
     138                 :            :                                                       int *err)
     139                 :            : {
     140                 :       2340 :         DECLARE_ARGS(val, low, high);
     141                 :            : 
     142                 :       2340 :         asm volatile("2: rdmsr ; xor %[err],%[err]\n"
     143                 :            :                      "1:\n\t"
     144                 :            :                      ".section .fixup,\"ax\"\n\t"
     145                 :            :                      "3: mov %[fault],%[err]\n\t"
     146                 :            :                      "xorl %%eax, %%eax\n\t"
     147                 :            :                      "xorl %%edx, %%edx\n\t"
     148                 :            :                      "jmp 1b\n\t"
     149                 :            :                      ".previous\n\t"
     150                 :            :                      _ASM_EXTABLE(2b, 3b)
     151                 :            :                      : [err] "=r" (*err), EAX_EDX_RET(val, low, high)
     152                 :            :                      : "c" (msr), [fault] "i" (-EIO));
     153         [ -  + ]:       2340 :         if (msr_tracepoint_active(__tracepoint_read_msr))
     154                 :          0 :                 do_trace_read_msr(msr, EAX_EDX_VAL(val, low, high), *err);
     155                 :       2340 :         return EAX_EDX_VAL(val, low, high);
     156                 :            : }
     157                 :            : 
     158                 :            : /* Can be uninlined because referenced by paravirt */
     159                 :            : static inline void notrace
     160                 :    1581424 : native_write_msr(unsigned int msr, u32 low, u32 high)
     161                 :            : {
     162                 :    1581424 :         __wrmsr(msr, low, high);
     163                 :            : 
     164         [ -  + ]:    1581424 :         if (msr_tracepoint_active(__tracepoint_write_msr))
     165                 :          0 :                 do_trace_write_msr(msr, ((u64)high << 32 | low), 0);
     166                 :    1581424 : }
     167                 :            : 
     168                 :            : /* Can be uninlined because referenced by paravirt */
     169                 :            : static inline int notrace
     170                 :        702 : native_write_msr_safe(unsigned int msr, u32 low, u32 high)
     171                 :            : {
     172                 :        702 :         int err;
     173                 :            : 
     174                 :        702 :         asm volatile("2: wrmsr ; xor %[err],%[err]\n"
     175                 :            :                      "1:\n\t"
     176                 :            :                      ".section .fixup,\"ax\"\n\t"
     177                 :            :                      "3:  mov %[fault],%[err] ; jmp 1b\n\t"
     178                 :            :                      ".previous\n\t"
     179                 :            :                      _ASM_EXTABLE(2b, 3b)
     180                 :            :                      : [err] "=a" (err)
     181                 :            :                      : "c" (msr), "0" (low), "d" (high),
     182                 :            :                        [fault] "i" (-EIO)
     183                 :            :                      : "memory");
     184         [ -  + ]:        702 :         if (msr_tracepoint_active(__tracepoint_write_msr))
     185                 :          0 :                 do_trace_write_msr(msr, ((u64)high << 32 | low), err);
     186                 :        702 :         return err;
     187                 :            : }
     188                 :            : 
     189                 :            : extern int rdmsr_safe_regs(u32 regs[8]);
     190                 :            : extern int wrmsr_safe_regs(u32 regs[8]);
     191                 :            : 
     192                 :            : /**
     193                 :            :  * rdtsc() - returns the current TSC without ordering constraints
     194                 :            :  *
     195                 :            :  * rdtsc() returns the result of RDTSC as a 64-bit integer.  The
     196                 :            :  * only ordering constraint it supplies is the ordering implied by
     197                 :            :  * "asm volatile": it will put the RDTSC in the place you expect.  The
     198                 :            :  * CPU can and will speculatively execute that RDTSC, though, so the
     199                 :            :  * results can be non-monotonic if compared on different CPUs.
     200                 :            :  */
     201                 :  248795330 : static __always_inline unsigned long long rdtsc(void)
     202                 :            : {
     203                 :  248795330 :         DECLARE_ARGS(val, low, high);
     204                 :            : 
     205                 :  248795330 :         asm volatile("rdtsc" : EAX_EDX_RET(val, low, high));
     206                 :            : 
     207   [ +  +  -  +  :  248795330 :         return EAX_EDX_VAL(val, low, high);
          +  +  -  -  -  
             -  #  #  #  
                      # ]
     208                 :            : }
     209                 :            : 
     210                 :            : /**
     211                 :            :  * rdtsc_ordered() - read the current TSC in program order
     212                 :            :  *
     213                 :            :  * rdtsc_ordered() returns the result of RDTSC as a 64-bit integer.
     214                 :            :  * It is ordered like a load to a global in-memory counter.  It should
     215                 :            :  * be impossible to observe non-monotonic rdtsc_unordered() behavior
     216                 :            :  * across multiple CPUs as long as the TSC is synced.
     217                 :            :  */
     218                 :  315746346 : static __always_inline unsigned long long rdtsc_ordered(void)
     219                 :            : {
     220                 :  315746346 :         DECLARE_ARGS(val, low, high);
     221                 :            : 
     222                 :            :         /*
     223                 :            :          * The RDTSC instruction is not ordered relative to memory
     224                 :            :          * access.  The Intel SDM and the AMD APM are both vague on this
     225                 :            :          * point, but empirically an RDTSC instruction can be
     226                 :            :          * speculatively executed before prior loads.  An RDTSC
     227                 :            :          * immediately after an appropriate barrier appears to be
     228                 :            :          * ordered as a normal load, that is, it provides the same
     229                 :            :          * ordering guarantees as reading from a global memory location
     230                 :            :          * that some other imaginary CPU is updating continuously with a
     231                 :            :          * time stamp.
     232                 :            :          *
     233                 :            :          * Thus, use the preferred barrier on the respective CPU, aiming for
     234                 :            :          * RDTSCP as the default.
     235                 :            :          */
     236                 :  315746346 :         asm volatile(ALTERNATIVE_2("rdtsc",
     237                 :            :                                    "lfence; rdtsc", X86_FEATURE_LFENCE_RDTSC,
     238                 :            :                                    "rdtscp", X86_FEATURE_RDTSCP)
     239                 :            :                         : EAX_EDX_RET(val, low, high)
     240                 :            :                         /* RDTSCP clobbers ECX with MSR_TSC_AUX. */
     241                 :            :                         :: "ecx");
     242                 :            : 
     243   [ +  -  +  + ]:  315746346 :         return EAX_EDX_VAL(val, low, high);
     244                 :            : }
     245                 :            : 
     246                 :          0 : static inline unsigned long long native_read_pmc(int counter)
     247                 :            : {
     248                 :          0 :         DECLARE_ARGS(val, low, high);
     249                 :            : 
     250                 :          0 :         asm volatile("rdpmc" : EAX_EDX_RET(val, low, high) : "c" (counter));
     251         [ #  # ]:          0 :         if (msr_tracepoint_active(__tracepoint_rdpmc))
     252                 :          0 :                 do_trace_rdpmc(counter, EAX_EDX_VAL(val, low, high), 0);
     253                 :          0 :         return EAX_EDX_VAL(val, low, high);
     254                 :            : }
     255                 :            : 
     256                 :            : #ifdef CONFIG_PARAVIRT_XXL
     257                 :            : #include <asm/paravirt.h>
     258                 :            : #else
     259                 :            : #include <linux/errno.h>
     260                 :            : /*
     261                 :            :  * Access to machine-specific registers (available on 586 and better only)
     262                 :            :  * Note: the rd* operations modify the parameters directly (without using
     263                 :            :  * pointer indirection), this allows gcc to optimize better
     264                 :            :  */
     265                 :            : 
     266                 :            : #define rdmsr(msr, low, high)                                   \
     267                 :            : do {                                                            \
     268                 :            :         u64 __val = native_read_msr((msr));                     \
     269                 :            :         (void)((low) = (u32)__val);                             \
     270                 :            :         (void)((high) = (u32)(__val >> 32));                      \
     271                 :            : } while (0)
     272                 :            : 
     273                 :        156 : static inline void wrmsr(unsigned int msr, u32 low, u32 high)
     274                 :            : {
     275                 :        156 :         native_write_msr(msr, low, high);
     276                 :         78 : }
     277                 :            : 
     278                 :            : #define rdmsrl(msr, val)                        \
     279                 :            :         ((val) = native_read_msr((msr)))
     280                 :            : 
     281                 :    1581266 : static inline void wrmsrl(unsigned int msr, u64 val)
     282                 :            : {
     283                 :    1581110 :         native_write_msr(msr, (u32)(val & 0xffffffffULL), (u32)(val >> 32));
     284                 :    1190264 : }
     285                 :            : 
     286                 :            : /* wrmsr with exception handling */
     287                 :        702 : static inline int wrmsr_safe(unsigned int msr, u32 low, u32 high)
     288                 :            : {
     289                 :        702 :         return native_write_msr_safe(msr, low, high);
     290                 :            : }
     291                 :            : 
     292                 :            : /* rdmsr with exception handling */
     293                 :            : #define rdmsr_safe(msr, low, high)                              \
     294                 :            : ({                                                              \
     295                 :            :         int __err;                                              \
     296                 :            :         u64 __val = native_read_msr_safe((msr), &__err);    \
     297                 :            :         (*low) = (u32)__val;                                    \
     298                 :            :         (*high) = (u32)(__val >> 32);                             \
     299                 :            :         __err;                                                  \
     300                 :            : })
     301                 :            : 
     302                 :       1404 : static inline int rdmsrl_safe(unsigned int msr, unsigned long long *p)
     303                 :            : {
     304                 :       1404 :         int err;
     305                 :            : 
     306                 :       1404 :         *p = native_read_msr_safe(msr, &err);
     307   [ +  +  -  -  :       1404 :         return err;
             -  +  +  - ]
     308                 :            : }
     309                 :            : 
     310                 :            : #define rdpmc(counter, low, high)                       \
     311                 :            : do {                                                    \
     312                 :            :         u64 _l = native_read_pmc((counter));            \
     313                 :            :         (low)  = (u32)_l;                               \
     314                 :            :         (high) = (u32)(_l >> 32);                 \
     315                 :            : } while (0)
     316                 :            : 
     317                 :            : #define rdpmcl(counter, val) ((val) = native_read_pmc(counter))
     318                 :            : 
     319                 :            : #endif  /* !CONFIG_PARAVIRT_XXL */
     320                 :            : 
     321                 :            : /*
     322                 :            :  * 64-bit version of wrmsr_safe():
     323                 :            :  */
     324                 :        390 : static inline int wrmsrl_safe(u32 msr, u64 val)
     325                 :            : {
     326                 :        312 :         return wrmsr_safe(msr, (u32)val,  (u32)(val >> 32));
     327                 :            : }
     328                 :            : 
     329                 :            : #define write_tsc(low, high) wrmsr(MSR_IA32_TSC, (low), (high))
     330                 :            : 
     331                 :            : #define write_rdtscp_aux(val) wrmsr(MSR_TSC_AUX, (val), 0)
     332                 :            : 
     333                 :            : struct msr *msrs_alloc(void);
     334                 :            : void msrs_free(struct msr *msrs);
     335                 :            : int msr_set_bit(u32 msr, u8 bit);
     336                 :            : int msr_clear_bit(u32 msr, u8 bit);
     337                 :            : 
     338                 :            : #ifdef CONFIG_SMP
     339                 :            : int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
     340                 :            : int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
     341                 :            : int rdmsrl_on_cpu(unsigned int cpu, u32 msr_no, u64 *q);
     342                 :            : int wrmsrl_on_cpu(unsigned int cpu, u32 msr_no, u64 q);
     343                 :            : void rdmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs);
     344                 :            : void wrmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs);
     345                 :            : int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
     346                 :            : int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
     347                 :            : int rdmsrl_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 *q);
     348                 :            : int wrmsrl_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 q);
     349                 :            : int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]);
     350                 :            : int wrmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]);
     351                 :            : #else  /*  CONFIG_SMP  */
     352                 :            : static inline int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
     353                 :            : {
     354                 :            :         rdmsr(msr_no, *l, *h);
     355                 :            :         return 0;
     356                 :            : }
     357                 :            : static inline int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
     358                 :            : {
     359                 :            :         wrmsr(msr_no, l, h);
     360                 :            :         return 0;
     361                 :            : }
     362                 :            : static inline int rdmsrl_on_cpu(unsigned int cpu, u32 msr_no, u64 *q)
     363                 :            : {
     364                 :            :         rdmsrl(msr_no, *q);
     365                 :            :         return 0;
     366                 :            : }
     367                 :            : static inline int wrmsrl_on_cpu(unsigned int cpu, u32 msr_no, u64 q)
     368                 :            : {
     369                 :            :         wrmsrl(msr_no, q);
     370                 :            :         return 0;
     371                 :            : }
     372                 :            : static inline void rdmsr_on_cpus(const struct cpumask *m, u32 msr_no,
     373                 :            :                                 struct msr *msrs)
     374                 :            : {
     375                 :            :         rdmsr_on_cpu(0, msr_no, &(msrs[0].l), &(msrs[0].h));
     376                 :            : }
     377                 :            : static inline void wrmsr_on_cpus(const struct cpumask *m, u32 msr_no,
     378                 :            :                                 struct msr *msrs)
     379                 :            : {
     380                 :            :         wrmsr_on_cpu(0, msr_no, msrs[0].l, msrs[0].h);
     381                 :            : }
     382                 :            : static inline int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no,
     383                 :            :                                     u32 *l, u32 *h)
     384                 :            : {
     385                 :            :         return rdmsr_safe(msr_no, l, h);
     386                 :            : }
     387                 :            : static inline int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
     388                 :            : {
     389                 :            :         return wrmsr_safe(msr_no, l, h);
     390                 :            : }
     391                 :            : static inline int rdmsrl_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 *q)
     392                 :            : {
     393                 :            :         return rdmsrl_safe(msr_no, q);
     394                 :            : }
     395                 :            : static inline int wrmsrl_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 q)
     396                 :            : {
     397                 :            :         return wrmsrl_safe(msr_no, q);
     398                 :            : }
     399                 :            : static inline int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8])
     400                 :            : {
     401                 :            :         return rdmsr_safe_regs(regs);
     402                 :            : }
     403                 :            : static inline int wrmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8])
     404                 :            : {
     405                 :            :         return wrmsr_safe_regs(regs);
     406                 :            : }
     407                 :            : #endif  /* CONFIG_SMP */
     408                 :            : #endif /* __ASSEMBLY__ */
     409                 :            : #endif /* _ASM_X86_MSR_H */

Generated by: LCOV version 1.14