#include <linux/seq_file.h>
 #include <linux/debugfs.h>
 #include <linux/kprobes.h>
+#include <linux/uaccess.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/percpu.h>
 static struct dentry *cpu_debugfs_dir;
 
 static struct cpu_debug_base cpu_base[] = {
-       { "mc",         CPU_MC          },      /* Machine Check        */
-       { "monitor",    CPU_MONITOR     },      /* Monitor              */
-       { "time",       CPU_TIME        },      /* Time                 */
-       { "pmc",        CPU_PMC         },      /* Performance Monitor  */
-       { "platform",   CPU_PLATFORM    },      /* Platform             */
-       { "apic",       CPU_APIC        },      /* APIC                 */
-       { "poweron",    CPU_POWERON     },      /* Power-on             */
-       { "control",    CPU_CONTROL     },      /* Control              */
-       { "features",   CPU_FEATURES    },      /* Features control     */
-       { "lastbranch", CPU_LBRANCH     },      /* Last Branch          */
-       { "bios",       CPU_BIOS        },      /* BIOS                 */
-       { "freq",       CPU_FREQ        },      /* Frequency            */
-       { "mtrr",       CPU_MTRR        },      /* MTRR                 */
-       { "perf",       CPU_PERF        },      /* Performance          */
-       { "cache",      CPU_CACHE       },      /* Cache                */
-       { "sysenter",   CPU_SYSENTER    },      /* Sysenter             */
-       { "therm",      CPU_THERM       },      /* Thermal              */
-       { "misc",       CPU_MISC        },      /* Miscellaneous        */
-       { "debug",      CPU_DEBUG       },      /* Debug                */
-       { "pat",        CPU_PAT         },      /* PAT                  */
-       { "vmx",        CPU_VMX         },      /* VMX                  */
-       { "call",       CPU_CALL        },      /* System Call          */
-       { "base",       CPU_BASE        },      /* BASE Address         */
-       { "smm",        CPU_SMM         },      /* System mgmt mode     */
-       { "svm",        CPU_SVM         },      /*Secure Virtial Machine*/
-       { "osvm",       CPU_OSVM        },      /* OS-Visible Workaround*/
-       { "tss",        CPU_TSS         },      /* Task Stack Segment   */
-       { "cr",         CPU_CR          },      /* Control Registers    */
-       { "dt",         CPU_DT          },      /* Descriptor Table     */
-       { "registers",  CPU_REG_ALL     },      /* Select all Registers */
+       { "mc",         CPU_MC,         0       },
+       { "monitor",    CPU_MONITOR,    0       },
+       { "time",       CPU_TIME,       0       },
+       { "pmc",        CPU_PMC,        1       },
+       { "platform",   CPU_PLATFORM,   0       },
+       { "apic",       CPU_APIC,       0       },
+       { "poweron",    CPU_POWERON,    0       },
+       { "control",    CPU_CONTROL,    0       },
+       { "features",   CPU_FEATURES,   0       },
+       { "lastbranch", CPU_LBRANCH,    0       },
+       { "bios",       CPU_BIOS,       0       },
+       { "freq",       CPU_FREQ,       0       },
+       { "mtrr",       CPU_MTRR,       0       },
+       { "perf",       CPU_PERF,       0       },
+       { "cache",      CPU_CACHE,      0       },
+       { "sysenter",   CPU_SYSENTER,   0       },
+       { "therm",      CPU_THERM,      0       },
+       { "misc",       CPU_MISC,       0       },
+       { "debug",      CPU_DEBUG,      0       },
+       { "pat",        CPU_PAT,        0       },
+       { "vmx",        CPU_VMX,        0       },
+       { "call",       CPU_CALL,       0       },
+       { "base",       CPU_BASE,       0       },
+       { "smm",        CPU_SMM,        0       },
+       { "svm",        CPU_SVM,        0       },
+       { "osvm",       CPU_OSVM,       0       },
+       { "tss",        CPU_TSS,        0       },
+       { "cr",         CPU_CR,         0       },
+       { "dt",         CPU_DT,         0       },
+       { "registers",  CPU_REG_ALL,    0       },
 };
 
 static struct cpu_file_base cpu_file[] = {
-       { "index",      CPU_REG_ALL     },      /* index                */
-       { "value",      CPU_REG_ALL     },      /* value                */
+       { "index",      CPU_REG_ALL,    0       },
+       { "value",      CPU_REG_ALL,    1       },
 };
 
 /* Intel Registers Range */
        return err;
 }
 
+static int write_msr(struct cpu_private *priv, u64 val)
+{
+       u32 low, high;
+
+       high = (val >> 32) & 0xffffffff;
+       low = val & 0xffffffff;
+
+       if (!wrmsr_safe_on_cpu(priv->cpu, priv->reg, low, high))
+               return 0;
+
+       return -EPERM;
+}
+
+static int write_cpu_register(struct cpu_private *priv, const char *buf)
+{
+       int ret = -EPERM;
+       u64 val;
+
+       ret = strict_strtoull(buf, 0, &val);
+       if (ret < 0)
+               return ret;
+
+       /* Supporting only MSRs */
+       if (priv->type < CPU_TSS_BIT)
+               return write_msr(priv, val);
+
+       return ret;
+}
+
+static ssize_t cpu_write(struct file *file, const char __user *ubuf,
+                            size_t count, loff_t *off)
+{
+       struct seq_file *seq = file->private_data;
+       struct cpu_private *priv = seq->private;
+       char buf[19];
+
+       if ((priv == NULL) || (count >= sizeof(buf)))
+               return -EINVAL;
+
+       if (copy_from_user(&buf, ubuf, count))
+               return -EFAULT;
+
+       buf[count] = 0;
+
+       if ((cpu_base[priv->type].write) && (cpu_file[priv->file].write))
+               if (!write_cpu_register(priv, buf))
+                       return count;
+
+       return -EACCES;
+}
+
 static const struct file_operations cpu_fops = {
+       .owner          = THIS_MODULE,
        .open           = cpu_seq_open,
        .read           = seq_read,
+       .write          = cpu_write,
        .llseek         = seq_lseek,
        .release        = seq_release,
 };