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