diff options
| -rw-r--r-- | Documentation/ioctl/ioctl-number.txt | 1 | ||||
| -rw-r--r-- | arch/x86/include/asm/msr.h | 10 | ||||
| -rw-r--r-- | arch/x86/kernel/msr.c | 51 |
3 files changed, 60 insertions, 2 deletions
diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt index dbea4f95fc85..1c058b552e93 100644 --- a/Documentation/ioctl/ioctl-number.txt +++ b/Documentation/ioctl/ioctl-number.txt | |||
| @@ -121,6 +121,7 @@ Code Seq# Include File Comments | |||
| 121 | 'c' 00-7F linux/comstats.h conflict! | 121 | 'c' 00-7F linux/comstats.h conflict! |
| 122 | 'c' 00-7F linux/coda.h conflict! | 122 | 'c' 00-7F linux/coda.h conflict! |
| 123 | 'c' 80-9F arch/s390/include/asm/chsc.h | 123 | 'c' 80-9F arch/s390/include/asm/chsc.h |
| 124 | 'c' A0-AF arch/x86/include/asm/msr.h | ||
| 124 | 'd' 00-FF linux/char/drm/drm/h conflict! | 125 | 'd' 00-FF linux/char/drm/drm/h conflict! |
| 125 | 'd' F0-FF linux/digi1.h | 126 | 'd' F0-FF linux/digi1.h |
| 126 | 'e' all linux/digi1.h conflict! | 127 | 'e' all linux/digi1.h conflict! |
diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h index 8e56712aa176..7e2b6ba962ff 100644 --- a/arch/x86/include/asm/msr.h +++ b/arch/x86/include/asm/msr.h | |||
| @@ -3,10 +3,16 @@ | |||
| 3 | 3 | ||
| 4 | #include <asm/msr-index.h> | 4 | #include <asm/msr-index.h> |
| 5 | 5 | ||
| 6 | #ifdef __KERNEL__ | ||
| 7 | #ifndef __ASSEMBLY__ | 6 | #ifndef __ASSEMBLY__ |
| 8 | 7 | ||
| 9 | #include <linux/types.h> | 8 | #include <linux/types.h> |
| 9 | #include <linux/ioctl.h> | ||
| 10 | |||
| 11 | #define X86_IOC_RDMSR_REGS _IOWR('c', 0xA0, __u32[8]) | ||
| 12 | #define X86_IOC_WRMSR_REGS _IOWR('c', 0xA1, __u32[8]) | ||
| 13 | |||
| 14 | #ifdef __KERNEL__ | ||
| 15 | |||
| 10 | #include <asm/asm.h> | 16 | #include <asm/asm.h> |
| 11 | #include <asm/errno.h> | 17 | #include <asm/errno.h> |
| 12 | #include <asm/cpumask.h> | 18 | #include <asm/cpumask.h> |
| @@ -286,6 +292,6 @@ static inline int wrmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]) | |||
| 286 | return wrmsr_safe_regs(regs); | 292 | return wrmsr_safe_regs(regs); |
| 287 | } | 293 | } |
| 288 | #endif /* CONFIG_SMP */ | 294 | #endif /* CONFIG_SMP */ |
| 289 | #endif /* __ASSEMBLY__ */ | ||
| 290 | #endif /* __KERNEL__ */ | 295 | #endif /* __KERNEL__ */ |
| 296 | #endif /* __ASSEMBLY__ */ | ||
| 291 | #endif /* _ASM_X86_MSR_H */ | 297 | #endif /* _ASM_X86_MSR_H */ |
diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c index 2cfbb4b2c422..7dd950094178 100644 --- a/arch/x86/kernel/msr.c +++ b/arch/x86/kernel/msr.c | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | /* ----------------------------------------------------------------------- * | 1 | /* ----------------------------------------------------------------------- * |
| 2 | * | 2 | * |
| 3 | * Copyright 2000-2008 H. Peter Anvin - All Rights Reserved | 3 | * Copyright 2000-2008 H. Peter Anvin - All Rights Reserved |
| 4 | * Copyright 2009 Intel Corporation; author: H. Peter Anvin | ||
| 4 | * | 5 | * |
| 5 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
| 6 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
| @@ -121,6 +122,54 @@ static ssize_t msr_write(struct file *file, const char __user *buf, | |||
| 121 | return bytes ? bytes : err; | 122 | return bytes ? bytes : err; |
| 122 | } | 123 | } |
| 123 | 124 | ||
| 125 | static long msr_ioctl(struct file *file, unsigned int ioc, unsigned long arg) | ||
| 126 | { | ||
| 127 | u32 __user *uregs = (u32 __user *)arg; | ||
| 128 | u32 regs[8]; | ||
| 129 | int cpu = iminor(file->f_path.dentry->d_inode); | ||
| 130 | int err; | ||
| 131 | |||
| 132 | switch (ioc) { | ||
| 133 | case X86_IOC_RDMSR_REGS: | ||
| 134 | if (!(file->f_mode & FMODE_READ)) { | ||
| 135 | err = -EBADF; | ||
| 136 | break; | ||
| 137 | } | ||
| 138 | if (copy_from_user(®s, uregs, sizeof regs)) { | ||
| 139 | err = -EFAULT; | ||
| 140 | break; | ||
| 141 | } | ||
| 142 | err = rdmsr_safe_regs_on_cpu(cpu, regs); | ||
| 143 | if (err) | ||
| 144 | break; | ||
| 145 | if (copy_to_user(uregs, ®s, sizeof regs)) | ||
| 146 | err = -EFAULT; | ||
| 147 | break; | ||
| 148 | |||
| 149 | case X86_IOC_WRMSR_REGS: | ||
| 150 | if (!(file->f_mode & FMODE_WRITE)) { | ||
| 151 | err = -EBADF; | ||
| 152 | break; | ||
| 153 | } | ||
| 154 | if (copy_from_user(®s, uregs, sizeof regs)) { | ||
| 155 | err = -EFAULT; | ||
| 156 | break; | ||
| 157 | } | ||
| 158 | err = wrmsr_safe_regs_on_cpu(cpu, regs); | ||
| 159 | if (err) | ||
| 160 | break; | ||
| 161 | if (copy_to_user(uregs, ®s, sizeof regs)) | ||
| 162 | err = -EFAULT; | ||
| 163 | break; | ||
| 164 | |||
| 165 | default: | ||
| 166 | err = -ENOTTY; | ||
| 167 | break; | ||
| 168 | } | ||
| 169 | |||
| 170 | return err; | ||
| 171 | } | ||
| 172 | |||
| 124 | static int msr_open(struct inode *inode, struct file *file) | 173 | static int msr_open(struct inode *inode, struct file *file) |
| 125 | { | 174 | { |
| 126 | unsigned int cpu = iminor(file->f_path.dentry->d_inode); | 175 | unsigned int cpu = iminor(file->f_path.dentry->d_inode); |
| @@ -151,6 +200,8 @@ static const struct file_operations msr_fops = { | |||
| 151 | .read = msr_read, | 200 | .read = msr_read, |
| 152 | .write = msr_write, | 201 | .write = msr_write, |
| 153 | .open = msr_open, | 202 | .open = msr_open, |
| 203 | .unlocked_ioctl = msr_ioctl, | ||
| 204 | .compat_ioctl = msr_ioctl, | ||
| 154 | }; | 205 | }; |
| 155 | 206 | ||
| 156 | static int __cpuinit msr_device_create(int cpu) | 207 | static int __cpuinit msr_device_create(int cpu) |
