aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xarch/x86/include/asm/cpu_debug.h16
-rwxr-xr-xarch/x86/kernel/cpu/cpu_debug.c118
2 files changed, 97 insertions, 37 deletions
diff --git a/arch/x86/include/asm/cpu_debug.h b/arch/x86/include/asm/cpu_debug.h
index d24d64fcee04..56f1635e4617 100755
--- a/arch/x86/include/asm/cpu_debug.h
+++ b/arch/x86/include/asm/cpu_debug.h
@@ -171,16 +171,22 @@ struct cpu_private {
171struct cpu_debug_base { 171struct cpu_debug_base {
172 char *name; /* Register name */ 172 char *name; /* Register name */
173 unsigned flag; /* Register flag */ 173 unsigned flag; /* Register flag */
174 unsigned write; /* Register write flag */
174}; 175};
175 176
176struct cpu_cpuX_base { 177/*
177 struct dentry *dentry; /* Register dentry */ 178 * Currently it looks similar to cpu_debug_base but once we add more files
178 int init; /* Register index file */ 179 * cpu_file_base will go in different direction
179}; 180 */
180
181struct cpu_file_base { 181struct cpu_file_base {
182 char *name; /* Register file name */ 182 char *name; /* Register file name */
183 unsigned flag; /* Register file flag */ 183 unsigned flag; /* Register file flag */
184 unsigned write; /* Register write flag */
185};
186
187struct cpu_cpuX_base {
188 struct dentry *dentry; /* Register dentry */
189 int init; /* Register index file */
184}; 190};
185 191
186struct cpu_debug_range { 192struct cpu_debug_range {
diff --git a/arch/x86/kernel/cpu/cpu_debug.c b/arch/x86/kernel/cpu/cpu_debug.c
index 9abbcbd933cc..21c0cf8ced18 100755
--- a/arch/x86/kernel/cpu/cpu_debug.c
+++ b/arch/x86/kernel/cpu/cpu_debug.c
@@ -11,6 +11,7 @@
11#include <linux/seq_file.h> 11#include <linux/seq_file.h>
12#include <linux/debugfs.h> 12#include <linux/debugfs.h>
13#include <linux/kprobes.h> 13#include <linux/kprobes.h>
14#include <linux/uaccess.h>
14#include <linux/kernel.h> 15#include <linux/kernel.h>
15#include <linux/module.h> 16#include <linux/module.h>
16#include <linux/percpu.h> 17#include <linux/percpu.h>
@@ -40,41 +41,41 @@ static DEFINE_MUTEX(cpu_debug_lock);
40static struct dentry *cpu_debugfs_dir; 41static struct dentry *cpu_debugfs_dir;
41 42
42static struct cpu_debug_base cpu_base[] = { 43static struct cpu_debug_base cpu_base[] = {
43 { "mc", CPU_MC }, /* Machine Check */ 44 { "mc", CPU_MC, 0 },
44 { "monitor", CPU_MONITOR }, /* Monitor */ 45 { "monitor", CPU_MONITOR, 0 },
45 { "time", CPU_TIME }, /* Time */ 46 { "time", CPU_TIME, 0 },
46 { "pmc", CPU_PMC }, /* Performance Monitor */ 47 { "pmc", CPU_PMC, 1 },
47 { "platform", CPU_PLATFORM }, /* Platform */ 48 { "platform", CPU_PLATFORM, 0 },
48 { "apic", CPU_APIC }, /* APIC */ 49 { "apic", CPU_APIC, 0 },
49 { "poweron", CPU_POWERON }, /* Power-on */ 50 { "poweron", CPU_POWERON, 0 },
50 { "control", CPU_CONTROL }, /* Control */ 51 { "control", CPU_CONTROL, 0 },
51 { "features", CPU_FEATURES }, /* Features control */ 52 { "features", CPU_FEATURES, 0 },
52 { "lastbranch", CPU_LBRANCH }, /* Last Branch */ 53 { "lastbranch", CPU_LBRANCH, 0 },
53 { "bios", CPU_BIOS }, /* BIOS */ 54 { "bios", CPU_BIOS, 0 },
54 { "freq", CPU_FREQ }, /* Frequency */ 55 { "freq", CPU_FREQ, 0 },
55 { "mtrr", CPU_MTRR }, /* MTRR */ 56 { "mtrr", CPU_MTRR, 0 },
56 { "perf", CPU_PERF }, /* Performance */ 57 { "perf", CPU_PERF, 0 },
57 { "cache", CPU_CACHE }, /* Cache */ 58 { "cache", CPU_CACHE, 0 },
58 { "sysenter", CPU_SYSENTER }, /* Sysenter */ 59 { "sysenter", CPU_SYSENTER, 0 },
59 { "therm", CPU_THERM }, /* Thermal */ 60 { "therm", CPU_THERM, 0 },
60 { "misc", CPU_MISC }, /* Miscellaneous */ 61 { "misc", CPU_MISC, 0 },
61 { "debug", CPU_DEBUG }, /* Debug */ 62 { "debug", CPU_DEBUG, 0 },
62 { "pat", CPU_PAT }, /* PAT */ 63 { "pat", CPU_PAT, 0 },
63 { "vmx", CPU_VMX }, /* VMX */ 64 { "vmx", CPU_VMX, 0 },
64 { "call", CPU_CALL }, /* System Call */ 65 { "call", CPU_CALL, 0 },
65 { "base", CPU_BASE }, /* BASE Address */ 66 { "base", CPU_BASE, 0 },
66 { "smm", CPU_SMM }, /* System mgmt mode */ 67 { "smm", CPU_SMM, 0 },
67 { "svm", CPU_SVM }, /*Secure Virtial Machine*/ 68 { "svm", CPU_SVM, 0 },
68 { "osvm", CPU_OSVM }, /* OS-Visible Workaround*/ 69 { "osvm", CPU_OSVM, 0 },
69 { "tss", CPU_TSS }, /* Task Stack Segment */ 70 { "tss", CPU_TSS, 0 },
70 { "cr", CPU_CR }, /* Control Registers */ 71 { "cr", CPU_CR, 0 },
71 { "dt", CPU_DT }, /* Descriptor Table */ 72 { "dt", CPU_DT, 0 },
72 { "registers", CPU_REG_ALL }, /* Select all Registers */ 73 { "registers", CPU_REG_ALL, 0 },
73}; 74};
74 75
75static struct cpu_file_base cpu_file[] = { 76static struct cpu_file_base cpu_file[] = {
76 { "index", CPU_REG_ALL }, /* index */ 77 { "index", CPU_REG_ALL, 0 },
77 { "value", CPU_REG_ALL }, /* value */ 78 { "value", CPU_REG_ALL, 1 },
78}; 79};
79 80
80/* Intel Registers Range */ 81/* Intel Registers Range */
@@ -608,9 +609,62 @@ static int cpu_seq_open(struct inode *inode, struct file *file)
608 return err; 609 return err;
609} 610}
610 611
612static int write_msr(struct cpu_private *priv, u64 val)
613{
614 u32 low, high;
615
616 high = (val >> 32) & 0xffffffff;
617 low = val & 0xffffffff;
618
619 if (!wrmsr_safe_on_cpu(priv->cpu, priv->reg, low, high))
620 return 0;
621
622 return -EPERM;
623}
624
625static int write_cpu_register(struct cpu_private *priv, const char *buf)
626{
627 int ret = -EPERM;
628 u64 val;
629
630 ret = strict_strtoull(buf, 0, &val);
631 if (ret < 0)
632 return ret;
633
634 /* Supporting only MSRs */
635 if (priv->type < CPU_TSS_BIT)
636 return write_msr(priv, val);
637
638 return ret;
639}
640
641static ssize_t cpu_write(struct file *file, const char __user *ubuf,
642 size_t count, loff_t *off)
643{
644 struct seq_file *seq = file->private_data;
645 struct cpu_private *priv = seq->private;
646 char buf[19];
647
648 if ((priv == NULL) || (count >= sizeof(buf)))
649 return -EINVAL;
650
651 if (copy_from_user(&buf, ubuf, count))
652 return -EFAULT;
653
654 buf[count] = 0;
655
656 if ((cpu_base[priv->type].write) && (cpu_file[priv->file].write))
657 if (!write_cpu_register(priv, buf))
658 return count;
659
660 return -EACCES;
661}
662
611static const struct file_operations cpu_fops = { 663static const struct file_operations cpu_fops = {
664 .owner = THIS_MODULE,
612 .open = cpu_seq_open, 665 .open = cpu_seq_open,
613 .read = seq_read, 666 .read = seq_read,
667 .write = cpu_write,
614 .llseek = seq_lseek, 668 .llseek = seq_lseek,
615 .release = seq_release, 669 .release = seq_release,
616}; 670};