Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. // SPDX-License-Identifier: GPL-2.0
  2.  
  3. #include <linux/preempt.h>
  4. #include <asm/msr.h>
  5.  
  6. /**
  7.  * Read an MSR with error handling
  8.  *
  9.  * @msr: MSR to read
  10.  * @m: value to read into
  11.  *
  12.  * It returns read data only on success, otherwise it doesn't change the output
  13.  * argument @m.
  14.  *
  15.  */
  16. int msr_read(u32 msr, struct msr *m)
  17. {
  18.         int err;
  19.         u64 val;
  20.  
  21.         err = rdmsrl_safe(msr, &val);
  22.         if (!err)
  23.                 m->q = val;
  24.  
  25.         return err;
  26. }
  27.  
  28. /**
  29.  * Write an MSR with error handling
  30.  *
  31.  * @msr: MSR to write
  32.  * @m: value to write
  33.  */
  34. int msr_write(u32 msr, struct msr *m)
  35. {
  36.         return wrmsrl_safe(msr, m->q);
  37. }
  38.  
  39. static inline int __flip_bit(u32 msr, u8 bit, bool set)
  40. {
  41.         struct msr m, m1;
  42.         int err = -EINVAL;
  43.  
  44.         if (bit > 63)
  45.                 return err;
  46.  
  47.         err = msr_read(msr, &m);
  48.         if (err)
  49.                 return err;
  50.  
  51.         m1 = m;
  52.         if (set)
  53.                 m1.q |=  BIT_64(bit);
  54.         else
  55.                 m1.q &= ~BIT_64(bit);
  56.  
  57.         if (m1.q == m.q)
  58.                 return 0;
  59.  
  60.         err = msr_write(msr, &m1);
  61.         if (err)
  62.                 return err;
  63.  
  64.         return 1;
  65. }
  66.  
  67. /**
  68.  * Set @bit in a MSR @msr.
  69.  *
  70.  * Retval:
  71.  * < 0: An error was encountered.
  72.  * = 0: Bit was already set.
  73.  * > 0: Hardware accepted the MSR write.
  74.  */
  75. int msr_set_bit(u32 msr, u8 bit)
  76. {
  77.         return __flip_bit(msr, bit, true);
  78. }
  79.  
  80. /**
  81.  * Clear @bit in a MSR @msr.
  82.  *
  83.  * Retval:
  84.  * < 0: An error was encountered.
  85.  * = 0: Bit was already cleared.
  86.  * > 0: Hardware accepted the MSR write.
  87.  */
  88. int msr_clear_bit(u32 msr, u8 bit)
  89. {
  90.         return __flip_bit(msr, bit, false);
  91. }
  92.