msr.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. /* ----------------------------------------------------------------------- *
  2. *
  3. * Copyright 2000-2008 H. Peter Anvin - All Rights Reserved
  4. * Copyright 2009 Intel Corporation; author: H. Peter Anvin
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
  9. * USA; either version 2 of the License, or (at your option) any later
  10. * version; incorporated herein by reference.
  11. *
  12. * ----------------------------------------------------------------------- */
  13. /*
  14. * x86 MSR access device
  15. *
  16. * This device is accessed by lseek() to the appropriate register number
  17. * and then read/write in chunks of 8 bytes. A larger size means multiple
  18. * reads or writes of the same register.
  19. *
  20. * This driver uses /dev/cpu/%d/msr where %d is the minor number, and on
  21. * an SMP box will direct the access to CPU %d.
  22. */
  23. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  24. #include <linux/module.h>
  25. #include <linux/types.h>
  26. #include <linux/errno.h>
  27. #include <linux/fcntl.h>
  28. #include <linux/init.h>
  29. #include <linux/poll.h>
  30. #include <linux/smp.h>
  31. #include <linux/major.h>
  32. #include <linux/fs.h>
  33. #include <linux/device.h>
  34. #include <linux/cpu.h>
  35. #include <linux/notifier.h>
  36. #include <linux/uaccess.h>
  37. #include <linux/gfp.h>
  38. #include <asm/cpufeature.h>
  39. #include <asm/msr.h>
  40. static struct class *msr_class;
  41. static enum cpuhp_state cpuhp_msr_state;
  42. static ssize_t msr_read(struct file *file, char __user *buf,
  43. size_t count, loff_t *ppos)
  44. {
  45. u32 __user *tmp = (u32 __user *) buf;
  46. u32 data[2];
  47. u32 reg = *ppos;
  48. int cpu = iminor(file_inode(file));
  49. int err = 0;
  50. ssize_t bytes = 0;
  51. if (count % 8)
  52. return -EINVAL; /* Invalid chunk size */
  53. for (; count; count -= 8) {
  54. err = rdmsr_safe_on_cpu(cpu, reg, &data[0], &data[1]);
  55. if (err)
  56. break;
  57. if (copy_to_user(tmp, &data, 8)) {
  58. err = -EFAULT;
  59. break;
  60. }
  61. tmp += 2;
  62. bytes += 8;
  63. }
  64. return bytes ? bytes : err;
  65. }
  66. static ssize_t msr_write(struct file *file, const char __user *buf,
  67. size_t count, loff_t *ppos)
  68. {
  69. const u32 __user *tmp = (const u32 __user *)buf;
  70. u32 data[2];
  71. u32 reg = *ppos;
  72. int cpu = iminor(file_inode(file));
  73. int err = 0;
  74. ssize_t bytes = 0;
  75. if (count % 8)
  76. return -EINVAL; /* Invalid chunk size */
  77. for (; count; count -= 8) {
  78. if (copy_from_user(&data, tmp, 8)) {
  79. err = -EFAULT;
  80. break;
  81. }
  82. err = wrmsr_safe_on_cpu(cpu, reg, data[0], data[1]);
  83. if (err)
  84. break;
  85. tmp += 2;
  86. bytes += 8;
  87. }
  88. return bytes ? bytes : err;
  89. }
  90. static long msr_ioctl(struct file *file, unsigned int ioc, unsigned long arg)
  91. {
  92. u32 __user *uregs = (u32 __user *)arg;
  93. u32 regs[8];
  94. int cpu = iminor(file_inode(file));
  95. int err;
  96. switch (ioc) {
  97. case X86_IOC_RDMSR_REGS:
  98. if (!(file->f_mode & FMODE_READ)) {
  99. err = -EBADF;
  100. break;
  101. }
  102. if (copy_from_user(&regs, uregs, sizeof regs)) {
  103. err = -EFAULT;
  104. break;
  105. }
  106. err = rdmsr_safe_regs_on_cpu(cpu, regs);
  107. if (err)
  108. break;
  109. if (copy_to_user(uregs, &regs, sizeof regs))
  110. err = -EFAULT;
  111. break;
  112. case X86_IOC_WRMSR_REGS:
  113. if (!(file->f_mode & FMODE_WRITE)) {
  114. err = -EBADF;
  115. break;
  116. }
  117. if (copy_from_user(&regs, uregs, sizeof regs)) {
  118. err = -EFAULT;
  119. break;
  120. }
  121. err = wrmsr_safe_regs_on_cpu(cpu, regs);
  122. if (err)
  123. break;
  124. if (copy_to_user(uregs, &regs, sizeof regs))
  125. err = -EFAULT;
  126. break;
  127. default:
  128. err = -ENOTTY;
  129. break;
  130. }
  131. return err;
  132. }
  133. static int msr_open(struct inode *inode, struct file *file)
  134. {
  135. unsigned int cpu = iminor(file_inode(file));
  136. struct cpuinfo_x86 *c;
  137. if (!capable(CAP_SYS_RAWIO))
  138. return -EPERM;
  139. if (cpu >= nr_cpu_ids || !cpu_online(cpu))
  140. return -ENXIO; /* No such CPU */
  141. c = &cpu_data(cpu);
  142. if (!cpu_has(c, X86_FEATURE_MSR))
  143. return -EIO; /* MSR not supported */
  144. return 0;
  145. }
  146. /*
  147. * File operations we support
  148. */
  149. static const struct file_operations msr_fops = {
  150. .owner = THIS_MODULE,
  151. .llseek = no_seek_end_llseek,
  152. .read = msr_read,
  153. .write = msr_write,
  154. .open = msr_open,
  155. .unlocked_ioctl = msr_ioctl,
  156. .compat_ioctl = msr_ioctl,
  157. };
  158. static int msr_device_create(unsigned int cpu)
  159. {
  160. struct device *dev;
  161. dev = device_create(msr_class, NULL, MKDEV(MSR_MAJOR, cpu), NULL,
  162. "msr%d", cpu);
  163. return PTR_ERR_OR_ZERO(dev);
  164. }
  165. static int msr_device_destroy(unsigned int cpu)
  166. {
  167. device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu));
  168. return 0;
  169. }
  170. static char *msr_devnode(struct device *dev, umode_t *mode)
  171. {
  172. return kasprintf(GFP_KERNEL, "cpu/%u/msr", MINOR(dev->devt));
  173. }
  174. static int __init msr_init(void)
  175. {
  176. int err;
  177. if (__register_chrdev(MSR_MAJOR, 0, NR_CPUS, "cpu/msr", &msr_fops)) {
  178. pr_err("unable to get major %d for msr\n", MSR_MAJOR);
  179. return -EBUSY;
  180. }
  181. msr_class = class_create(THIS_MODULE, "msr");
  182. if (IS_ERR(msr_class)) {
  183. err = PTR_ERR(msr_class);
  184. goto out_chrdev;
  185. }
  186. msr_class->devnode = msr_devnode;
  187. err = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/msr:online",
  188. msr_device_create, msr_device_destroy);
  189. if (err < 0)
  190. goto out_class;
  191. cpuhp_msr_state = err;
  192. return 0;
  193. out_class:
  194. class_destroy(msr_class);
  195. out_chrdev:
  196. __unregister_chrdev(MSR_MAJOR, 0, NR_CPUS, "cpu/msr");
  197. return err;
  198. }
  199. module_init(msr_init);
  200. static void __exit msr_exit(void)
  201. {
  202. cpuhp_remove_state(cpuhp_msr_state);
  203. class_destroy(msr_class);
  204. __unregister_chrdev(MSR_MAJOR, 0, NR_CPUS, "cpu/msr");
  205. }
  206. module_exit(msr_exit)
  207. MODULE_AUTHOR("H. Peter Anvin <hpa@zytor.com>");
  208. MODULE_DESCRIPTION("x86 generic MSR driver");
  209. MODULE_LICENSE("GPL");