]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - kernel/sysctl.c
UBUNTU: [Config] CONFIG_QCOM_PM8XXX_XOADC=m
[mirror_ubuntu-artful-kernel.git] / kernel / sysctl.c
index 6648fbbb8157fc12703d02fa0fdc9ff85c527ac4..47a37792109dd7b0043cb6f24f0871da707f2a81 100644 (file)
 #include <linux/mount.h>
 
 #include <linux/uaccess.h>
+#include <linux/mutex.h>
 #include <asm/processor.h>
 
 #ifdef CONFIG_X86
+#include <asm/msr.h>
 #include <asm/nmi.h>
 #include <asm/stacktrace.h>
 #include <asm/io.h>
@@ -105,6 +107,9 @@ extern int core_uses_pid;
 extern char core_pattern[];
 extern unsigned int core_pipe_limit;
 #endif
+#ifdef CONFIG_USER_NS
+extern int unprivileged_userns_clone;
+#endif
 extern int pid_max;
 extern int pid_max_min, pid_max_max;
 extern int percpu_pagelist_fraction;
@@ -219,6 +224,15 @@ static int proc_dostring_coredump(struct ctl_table *table, int write,
                void __user *buffer, size_t *lenp, loff_t *ppos);
 #endif
 
+#ifdef CONFIG_X86
+int proc_dointvec_ibrs_ctrl(struct ctl_table *table, int write,
+                 void __user *buffer, size_t *lenp, loff_t *ppos);
+int proc_dointvec_ibpb_ctrl(struct ctl_table *table, int write,
+                 void __user *buffer, size_t *lenp, loff_t *ppos);
+int proc_dointvec_ibrs_dump(struct ctl_table *table, int write,
+                 void __user *buffer, size_t *lenp, loff_t *ppos);
+#endif
+
 #ifdef CONFIG_MAGIC_SYSRQ
 /* Note: sysrq code uses it's own private copy */
 static int __sysrq_enabled = CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE;
@@ -255,6 +269,12 @@ extern struct ctl_table epoll_table[];
 int sysctl_legacy_va_layout;
 #endif
 
