]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 20 Feb 2014 22:42:40 +0000 (14:42 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 20 Feb 2014 22:42:40 +0000 (14:42 -0800)
added patches:
ftrace-x86-use-breakpoints-for-converting-function-graph-caller.patch
iio-adis16400-set-timestamp-as-the-last-element-in-chan_spec.patch
iio-max1363-use-devm_regulator_get_optional-for-optional-regulator.patch
staging-comedi-adv_pci1710-fix-analog-output-readback-value.patch
staging-iio-ad799x-fix-error_free_irq-which-was-freeing-an-irq-that-may-not-have-been-requested.patch
x86-smap-don-t-enable-smap-if-config_x86_smap-is-disabled.patch
x86-smap-smap_violation-is-bogus-if-config_x86_smap-is-off.patch

queue-3.10/ftrace-x86-use-breakpoints-for-converting-function-graph-caller.patch [new file with mode: 0644]
queue-3.10/iio-adis16400-set-timestamp-as-the-last-element-in-chan_spec.patch [new file with mode: 0644]
queue-3.10/iio-max1363-use-devm_regulator_get_optional-for-optional-regulator.patch [new file with mode: 0644]
queue-3.10/series
queue-3.10/staging-comedi-adv_pci1710-fix-analog-output-readback-value.patch [new file with mode: 0644]
queue-3.10/staging-iio-ad799x-fix-error_free_irq-which-was-freeing-an-irq-that-may-not-have-been-requested.patch [new file with mode: 0644]
queue-3.10/x86-smap-don-t-enable-smap-if-config_x86_smap-is-disabled.patch [new file with mode: 0644]
queue-3.10/x86-smap-smap_violation-is-bogus-if-config_x86_smap-is-off.patch [new file with mode: 0644]

diff --git a/queue-3.10/ftrace-x86-use-breakpoints-for-converting-function-graph-caller.patch b/queue-3.10/ftrace-x86-use-breakpoints-for-converting-function-graph-caller.patch
new file mode 100644 (file)
index 0000000..924e41a
--- /dev/null
@@ -0,0 +1,189 @@
+From 87fbb2ac6073a7039303517546a76074feb14c84 Mon Sep 17 00:00:00 2001
+From: "Steven Rostedt (Red Hat)" <rostedt@goodmis.org>
+Date: Tue, 11 Feb 2014 20:19:44 -0500
+Subject: ftrace/x86: Use breakpoints for converting function graph caller
+
+From: "Steven Rostedt (Red Hat)" <rostedt@goodmis.org>
+
+commit 87fbb2ac6073a7039303517546a76074feb14c84 upstream.
+
+When the conversion was made to remove stop machine and use the breakpoint
+logic instead, the modification of the function graph caller is still
+done directly as though it was being done under stop machine.
+
+As it is not converted via stop machine anymore, there is a possibility
+that the code could be layed across cache lines and if another CPU is
+accessing that function graph call when it is being updated, it could
+cause a General Protection Fault.
+
+Convert the update of the function graph caller to use the breakpoint
+method as well.
+
+Cc: H. Peter Anvin <hpa@zytor.com>
+Fixes: 08d636b6d4fb "ftrace/x86: Have arch x86_64 use breakpoints instead of stop machine"
+Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/kernel/ftrace.c |   83 ++++++++++++++++++++++++++---------------------
+ 1 file changed, 47 insertions(+), 36 deletions(-)
+
+--- a/arch/x86/kernel/ftrace.c
++++ b/arch/x86/kernel/ftrace.c
+@@ -77,8 +77,7 @@ within(unsigned long addr, unsigned long
+       return addr >= start && addr < end;
+ }
+-static int
+-do_ftrace_mod_code(unsigned long ip, const void *new_code)
++static unsigned long text_ip_addr(unsigned long ip)
+ {
+       /*
+        * On x86_64, kernel text mappings are mapped read-only with
+@@ -91,7 +90,7 @@ do_ftrace_mod_code(unsigned long ip, con
+       if (within(ip, (unsigned long)_text, (unsigned long)_etext))
+               ip = (unsigned long)__va(__pa_symbol(ip));
+-      return probe_kernel_write((void *)ip, new_code, MCOUNT_INSN_SIZE);
++      return ip;
+ }
+ static const unsigned char *ftrace_nop_replace(void)
+@@ -123,8 +122,10 @@ ftrace_modify_code_direct(unsigned long
+       if (memcmp(replaced, old_code, MCOUNT_INSN_SIZE) != 0)
+               return -EINVAL;
++      ip = text_ip_addr(ip);
++
+       /* replace the text with the new text */
+-      if (do_ftrace_mod_code(ip, new_code))
++      if (probe_kernel_write((void *)ip, new_code, MCOUNT_INSN_SIZE))
+               return -EPERM;
+       sync_core();
+@@ -221,37 +222,51 @@ int ftrace_modify_call(struct dyn_ftrace
+       return -EINVAL;
+ }
+-int ftrace_update_ftrace_func(ftrace_func_t func)
++static unsigned long ftrace_update_func;
++
++static int update_ftrace_func(unsigned long ip, void *new)
+ {
+-      unsigned long ip = (unsigned long)(&ftrace_call);
+-      unsigned char old[MCOUNT_INSN_SIZE], *new;
++      unsigned char old[MCOUNT_INSN_SIZE];
+       int ret;
+-      memcpy(old, &ftrace_call, MCOUNT_INSN_SIZE);
+-      new = ftrace_call_replace(ip, (unsigned long)func);
++      memcpy(old, (void *)ip, MCOUNT_INSN_SIZE);
++
++      ftrace_update_func = ip;
++      /* Make sure the breakpoints see the ftrace_update_func update */
++      smp_wmb();
+       /* See comment above by declaration of modifying_ftrace_code */
+       atomic_inc(&modifying_ftrace_code);
+       ret = ftrace_modify_code(ip, old, new);
++      atomic_dec(&modifying_ftrace_code);
++
++      return ret;
++}
++
++int ftrace_update_ftrace_func(ftrace_func_t func)
++{
++      unsigned long ip = (unsigned long)(&ftrace_call);
++      unsigned char *new;
++      int ret;
++
++      new = ftrace_call_replace(ip, (unsigned long)func);
++      ret = update_ftrace_func(ip, new);
++
+       /* Also update the regs callback function */
+       if (!ret) {
+               ip = (unsigned long)(&ftrace_regs_call);
+-              memcpy(old, &ftrace_regs_call, MCOUNT_INSN_SIZE);
+               new = ftrace_call_replace(ip, (unsigned long)func);
+-              ret = ftrace_modify_code(ip, old, new);
++              ret = update_ftrace_func(ip, new);
+       }
+-      atomic_dec(&modifying_ftrace_code);
+-
+       return ret;
+ }
+ static int is_ftrace_caller(unsigned long ip)
+ {
+-      if (ip == (unsigned long)(&ftrace_call) ||
+-              ip == (unsigned long)(&ftrace_regs_call))
++      if (ip == ftrace_update_func)
+               return 1;
+       return 0;
+@@ -677,45 +692,41 @@ int __init ftrace_dyn_arch_init(void *da
+ #ifdef CONFIG_DYNAMIC_FTRACE
+ extern void ftrace_graph_call(void);
+-static int ftrace_mod_jmp(unsigned long ip,
+-                        int old_offset, int new_offset)
++static unsigned char *ftrace_jmp_replace(unsigned long ip, unsigned long addr)
+ {
+-      unsigned char code[MCOUNT_INSN_SIZE];
++      static union ftrace_code_union calc;
+-      if (probe_kernel_read(code, (void *)ip, MCOUNT_INSN_SIZE))
+-              return -EFAULT;
++      /* Jmp not a call (ignore the .e8) */
++      calc.e8         = 0xe9;
++      calc.offset     = ftrace_calc_offset(ip + MCOUNT_INSN_SIZE, addr);
+-      if (code[0] != 0xe9 || old_offset != *(int *)(&code[1]))
+-              return -EINVAL;
++      /*
++       * ftrace external locks synchronize the access to the static variable.
++       */
++      return calc.code;
++}
+-      *(int *)(&code[1]) = new_offset;
++static int ftrace_mod_jmp(unsigned long ip, void *func)
++{
++      unsigned char *new;
+-      if (do_ftrace_mod_code(ip, &code))
+-              return -EPERM;
++      new = ftrace_jmp_replace(ip, (unsigned long)func);
+-      return 0;
++      return update_ftrace_func(ip, new);
+ }
+ int ftrace_enable_ftrace_graph_caller(void)
+ {
+       unsigned long ip = (unsigned long)(&ftrace_graph_call);
+-      int old_offset, new_offset;
+-
+-      old_offset = (unsigned long)(&ftrace_stub) - (ip + MCOUNT_INSN_SIZE);
+-      new_offset = (unsigned long)(&ftrace_graph_caller) - (ip + MCOUNT_INSN_SIZE);
+-      return ftrace_mod_jmp(ip, old_offset, new_offset);
++      return ftrace_mod_jmp(ip, &ftrace_graph_caller);
+ }
+ int ftrace_disable_ftrace_graph_caller(void)
+ {
+       unsigned long ip = (unsigned long)(&ftrace_graph_call);
+-      int old_offset, new_offset;
+-
+-      old_offset = (unsigned long)(&ftrace_graph_caller) - (ip + MCOUNT_INSN_SIZE);
+-      new_offset = (unsigned long)(&ftrace_stub) - (ip + MCOUNT_INSN_SIZE);
+-      return ftrace_mod_jmp(ip, old_offset, new_offset);
++      return ftrace_mod_jmp(ip, &ftrace_stub);
+ }
+ #endif /* !CONFIG_DYNAMIC_FTRACE */
diff --git a/queue-3.10/iio-adis16400-set-timestamp-as-the-last-element-in-chan_spec.patch b/queue-3.10/iio-adis16400-set-timestamp-as-the-last-element-in-chan_spec.patch
new file mode 100644 (file)
index 0000000..670de18
--- /dev/null
@@ -0,0 +1,82 @@
+From c76782d151dab7ecfdcdf9a01561c2d61d9b490f Mon Sep 17 00:00:00 2001
+From: Marcus Folkesson <marcus.folkesson@gmail.com>
+Date: Fri, 24 Jan 2014 11:24:00 +0000
+Subject: iio: adis16400: Set timestamp as the last element in chan_spec
+
+From: Marcus Folkesson <marcus.folkesson@gmail.com>
+
+commit c76782d151dab7ecfdcdf9a01561c2d61d9b490f upstream.
+
+This is necessary since timestamp is calculated as the last element
+in iio_compute_scan_bytes().
+
+Without this fix any userspace code reading the layout of the buffer via
+sysfs will incorrectly interpret the data leading some nasty corruption.
+
+Signed-off-by: Marcus Folkesson <marcus.folkesson@gmail.com>
+Acked-by: Lars-Peter Clausen <lars@metafoo.de>
+Signed-off-by: Jonathan Cameron <jic23@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/iio/imu/adis16400.h      |    1 +
+ drivers/iio/imu/adis16400_core.c |   10 +++++-----
+ 2 files changed, 6 insertions(+), 5 deletions(-)
+
+--- a/drivers/iio/imu/adis16400.h
++++ b/drivers/iio/imu/adis16400.h
+@@ -189,6 +189,7 @@ enum {
+       ADIS16300_SCAN_INCLI_X,
+       ADIS16300_SCAN_INCLI_Y,
+       ADIS16400_SCAN_ADC,
++      ADIS16400_SCAN_TIMESTAMP,
+ };
+ #ifdef CONFIG_IIO_BUFFER
+--- a/drivers/iio/imu/adis16400_core.c
++++ b/drivers/iio/imu/adis16400_core.c
+@@ -632,7 +632,7 @@ static const struct iio_chan_spec adis16
+       ADIS16400_MAGN_CHAN(Z, ADIS16400_ZMAGN_OUT, 14),
+       ADIS16400_TEMP_CHAN(ADIS16400_TEMP_OUT, 12),
+       ADIS16400_AUX_ADC_CHAN(ADIS16400_AUX_ADC, 12),
+-      IIO_CHAN_SOFT_TIMESTAMP(12)
++      IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP),
+ };
+ static const struct iio_chan_spec adis16448_channels[] = {
+@@ -659,7 +659,7 @@ static const struct iio_chan_spec adis16
+               },
+       },
+       ADIS16400_TEMP_CHAN(ADIS16448_TEMP_OUT, 12),
+-      IIO_CHAN_SOFT_TIMESTAMP(11)
++      IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP),
+ };
+ static const struct iio_chan_spec adis16350_channels[] = {
+@@ -677,7 +677,7 @@ static const struct iio_chan_spec adis16
+       ADIS16400_MOD_TEMP_CHAN(X, ADIS16350_XTEMP_OUT, 12),
+       ADIS16400_MOD_TEMP_CHAN(Y, ADIS16350_YTEMP_OUT, 12),
+       ADIS16400_MOD_TEMP_CHAN(Z, ADIS16350_ZTEMP_OUT, 12),
+-      IIO_CHAN_SOFT_TIMESTAMP(11)
++      IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP),
+ };
+ static const struct iio_chan_spec adis16300_channels[] = {
+@@ -690,7 +690,7 @@ static const struct iio_chan_spec adis16
+       ADIS16400_AUX_ADC_CHAN(ADIS16300_AUX_ADC, 12),
+       ADIS16400_INCLI_CHAN(X, ADIS16300_PITCH_OUT, 13),
+       ADIS16400_INCLI_CHAN(Y, ADIS16300_ROLL_OUT, 13),
+-      IIO_CHAN_SOFT_TIMESTAMP(14)
++      IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP),
+ };
+ static const struct iio_chan_spec adis16334_channels[] = {
+@@ -701,7 +701,7 @@ static const struct iio_chan_spec adis16
+       ADIS16400_ACCEL_CHAN(Y, ADIS16400_YACCL_OUT, 14),
+       ADIS16400_ACCEL_CHAN(Z, ADIS16400_ZACCL_OUT, 14),
+       ADIS16400_TEMP_CHAN(ADIS16350_XTEMP_OUT, 12),
+-      IIO_CHAN_SOFT_TIMESTAMP(8)
++      IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP),
+ };
+ static struct attribute *adis16400_attributes[] = {
diff --git a/queue-3.10/iio-max1363-use-devm_regulator_get_optional-for-optional-regulator.patch b/queue-3.10/iio-max1363-use-devm_regulator_get_optional-for-optional-regulator.patch
new file mode 100644 (file)
index 0000000..cb85623
--- /dev/null
@@ -0,0 +1,35 @@
+From 55b40d37311807a6bb2acdae0df904f54a0da3ae Mon Sep 17 00:00:00 2001
+From: Guenter Roeck <linux@roeck-us.net>
+Date: Mon, 27 Jan 2014 18:10:00 +0000
+Subject: iio: max1363: Use devm_regulator_get_optional for optional regulator
+
+From: Guenter Roeck <linux@roeck-us.net>
+
+commit 55b40d37311807a6bb2acdae0df904f54a0da3ae upstream.
+
+In kernel version 3.13, devm_regulator_get() may return no error
+if a regulator is undeclared. regulator_get_voltage() will return
+-EINVAL if this happens. This causes the driver to fail loading if
+the vref regulator is not declared.
+
+Since vref is optional, call devm_regulator_get_optional instead.
+
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Jonathan Cameron <jic23@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/iio/adc/max1363.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/iio/adc/max1363.c
++++ b/drivers/iio/adc/max1363.c
+@@ -1528,7 +1528,7 @@ static int max1363_probe(struct i2c_clie
+       st->client = client;
+       st->vref_uv = st->chip_info->int_vref_mv * 1000;
+-      vref = devm_regulator_get(&client->dev, "vref");
++      vref = devm_regulator_get_optional(&client->dev, "vref");
+       if (!IS_ERR(vref)) {
+               int vref_uv;
index 73e57fe4ea3f273669874f5ac241d233fb2e2347..a86911fc8cef64ffba783b6941c3b4c0a2bb39b5 100644 (file)
@@ -27,3 +27,10 @@ drm-radeon-fix-uvd-irq-support-on-7xx.patch
 drm-radeon-fix-uvd-irq-support-on-si.patch
 vt-fix-secure-clear-screen.patch
 usb-qcserial-add-netgear-aircard-340u.patch
+staging-comedi-adv_pci1710-fix-analog-output-readback-value.patch
+staging-iio-ad799x-fix-error_free_irq-which-was-freeing-an-irq-that-may-not-have-been-requested.patch
+iio-max1363-use-devm_regulator_get_optional-for-optional-regulator.patch
+iio-adis16400-set-timestamp-as-the-last-element-in-chan_spec.patch
+x86-smap-don-t-enable-smap-if-config_x86_smap-is-disabled.patch
+x86-smap-smap_violation-is-bogus-if-config_x86_smap-is-off.patch
+ftrace-x86-use-breakpoints-for-converting-function-graph-caller.patch
diff --git a/queue-3.10/staging-comedi-adv_pci1710-fix-analog-output-readback-value.patch b/queue-3.10/staging-comedi-adv_pci1710-fix-analog-output-readback-value.patch
new file mode 100644 (file)
index 0000000..49d662f
--- /dev/null
@@ -0,0 +1,85 @@
+From 1e85c1ea1ff2a60659e790ef8ec76c7339445841 Mon Sep 17 00:00:00 2001
+From: H Hartley Sweeten <hsweeten@visionengravers.com>
+Date: Wed, 5 Feb 2014 14:59:53 -0700
+Subject: staging: comedi: adv_pci1710: fix analog output readback value
+
+From: H Hartley Sweeten <hsweeten@visionengravers.com>
+
+commit 1e85c1ea1ff2a60659e790ef8ec76c7339445841 upstream.
+
+The last value written to a analog output channel is cached in the
+private data of this driver for readback.
+
+Currently, the wrong value is cached in the (*insn_write) functions.
+The current code stores the data[n] value for readback afer the loop
+has written all the values. At this time 'n' points past the end of
+the data array.
+
+Fix the functions by using a local variable to hold the data being
+written to the analog output channel. This variable is then used
+after the loop is complete to store the readback value. The current
+value is retrieved before the loop in case no values are actually
+written..
+
+Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com>
+Reviewed-by: Ian Abbott <abbotti@mev.co.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/comedi/drivers/adv_pci1710.c |   17 ++++++++++++-----
+ 1 file changed, 12 insertions(+), 5 deletions(-)
+
+--- a/drivers/staging/comedi/drivers/adv_pci1710.c
++++ b/drivers/staging/comedi/drivers/adv_pci1710.c
+@@ -489,6 +489,7 @@ static int pci171x_insn_write_ao(struct
+                                struct comedi_insn *insn, unsigned int *data)
+ {
+       struct pci1710_private *devpriv = dev->private;
++      unsigned int val;
+       int n, chan, range, ofs;
+       chan = CR_CHAN(insn->chanspec);
+@@ -504,11 +505,14 @@ static int pci171x_insn_write_ao(struct
+               outw(devpriv->da_ranges, dev->iobase + PCI171x_DAREF);
+               ofs = PCI171x_DA1;
+       }
++      val = devpriv->ao_data[chan];
+-      for (n = 0; n < insn->n; n++)
+-              outw(data[n], dev->iobase + ofs);
++      for (n = 0; n < insn->n; n++) {
++              val = data[n];
++              outw(val, dev->iobase + ofs);
++      }
+-      devpriv->ao_data[chan] = data[n];
++      devpriv->ao_data[chan] = val;
+       return n;
+@@ -678,6 +682,7 @@ static int pci1720_insn_write_ao(struct
+                                struct comedi_insn *insn, unsigned int *data)
+ {
+       struct pci1710_private *devpriv = dev->private;
++      unsigned int val;
+       int n, rangereg, chan;
+       chan = CR_CHAN(insn->chanspec);
+@@ -687,13 +692,15 @@ static int pci1720_insn_write_ao(struct
+               outb(rangereg, dev->iobase + PCI1720_RANGE);
+               devpriv->da_ranges = rangereg;
+       }
++      val = devpriv->ao_data[chan];
+       for (n = 0; n < insn->n; n++) {
+-              outw(data[n], dev->iobase + PCI1720_DA0 + (chan << 1));
++              val = data[n];
++              outw(val, dev->iobase + PCI1720_DA0 + (chan << 1));
+               outb(0, dev->iobase + PCI1720_SYNCOUT); /*  update outputs */
+       }
+-      devpriv->ao_data[chan] = data[n];
++      devpriv->ao_data[chan] = val;
+       return n;
+ }
diff --git a/queue-3.10/staging-iio-ad799x-fix-error_free_irq-which-was-freeing-an-irq-that-may-not-have-been-requested.patch b/queue-3.10/staging-iio-ad799x-fix-error_free_irq-which-was-freeing-an-irq-that-may-not-have-been-requested.patch
new file mode 100644 (file)
index 0000000..1eb2c5f
--- /dev/null
@@ -0,0 +1,32 @@
+From 38408d056188be29a6c4e17f3703c796551bb330 Mon Sep 17 00:00:00 2001
+From: Hartmut Knaack <knaack.h@gmx.de>
+Date: Wed, 1 Jan 2014 23:04:00 +0000
+Subject: staging:iio:ad799x fix error_free_irq which was freeing an irq that may not have been requested
+
+From: Hartmut Knaack <knaack.h@gmx.de>
+
+commit 38408d056188be29a6c4e17f3703c796551bb330 upstream.
+
+Only free an IRQ in error_free_irq, if it has been requested previously.
+
+Signed-off-by: Hartmut Knaack <knaack.h@gmx.de>
+Acked-by: Lars-Peter Clausen <lars@metafoo.de>
+Signed-off-by: Jonathan Cameron <jic23@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/iio/adc/ad799x_core.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/staging/iio/adc/ad799x_core.c
++++ b/drivers/staging/iio/adc/ad799x_core.c
+@@ -644,7 +644,8 @@ static int ad799x_probe(struct i2c_clien
+       return 0;
+ error_free_irq:
+-      free_irq(client->irq, indio_dev);
++      if (client->irq > 0)
++              free_irq(client->irq, indio_dev);
+ error_cleanup_ring:
+       ad799x_ring_cleanup(indio_dev);
+ error_disable_reg:
diff --git a/queue-3.10/x86-smap-don-t-enable-smap-if-config_x86_smap-is-disabled.patch b/queue-3.10/x86-smap-don-t-enable-smap-if-config_x86_smap-is-disabled.patch
new file mode 100644 (file)
index 0000000..986fb15
--- /dev/null
@@ -0,0 +1,41 @@
+From 03bbd596ac04fef47ce93a730b8f086d797c3021 Mon Sep 17 00:00:00 2001
+From: "H. Peter Anvin" <hpa@linux.intel.com>
+Date: Thu, 13 Feb 2014 07:34:30 -0800
+Subject: x86, smap: Don't enable SMAP if CONFIG_X86_SMAP is disabled
+
+From: "H. Peter Anvin" <hpa@linux.intel.com>
+
+commit 03bbd596ac04fef47ce93a730b8f086d797c3021 upstream.
+
+If SMAP support is not compiled into the kernel, don't enable SMAP in
+CR4 -- in fact, we should clear it, because the kernel doesn't contain
+the proper STAC/CLAC instructions for SMAP support.
+
+Found by Fengguang Wu's test system.
+
+Reported-by: Fengguang Wu <fengguang.wu@intel.com>
+Link: http://lkml.kernel.org/r/20140213124550.GA30497@localhost
+Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/kernel/cpu/common.c |    7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/arch/x86/kernel/cpu/common.c
++++ b/arch/x86/kernel/cpu/common.c
+@@ -284,8 +284,13 @@ static __always_inline void setup_smap(s
+       raw_local_save_flags(eflags);
+       BUG_ON(eflags & X86_EFLAGS_AC);
+-      if (cpu_has(c, X86_FEATURE_SMAP))
++      if (cpu_has(c, X86_FEATURE_SMAP)) {
++#ifdef CONFIG_X86_SMAP
+               set_in_cr4(X86_CR4_SMAP);
++#else
++              clear_in_cr4(X86_CR4_SMAP);
++#endif
++      }
+ }
+ /*
diff --git a/queue-3.10/x86-smap-smap_violation-is-bogus-if-config_x86_smap-is-off.patch b/queue-3.10/x86-smap-smap_violation-is-bogus-if-config_x86_smap-is-off.patch
new file mode 100644 (file)
index 0000000..9d84342
--- /dev/null
@@ -0,0 +1,61 @@
+From 4640c7ee9b8953237d05a61ea3ea93981d1bc961 Mon Sep 17 00:00:00 2001
+From: "H. Peter Anvin" <hpa@linux.intel.com>
+Date: Thu, 13 Feb 2014 07:46:04 -0800
+Subject: x86, smap: smap_violation() is bogus if CONFIG_X86_SMAP is off
+
+From: "H. Peter Anvin" <hpa@linux.intel.com>
+
+commit 4640c7ee9b8953237d05a61ea3ea93981d1bc961 upstream.
+
+If CONFIG_X86_SMAP is disabled, smap_violation() tests for conditions
+which are incorrect (as the AC flag doesn't matter), causing spurious
+faults.
+
+The dynamic disabling of SMAP (nosmap on the command line) is fine
+because it disables X86_FEATURE_SMAP, therefore causing the
+static_cpu_has() to return false.
+
+Found by Fengguang Wu's test system.
+
+[ v3: move all predicates into smap_violation() ]
+[ v2: use IS_ENABLED() instead of #ifdef ]
+
+Reported-by: Fengguang Wu <fengguang.wu@intel.com>
+Link: http://lkml.kernel.org/r/20140213124550.GA30497@localhost
+Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/mm/fault.c |   14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+--- a/arch/x86/mm/fault.c
++++ b/arch/x86/mm/fault.c
+@@ -989,6 +989,12 @@ static int fault_in_kernel_space(unsigne
+ static inline bool smap_violation(int error_code, struct pt_regs *regs)
+ {
++      if (!IS_ENABLED(CONFIG_X86_SMAP))
++              return false;
++
++      if (!static_cpu_has(X86_FEATURE_SMAP))
++              return false;
++
+       if (error_code & PF_USER)
+               return false;
+@@ -1091,11 +1097,9 @@ __do_page_fault(struct pt_regs *regs, un
+       if (unlikely(error_code & PF_RSVD))
+               pgtable_bad(regs, error_code, address);
+-      if (static_cpu_has(X86_FEATURE_SMAP)) {
+-              if (unlikely(smap_violation(error_code, regs))) {
+-                      bad_area_nosemaphore(regs, error_code, address);
+-                      return;
+-              }
++      if (unlikely(smap_violation(error_code, regs))) {
++              bad_area_nosemaphore(regs, error_code, address);
++              return;
+       }
+       perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);