+u32 sysctl_ibrs_dump = 0;
+u32 sysctl_ibrs_enabled = 0;
+EXPORT_SYMBOL(sysctl_ibrs_enabled);
+u32 sysctl_ibpb_enabled = 0;
+EXPORT_SYMBOL(sysctl_ibpb_enabled);
+
 /* The default sysctl tables: */
 
 static struct ctl_table sysctl_base_table[] = {
@@ -367,7 +387,8 @@ static struct ctl_table kern_table[] = {
                .data           = &sysctl_sched_time_avg,
                .maxlen         = sizeof(unsigned int),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec,
+               .proc_handler   = proc_dointvec_minmax,
+               .extra1         = &one,
        },
 #ifdef CONFIG_SCHEDSTATS
        {
@@ -512,6 +533,15 @@ static struct ctl_table kern_table[] = {
                .proc_handler   = proc_dointvec,
        },
 #endif
+#ifdef CONFIG_USER_NS
+       {
+               .procname       = "unprivileged_userns_clone",
+               .data           = &unprivileged_userns_clone,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec,
+       },
+#endif
 #ifdef CONFIG_PROC_SYSCTL
        {
                .procname       = "tainted",
@@ -1228,6 +1258,35 @@ static struct ctl_table kern_table[] = {
                .extra1         = &zero,
                .extra2         = &one,
        },
+#endif
+#ifdef CONFIG_X86
+       {
+               .procname       = "ibrs_enabled",
+               .data           = &sysctl_ibrs_enabled,
+               .maxlen         = sizeof(unsigned int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec_ibrs_ctrl,
+               .extra1         = &zero,
+               .extra2         = &two,
+       },
+       {
+               .procname       = "ibpb_enabled",
+               .data           = &sysctl_ibpb_enabled,
+               .maxlen         = sizeof(unsigned int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec_ibpb_ctrl,
+               .extra1         = &zero,
+               .extra2         = &one,
+       },
+       {
+               .procname       = "ibrs_dump",
+               .data           = &sysctl_ibrs_dump,
+               .maxlen         = sizeof(unsigned int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec_ibrs_dump,
+               .extra1         = &zero,
+               .extra2         = &one,
+       },
 #endif
        { }
 };
@@ -2572,6 +2631,97 @@ int proc_dointvec_minmax(struct ctl_table *table, int write,
                                do_proc_dointvec_minmax_conv, &param);
 }
 
+#ifdef CONFIG_X86
+int proc_dointvec_ibrs_dump(struct ctl_table *table, int write,
+       void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       int ret, orig_inuse;
+       unsigned int cpu;
+
+
+       ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+       printk("sysctl_ibrs_enabled = %u, sysctl_ibpb_enabled = %u\n", sysctl_ibrs_enabled, sysctl_ibpb_enabled);
+       printk("use_ibrs = %d, use_ibpb = %d\n", use_ibrs, use_ibpb);
+       mutex_lock(&spec_ctrl_mutex);
+       orig_inuse = use_ibrs;
+       /* temporary halt to ibrs usage to dump ibrs values */
+       clear_ibrs_inuse();
+       for_each_online_cpu(cpu) {
+              u64 val;
+
+              if (boot_cpu_has(X86_FEATURE_SPEC_CTRL))
+                      rdmsrl_on_cpu(cpu, MSR_IA32_SPEC_CTRL, &val);
+              else
+                      val = 0;
+              printk("read cpu %d ibrs val %lu\n", cpu, (unsigned long) val);
+       }
+       use_ibrs = orig_inuse;
+       mutex_unlock(&spec_ctrl_mutex);
+       return ret;
+}
+
+int proc_dointvec_ibrs_ctrl(struct ctl_table *table, int write,
+       void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       int ret;
+       unsigned int cpu;
+
+       ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+       pr_debug("sysctl_ibrs_enabled = %u, sysctl_ibpb_enabled = %u\n", sysctl_ibrs_enabled, sysctl_ibpb_enabled);
+       pr_debug("before:use_ibrs = %d, use_ibpb = %d\n", use_ibrs, use_ibpb);
+       mutex_lock(&spec_ctrl_mutex);
+       if (sysctl_ibrs_enabled == 0) {
+               /* always set IBRS off */
+               set_ibrs_disabled();
+               if (ibrs_supported) {
+                       for_each_online_cpu(cpu)
+                               wrmsrl_on_cpu(cpu, MSR_IA32_SPEC_CTRL, 0x0);
+               }
+       } else if (sysctl_ibrs_enabled == 2) {
+               /* always set IBRS on, even in user space */
+               clear_ibrs_disabled();
+               if (ibrs_supported) {
+                       for_each_online_cpu(cpu)
+                               wrmsrl_on_cpu(cpu, MSR_IA32_SPEC_CTRL, FEATURE_ENABLE_IBRS);
+               } else {
+                       sysctl_ibrs_enabled = 0;
+               }
+       } else if (sysctl_ibrs_enabled == 1) {
+               /* use IBRS in kernel */
+               clear_ibrs_disabled();
+               if (!ibrs_inuse)
+                       /* platform don't support ibrs */
+                       sysctl_ibrs_enabled = 0;
+       }
+       mutex_unlock(&spec_ctrl_mutex);
+       pr_debug("after:use_ibrs = %d, use_ibpb = %d\n", use_ibrs, use_ibpb);
+       return ret;
+}
+
+int proc_dointvec_ibpb_ctrl(struct ctl_table *table, int write,
+       void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       int ret;
+
+       ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+       pr_debug("sysctl_ibrs_enabled = %u, sysctl_ibpb_enabled = %u\n", sysctl_ibrs_enabled, sysctl_ibpb_enabled);
+       pr_debug("before:use_ibrs = %d, use_ibpb = %d\n", use_ibrs, use_ibpb);
+       mutex_lock(&spec_ctrl_mutex);
+       if (sysctl_ibpb_enabled == 0)
+               set_ibpb_disabled();
+       else if (sysctl_ibpb_enabled == 1) {
+               clear_ibpb_disabled();
+               if (!ibpb_inuse)
+                       /* platform don't support ibpb */
+                       sysctl_ibpb_enabled = 0;
+       }
+       mutex_unlock(&spec_ctrl_mutex);
+       pr_debug("after:use_ibrs = %d, use_ibpb = %d\n", use_ibrs, use_ibpb);
+       return ret;
+}
+#endif
+
+
 struct do_proc_douintvec_minmax_conv_param {
        unsigned int *min;
        unsigned int *max;