]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.13-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 19 Oct 2017 09:43:38 +0000 (11:43 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 19 Oct 2017 09:43:38 +0000 (11:43 +0200)
added patches:
drivers-hv-vmbus-fix-bugs-in-rescind-handling.patch
drivers-hv-vmbus-fix-rescind-handling-issues.patch
hid-hid-elecom-extend-to-fix-descriptor-for-huge-trackball.patch
mm-page_vma_mapped-ensure-pmd-is-loaded-with-read_once-outside-of-lock.patch
perf-pmu-unbreak-perf-record-for-arm-arm64-with-events-with-explicit-pmu.patch
x86-apic-silence-fw_bug-tsc_deadline-disabled-due-to-errata-on-cpus-without-the-feature.patch
x86-apic-silence-fw_bug-tsc_deadline-disabled-due-to-errata-on-hypervisors.patch

queue-4.13/drivers-hv-vmbus-fix-bugs-in-rescind-handling.patch [new file with mode: 0644]
queue-4.13/drivers-hv-vmbus-fix-rescind-handling-issues.patch [new file with mode: 0644]
queue-4.13/hid-hid-elecom-extend-to-fix-descriptor-for-huge-trackball.patch [new file with mode: 0644]
queue-4.13/mm-page_vma_mapped-ensure-pmd-is-loaded-with-read_once-outside-of-lock.patch [new file with mode: 0644]
queue-4.13/perf-pmu-unbreak-perf-record-for-arm-arm64-with-events-with-explicit-pmu.patch [new file with mode: 0644]
queue-4.13/series [new file with mode: 0644]
queue-4.13/x86-apic-silence-fw_bug-tsc_deadline-disabled-due-to-errata-on-cpus-without-the-feature.patch [new file with mode: 0644]
queue-4.13/x86-apic-silence-fw_bug-tsc_deadline-disabled-due-to-errata-on-hypervisors.patch [new file with mode: 0644]

diff --git a/queue-4.13/drivers-hv-vmbus-fix-bugs-in-rescind-handling.patch b/queue-4.13/drivers-hv-vmbus-fix-bugs-in-rescind-handling.patch
new file mode 100644 (file)
index 0000000..b49d2e8
--- /dev/null
@@ -0,0 +1,193 @@
+From 192b2d78722ffea188e5ec6ae5d55010dce05a4b Mon Sep 17 00:00:00 2001
+From: "K. Y. Srinivasan" <kys@microsoft.com>
+Date: Fri, 29 Sep 2017 21:09:36 -0700
+Subject: Drivers: hv: vmbus: Fix bugs in rescind handling
+
+From: K. Y. Srinivasan <kys@microsoft.com>
+
+commit 192b2d78722ffea188e5ec6ae5d55010dce05a4b upstream.
+
+This patch addresses the following bugs in the current rescind handling code:
+
+1. Fixes a race condition where we may be invoking hv_process_channel_removal()
+on an already freed channel.
+
+2. Prevents indefinite wait when rescinding sub-channels by correctly setting
+the probe_complete state.
+
+I would like to thank Dexuan for patiently reviewing earlier versions of this
+patch and identifying many of the issues fixed here.
+
+Greg, please apply this to 4.14-final.
+
+Fixes: '54a66265d675 ("Drivers: hv: vmbus: Fix rescind handling")'
+
+Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
+Reviewed-by: Dexuan Cui <decui@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/hv/channel.c      |    6 +++---
+ drivers/hv/channel_mgmt.c |   37 ++++++++++++++++++-------------------
+ drivers/hv/vmbus_drv.c    |    3 +--
+ include/linux/hyperv.h    |    2 +-
+ 4 files changed, 23 insertions(+), 25 deletions(-)
+
+--- a/drivers/hv/channel.c
++++ b/drivers/hv/channel.c
+@@ -640,6 +640,7 @@ void vmbus_close(struct vmbus_channel *c
+                */
+               return;
+       }
++      mutex_lock(&vmbus_connection.channel_mutex);
+       /*
+        * Close all the sub-channels first and then close the
+        * primary channel.
+@@ -648,16 +649,15 @@ void vmbus_close(struct vmbus_channel *c
+               cur_channel = list_entry(cur, struct vmbus_channel, sc_list);
+               vmbus_close_internal(cur_channel);
+               if (cur_channel->rescind) {
+-                      mutex_lock(&vmbus_connection.channel_mutex);
+-                      hv_process_channel_removal(cur_channel,
++                      hv_process_channel_removal(
+                                          cur_channel->offermsg.child_relid);
+-                      mutex_unlock(&vmbus_connection.channel_mutex);
+               }
+       }
+       /*
+        * Now close the primary.
+        */
+       vmbus_close_internal(channel);
++      mutex_unlock(&vmbus_connection.channel_mutex);
+ }
+ EXPORT_SYMBOL_GPL(vmbus_close);
+--- a/drivers/hv/channel_mgmt.c
++++ b/drivers/hv/channel_mgmt.c
+@@ -159,7 +159,7 @@ static void vmbus_rescind_cleanup(struct
+       spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+-
++      channel->rescind = true;
+       list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list,
+                               msglistentry) {
+@@ -381,14 +381,21 @@ static void vmbus_release_relid(u32 reli
+                      true);
+ }
+-void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid)
++void hv_process_channel_removal(u32 relid)
+ {
+       unsigned long flags;
+-      struct vmbus_channel *primary_channel;
++      struct vmbus_channel *primary_channel, *channel;
+-      BUG_ON(!channel->rescind);
+       BUG_ON(!mutex_is_locked(&vmbus_connection.channel_mutex));
++      /*
++       * Make sure channel is valid as we may have raced.
++       */
++      channel = relid2channel(relid);
++      if (!channel)
++              return;
++
++      BUG_ON(!channel->rescind);
+       if (channel->target_cpu != get_cpu()) {
+               put_cpu();
+               smp_call_function_single(channel->target_cpu,
+@@ -515,6 +522,7 @@ static void vmbus_process_offer(struct v
+       if (!fnew) {
+               if (channel->sc_creation_callback != NULL)
+                       channel->sc_creation_callback(newchannel);
++              newchannel->probe_done = true;
+               return;
+       }
+@@ -843,7 +851,6 @@ static void vmbus_onoffer_rescind(struct
+ {
+       struct vmbus_channel_rescind_offer *rescind;
+       struct vmbus_channel *channel;
+-      unsigned long flags;
+       struct device *dev;
+       rescind = (struct vmbus_channel_rescind_offer *)hdr;
+@@ -882,16 +889,6 @@ static void vmbus_onoffer_rescind(struct
+               return;
+       }
+-      spin_lock_irqsave(&channel->lock, flags);
+-      channel->rescind = true;
+-      spin_unlock_irqrestore(&channel->lock, flags);
+-
+-      /*
+-       * Now that we have posted the rescind state, perform
+-       * rescind related cleanup.
+-       */
+-      vmbus_rescind_cleanup(channel);
+-
+       /*
+        * Now wait for offer handling to complete.
+        */
+@@ -910,6 +907,7 @@ static void vmbus_onoffer_rescind(struct
+       if (channel->device_obj) {
+               if (channel->chn_rescind_callback) {
+                       channel->chn_rescind_callback(channel);
++                      vmbus_rescind_cleanup(channel);
+                       return;
+               }
+               /*
+@@ -918,6 +916,7 @@ static void vmbus_onoffer_rescind(struct
+                */
+               dev = get_device(&channel->device_obj->device);
+               if (dev) {
++                      vmbus_rescind_cleanup(channel);
+                       vmbus_device_unregister(channel->device_obj);
+                       put_device(dev);
+               }
+@@ -930,16 +929,16 @@ static void vmbus_onoffer_rescind(struct
+                * 1. Close all sub-channels first
+                * 2. Then close the primary channel.
+                */
++              mutex_lock(&vmbus_connection.channel_mutex);
++              vmbus_rescind_cleanup(channel);
+               if (channel->state == CHANNEL_OPEN_STATE) {
+                       /*
+                        * The channel is currently not open;
+                        * it is safe for us to cleanup the channel.
+                        */
+-                      mutex_lock(&vmbus_connection.channel_mutex);
+-                      hv_process_channel_removal(channel,
+-                                              channel->offermsg.child_relid);
+-                      mutex_unlock(&vmbus_connection.channel_mutex);
++                      hv_process_channel_removal(rescind->child_relid);
+               }
++              mutex_unlock(&vmbus_connection.channel_mutex);
+       }
+ }
+--- a/drivers/hv/vmbus_drv.c
++++ b/drivers/hv/vmbus_drv.c
+@@ -768,8 +768,7 @@ static void vmbus_device_release(struct
+       struct vmbus_channel *channel = hv_dev->channel;
+       mutex_lock(&vmbus_connection.channel_mutex);
+-      hv_process_channel_removal(channel,
+-                                 channel->offermsg.child_relid);
++      hv_process_channel_removal(channel->offermsg.child_relid);
+       mutex_unlock(&vmbus_connection.channel_mutex);
+       kfree(hv_dev);
+--- a/include/linux/hyperv.h
++++ b/include/linux/hyperv.h
+@@ -1455,7 +1455,7 @@ extern bool vmbus_prep_negotiate_resp(st
+                               const int *srv_version, int srv_vercnt,
+                               int *nego_fw_version, int *nego_srv_version);
+-void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid);
++void hv_process_channel_removal(u32 relid);
+ void vmbus_setevent(struct vmbus_channel *channel);
+ /*
diff --git a/queue-4.13/drivers-hv-vmbus-fix-rescind-handling-issues.patch b/queue-4.13/drivers-hv-vmbus-fix-rescind-handling-issues.patch
new file mode 100644 (file)
index 0000000..8d1412d
--- /dev/null
@@ -0,0 +1,159 @@
+From 6f3d791f300618caf82a2be0c27456edd76d5164 Mon Sep 17 00:00:00 2001
+From: "K. Y. Srinivasan" <kys@microsoft.com>
+Date: Fri, 11 Aug 2017 10:03:59 -0700
+Subject: Drivers: hv: vmbus: Fix rescind handling issues
+
+From: K. Y. Srinivasan <kys@microsoft.com>
+
+commit 6f3d791f300618caf82a2be0c27456edd76d5164 upstream.
+
+This patch handles the following issues that were observed when we are
+handling racing channel offer message and rescind message for the same
+offer:
+
+1. Since the host does not respond to messages on a rescinded channel,
+in the current code, we could be indefinitely blocked on the vmbus_open() call.
+
+2. When a rescinded channel is being closed, if there is a pending interrupt on the
+channel, we could end up freeing the channel that the interrupt handler would run on.
+
+Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
+Reviewed-by: Dexuan Cui <decui@microsoft.com>
+Tested-by: Dexuan Cui <decui@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/hv/channel.c      |   14 ++++++++++++++
+ drivers/hv/channel_mgmt.c |   29 ++++++++++++++++++++++++++---
+ drivers/hv/vmbus_drv.c    |    3 +++
+ include/linux/hyperv.h    |    2 ++
+ 4 files changed, 45 insertions(+), 3 deletions(-)
+
+--- a/drivers/hv/channel.c
++++ b/drivers/hv/channel.c
+@@ -177,6 +177,11 @@ int vmbus_open(struct vmbus_channel *new
+                     &vmbus_connection.chn_msg_list);
+       spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
++      if (newchannel->rescind) {
++              err = -ENODEV;
++              goto error_free_gpadl;
++      }
++
+       ret = vmbus_post_msg(open_msg,
+                            sizeof(struct vmbus_channel_open_channel), true);
+@@ -421,6 +426,11 @@ int vmbus_establish_gpadl(struct vmbus_c
+       spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
++      if (channel->rescind) {
++              ret = -ENODEV;
++              goto cleanup;
++      }
++
+       ret = vmbus_post_msg(gpadlmsg, msginfo->msgsize -
+                            sizeof(*msginfo), true);
+       if (ret != 0)
+@@ -494,6 +504,10 @@ int vmbus_teardown_gpadl(struct vmbus_ch
+       list_add_tail(&info->msglistentry,
+                     &vmbus_connection.chn_msg_list);
+       spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
++
++      if (channel->rescind)
++              goto post_msg_err;
++
+       ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_gpadl_teardown),
+                            true);
+--- a/drivers/hv/channel_mgmt.c
++++ b/drivers/hv/channel_mgmt.c
+@@ -451,6 +451,12 @@ static void vmbus_process_offer(struct v
+       /* Make sure this is a new offer */
+       mutex_lock(&vmbus_connection.channel_mutex);
++      /*
++       * Now that we have acquired the channel_mutex,
++       * we can release the potentially racing rescind thread.
++       */
++      atomic_dec(&vmbus_connection.offer_in_progress);
++
+       list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) {
+               if (!uuid_le_cmp(channel->offermsg.offer.if_type,
+                       newchannel->offermsg.offer.if_type) &&
+@@ -481,7 +487,6 @@ static void vmbus_process_offer(struct v
+                       channel->num_sc++;
+                       spin_unlock_irqrestore(&channel->lock, flags);
+               } else {
+-                      atomic_dec(&vmbus_connection.offer_in_progress);
+                       goto err_free_chan;
+               }
+       }
+@@ -510,7 +515,6 @@ static void vmbus_process_offer(struct v
+       if (!fnew) {
+               if (channel->sc_creation_callback != NULL)
+                       channel->sc_creation_callback(newchannel);
+-              atomic_dec(&vmbus_connection.offer_in_progress);
+               return;
+       }
+@@ -541,7 +545,7 @@ static void vmbus_process_offer(struct v
+               goto err_deq_chan;
+       }
+-      atomic_dec(&vmbus_connection.offer_in_progress);
++      newchannel->probe_done = true;
+       return;
+ err_deq_chan:
+@@ -882,8 +886,27 @@ static void vmbus_onoffer_rescind(struct
+       channel->rescind = true;
+       spin_unlock_irqrestore(&channel->lock, flags);
++      /*
++       * Now that we have posted the rescind state, perform
++       * rescind related cleanup.
++       */
+       vmbus_rescind_cleanup(channel);
++      /*
++       * Now wait for offer handling to complete.
++       */
++      while (READ_ONCE(channel->probe_done) == false) {
++              /*
++               * We wait here until any channel offer is currently
++               * being processed.
++               */
++              msleep(1);
++      }
++
++      /*
++       * At this point, the rescind handling can proceed safely.
++       */
++
+       if (channel->device_obj) {
+               if (channel->chn_rescind_callback) {
+                       channel->chn_rescind_callback(channel);
+--- a/drivers/hv/vmbus_drv.c
++++ b/drivers/hv/vmbus_drv.c
+@@ -940,6 +940,9 @@ static void vmbus_chan_sched(struct hv_p
+                       if (channel->offermsg.child_relid != relid)
+                               continue;
++                      if (channel->rescind)
++                              continue;
++
+                       switch (channel->callback_mode) {
+                       case HV_CALL_ISR:
+                               vmbus_channel_isr(channel);
+--- a/include/linux/hyperv.h
++++ b/include/linux/hyperv.h
+@@ -895,6 +895,8 @@ struct vmbus_channel {
+        */
+       enum hv_numa_policy affinity_policy;
++      bool probe_done;
++
+ };
+ static inline bool is_hvsock_channel(const struct vmbus_channel *c)
diff --git a/queue-4.13/hid-hid-elecom-extend-to-fix-descriptor-for-huge-trackball.patch b/queue-4.13/hid-hid-elecom-extend-to-fix-descriptor-for-huge-trackball.patch
new file mode 100644 (file)
index 0000000..43ecde1
--- /dev/null
@@ -0,0 +1,101 @@
+From a0933a456ff83a3b5ffa3a1903e0b8de4a56adf5 Mon Sep 17 00:00:00 2001
+From: Alex Manoussakis <amanou@gnu.org>
+Date: Thu, 5 Oct 2017 13:41:20 -0400
+Subject: HID: hid-elecom: extend to fix descriptor for HUGE trackball
+
+From: Alex Manoussakis <amanou@gnu.org>
+
+commit a0933a456ff83a3b5ffa3a1903e0b8de4a56adf5 upstream.
+
+In addition to DEFT, Elecom introduced a larger trackball called HUGE, in
+both wired (M-HT1URBK) and wireless (M-HT1DRBK) versions. It has the same
+buttons and behavior as the DEFT. This patch adds the two relevant USB IDs
+to enable operation of the three Fn buttons on the top of the device.
+
+Cc: Diego Elio Petteno <flameeyes@flameeyes.eu>
+Signed-off-by: Alex Manoussakis <amanou@gnu.org>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/hid/Kconfig      |    1 +
+ drivers/hid/hid-core.c   |    2 ++
+ drivers/hid/hid-elecom.c |   13 +++++++++----
+ drivers/hid/hid-ids.h    |    2 ++
+ 4 files changed, 14 insertions(+), 4 deletions(-)
+
+--- a/drivers/hid/Kconfig
++++ b/drivers/hid/Kconfig
+@@ -281,6 +281,7 @@ config HID_ELECOM
+       Support for ELECOM devices:
+         - BM084 Bluetooth Mouse
+         - DEFT Trackball (Wired and wireless)
++        - HUGE Trackball (Wired and wireless)
+ config HID_ELO
+       tristate "ELO USB 4000/4500 touchscreen"
+--- a/drivers/hid/hid-core.c
++++ b/drivers/hid/hid-core.c
+@@ -2031,6 +2031,8 @@ static const struct hid_device_id hid_ha
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRED) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRELESS) },
++      { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_HUGE_WIRED) },
++      { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_HUGE_WIRELESS) },
+ #endif
+ #if IS_ENABLED(CONFIG_HID_ELO)
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0009) },
+--- a/drivers/hid/hid-elecom.c
++++ b/drivers/hid/hid-elecom.c
+@@ -3,6 +3,7 @@
+  *  Copyright (c) 2010 Richard Nauber <Richard.Nauber@gmail.com>
+  *  Copyright (c) 2016 Yuxuan Shui <yshuiv7@gmail.com>
+  *  Copyright (c) 2017 Diego Elio Pettenò <flameeyes@flameeyes.eu>
++ *  Copyright (c) 2017 Alex Manoussakis <amanou@gnu.org>
+  */
+ /*
+@@ -32,9 +33,11 @@ static __u8 *elecom_report_fixup(struct
+               break;
+       case USB_DEVICE_ID_ELECOM_DEFT_WIRED:
+       case USB_DEVICE_ID_ELECOM_DEFT_WIRELESS:
+-              /* The DEFT trackball has eight buttons, but its descriptor only
+-               * reports five, disabling the three Fn buttons on the top of
+-               * the mouse.
++      case USB_DEVICE_ID_ELECOM_HUGE_WIRED:
++      case USB_DEVICE_ID_ELECOM_HUGE_WIRELESS:
++              /* The DEFT/HUGE trackball has eight buttons, but its descriptor
++               * only reports five, disabling the three Fn buttons on the top
++               * of the mouse.
+                *
+                * Apply the following diff to the descriptor:
+                *
+@@ -62,7 +65,7 @@ static __u8 *elecom_report_fixup(struct
+                * End Collection,                     End Collection,
+                */
+               if (*rsize == 213 && rdesc[13] == 5 && rdesc[21] == 5) {
+-                      hid_info(hdev, "Fixing up Elecom DEFT Fn buttons\n");
++                      hid_info(hdev, "Fixing up Elecom DEFT/HUGE Fn buttons\n");
+                       rdesc[13] = 8; /* Button/Variable Report Count */
+                       rdesc[21] = 8; /* Button/Variable Usage Maximum */
+                       rdesc[29] = 0; /* Button/Constant Report Count */
+@@ -76,6 +79,8 @@ static const struct hid_device_id elecom
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRED) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRELESS) },
++      { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_HUGE_WIRED) },
++      { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_HUGE_WIRELESS) },
+       { }
+ };
+ MODULE_DEVICE_TABLE(hid, elecom_devices);
+--- a/drivers/hid/hid-ids.h
++++ b/drivers/hid/hid-ids.h
+@@ -366,6 +366,8 @@
+ #define USB_DEVICE_ID_ELECOM_BM084    0x0061
+ #define USB_DEVICE_ID_ELECOM_DEFT_WIRED       0x00fe
+ #define USB_DEVICE_ID_ELECOM_DEFT_WIRELESS    0x00ff
++#define USB_DEVICE_ID_ELECOM_HUGE_WIRED       0x010c
++#define USB_DEVICE_ID_ELECOM_HUGE_WIRELESS    0x010d
+ #define USB_VENDOR_ID_DREAM_CHEEKY    0x1d34
+ #define USB_DEVICE_ID_DREAM_CHEEKY_WN 0x0004
diff --git a/queue-4.13/mm-page_vma_mapped-ensure-pmd-is-loaded-with-read_once-outside-of-lock.patch b/queue-4.13/mm-page_vma_mapped-ensure-pmd-is-loaded-with-read_once-outside-of-lock.patch
new file mode 100644 (file)
index 0000000..3fc44cf
--- /dev/null
@@ -0,0 +1,122 @@
+From a7b100953aa33a5bbdc3e5e7f2241b9c0704606e Mon Sep 17 00:00:00 2001
+From: Will Deacon <will.deacon@arm.com>
+Date: Fri, 13 Oct 2017 15:58:25 -0700
+Subject: mm: page_vma_mapped: ensure pmd is loaded with READ_ONCE outside of lock
+
+From: Will Deacon <will.deacon@arm.com>
+
+commit a7b100953aa33a5bbdc3e5e7f2241b9c0704606e upstream.
+
+Loading the pmd without holding the pmd_lock exposes us to races with
+concurrent updaters of the page tables but, worse still, it also allows
+the compiler to cache the pmd value in a register and reuse it later on,
+even if we've performed a READ_ONCE in between and seen a more recent
+value.
+
+In the case of page_vma_mapped_walk, this leads to the following crash
+when the pmd loaded for the initial pmd_trans_huge check is all zeroes
+and a subsequent valid table entry is loaded by check_pmd.  We then
+proceed into map_pte, but the compiler re-uses the zero entry inside
+pte_offset_map, resulting in a junk pointer being installed in
+pvmw->pte:
+
+  PC is at check_pte+0x20/0x170
+  LR is at page_vma_mapped_walk+0x2e0/0x540
+  [...]
+  Process doio (pid: 2463, stack limit = 0xffff00000f2e8000)
+  Call trace:
+    check_pte+0x20/0x170
+    page_vma_mapped_walk+0x2e0/0x540
+    page_mkclean_one+0xac/0x278
+    rmap_walk_file+0xf0/0x238
+    rmap_walk+0x64/0xa0
+    page_mkclean+0x90/0xa8
+    clear_page_dirty_for_io+0x84/0x2a8
+    mpage_submit_page+0x34/0x98
+    mpage_process_page_bufs+0x164/0x170
+    mpage_prepare_extent_to_map+0x134/0x2b8
+    ext4_writepages+0x484/0xe30
+    do_writepages+0x44/0xe8
+    __filemap_fdatawrite_range+0xbc/0x110
+    file_write_and_wait_range+0x48/0xd8
+    ext4_sync_file+0x80/0x4b8
+    vfs_fsync_range+0x64/0xc0
+    SyS_msync+0x194/0x1e8
+
+This patch fixes the problem by ensuring that READ_ONCE is used before
+the initial checks on the pmd, and this value is subsequently used when
+checking whether or not the pmd is present.  pmd_check is removed and
+the pmd_present check is inlined directly.
+
+Link: http://lkml.kernel.org/r/1507222630-5839-1-git-send-email-will.deacon@arm.com
+Fixes: f27176cfc363 ("mm: convert page_mkclean_one() to use page_vma_mapped_walk()")
+Signed-off-by: Will Deacon <will.deacon@arm.com>
+Tested-by: Yury Norov <ynorov@caviumnetworks.com>
+Tested-by: Richard Ruigrok <rruigrok@codeaurora.org>
+Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
+Cc: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+[will: backport to 4.13.y]
+Signed-off-by: Will Deacon <will.deacon@arm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/page_vma_mapped.c |   25 ++++++++++---------------
+ 1 file changed, 10 insertions(+), 15 deletions(-)
+
+--- a/mm/page_vma_mapped.c
++++ b/mm/page_vma_mapped.c
+@@ -6,17 +6,6 @@
+ #include "internal.h"
+-static inline bool check_pmd(struct page_vma_mapped_walk *pvmw)
+-{
+-      pmd_t pmde;
+-      /*
+-       * Make sure we don't re-load pmd between present and !trans_huge check.
+-       * We need a consistent view.
+-       */
+-      pmde = READ_ONCE(*pvmw->pmd);
+-      return pmd_present(pmde) && !pmd_trans_huge(pmde);
+-}
+-
+ static inline bool not_found(struct page_vma_mapped_walk *pvmw)
+ {
+       page_vma_mapped_walk_done(pvmw);
+@@ -106,6 +95,7 @@ bool page_vma_mapped_walk(struct page_vm
+       pgd_t *pgd;
+       p4d_t *p4d;
+       pud_t *pud;
++      pmd_t pmde;
+       /* The only possible pmd mapping has been handled on last iteration */
+       if (pvmw->pmd && !pvmw->pte)
+@@ -138,7 +128,13 @@ restart:
+       if (!pud_present(*pud))
+               return false;
+       pvmw->pmd = pmd_offset(pud, pvmw->address);
+-      if (pmd_trans_huge(*pvmw->pmd)) {
++      /*
++       * Make sure the pmd value isn't cached in a register by the
++       * compiler and used as a stale value after we've observed a
++       * subsequent update.
++       */
++      pmde = READ_ONCE(*pvmw->pmd);
++      if (pmd_trans_huge(pmde)) {
+               pvmw->ptl = pmd_lock(mm, pvmw->pmd);
+               if (!pmd_present(*pvmw->pmd))
+                       return not_found(pvmw);
+@@ -153,9 +149,8 @@ restart:
+                       spin_unlock(pvmw->ptl);
+                       pvmw->ptl = NULL;
+               }
+-      } else {
+-              if (!check_pmd(pvmw))
+-                      return false;
++      } else if (!pmd_present(pmde)) {
++              return false;
+       }
+       if (!map_pte(pvmw))
+               goto next_pte;
diff --git a/queue-4.13/perf-pmu-unbreak-perf-record-for-arm-arm64-with-events-with-explicit-pmu.patch b/queue-4.13/perf-pmu-unbreak-perf-record-for-arm-arm64-with-events-with-explicit-pmu.patch
new file mode 100644 (file)
index 0000000..6534734
--- /dev/null
@@ -0,0 +1,200 @@
+From 66ec11919a0f96e936bb731fdbc2851316077d26 Mon Sep 17 00:00:00 2001
+From: Mark Rutland <mark.rutland@arm.com>
+Date: Fri, 6 Oct 2017 19:38:22 +0100
+Subject: perf pmu: Unbreak perf record for arm/arm64 with events with explicit PMU
+
+From: Mark Rutland <mark.rutland@arm.com>
+
+commit 66ec11919a0f96e936bb731fdbc2851316077d26 upstream.
+
+Currently, perf record is broken on arm/arm64 systems when the PMU is
+specified explicitly as part of the event, e.g.
+
+$ ./perf record -e armv8_cortex_a53/cpu_cycles/u true
+
+In such cases, perf record fails to open events unless
+perf_event_paranoid is set to -1, even if the PMU in question supports
+mode exclusion. Further, even when perf_event_paranoid is toggled, no
+samples are recorded.
+
+This is an unintended side effect of commit:
+
+  e3ba76deef23064f ("perf tools: Force uncore events to system wide monitoring)
+
+... which assumes that if a PMU has an associated cpu_map, it is an
+uncore PMU, and forces events for such PMUs to be system-wide.
+
+This is not true for arm/arm64 systems, which can have heterogeneous
+CPUs. To account for this, multiple CPU PMUs are exposed, each with a
+"cpus" field under sysfs, which the perf tool parses into a cpu_map. ARM
+PMUs do not have a "cpumask" file, and only have a "cpus" file. For the
+gory details as to why, see commit:
+
+ 7e3fcffe95544010 ("perf pmu: Support alternative sysfs cpumask")
+
+Given all of this, we can instead identify uncore PMUs by explicitly
+checking for a "cpumask" file, and restore arm/arm64 PMU support back to
+a working state. This patch does so, adding a new perf_pmu::is_uncore
+field, and splitting the existing cpumask parsing so that it can be
+reused.
+
+Signed-off-by: Mark Rutland <mark.rutland@arm.com>
+Tested-by Will Deacon <will.deacon@arm.com>
+Acked-by: Jiri Olsa <jolsa@kernel.org>
+Cc: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Borislav Petkov <bp@alien8.de>
+Cc: David Ahern <dsahern@gmail.com>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Fixes: e3ba76deef23064f ("perf tools: Force uncore events to system wide monitoring)
+Link: http://lkml.kernel.org/r/1507315102-5942-1-git-send-email-mark.rutland@arm.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ tools/perf/util/parse-events.c |    9 +++---
+ tools/perf/util/pmu.c          |   56 ++++++++++++++++++++++++++++++-----------
+ tools/perf/util/pmu.h          |    1 
+ 3 files changed, 47 insertions(+), 19 deletions(-)
+
+--- a/tools/perf/util/parse-events.c
++++ b/tools/perf/util/parse-events.c
+@@ -309,10 +309,11 @@ static char *get_config_name(struct list
+ static struct perf_evsel *
+ __add_event(struct list_head *list, int *idx,
+           struct perf_event_attr *attr,
+-          char *name, struct cpu_map *cpus,
++          char *name, struct perf_pmu *pmu,
+           struct list_head *config_terms)
+ {
+       struct perf_evsel *evsel;
++      struct cpu_map *cpus = pmu ? pmu->cpus : NULL;
+       event_attr_init(attr);
+@@ -323,7 +324,7 @@ __add_event(struct list_head *list, int
+       (*idx)++;
+       evsel->cpus        = cpu_map__get(cpus);
+       evsel->own_cpus    = cpu_map__get(cpus);
+-      evsel->system_wide = !!cpus;
++      evsel->system_wide = pmu ? pmu->is_uncore : false;
+       if (name)
+               evsel->name = strdup(name);
+@@ -1232,7 +1233,7 @@ int parse_events_add_pmu(struct parse_ev
+       if (!head_config) {
+               attr.type = pmu->type;
+-              evsel = __add_event(list, &data->idx, &attr, NULL, pmu->cpus, NULL);
++              evsel = __add_event(list, &data->idx, &attr, NULL, pmu, NULL);
+               return evsel ? 0 : -ENOMEM;
+       }
+@@ -1253,7 +1254,7 @@ int parse_events_add_pmu(struct parse_ev
+               return -EINVAL;
+       evsel = __add_event(list, &data->idx, &attr,
+-                          get_config_name(head_config), pmu->cpus,
++                          get_config_name(head_config), pmu,
+                           &config_terms);
+       if (evsel) {
+               evsel->unit = info.unit;
+--- a/tools/perf/util/pmu.c
++++ b/tools/perf/util/pmu.c
+@@ -470,17 +470,36 @@ static void pmu_read_sysfs(void)
+       closedir(dir);
+ }
++static struct cpu_map *__pmu_cpumask(const char *path)
++{
++      FILE *file;
++      struct cpu_map *cpus;
++
++      file = fopen(path, "r");
++      if (!file)
++              return NULL;
++
++      cpus = cpu_map__read(file);
++      fclose(file);
++      return cpus;
++}
++
++/*
++ * Uncore PMUs have a "cpumask" file under sysfs. CPU PMUs (e.g. on arm/arm64)
++ * may have a "cpus" file.
++ */
++#define CPUS_TEMPLATE_UNCORE  "%s/bus/event_source/devices/%s/cpumask"
++#define CPUS_TEMPLATE_CPU     "%s/bus/event_source/devices/%s/cpus"
++
+ static struct cpu_map *pmu_cpumask(const char *name)
+ {
+-      struct stat st;
+       char path[PATH_MAX];
+-      FILE *file;
+       struct cpu_map *cpus;
+       const char *sysfs = sysfs__mountpoint();
+       const char *templates[] = {
+-               "%s/bus/event_source/devices/%s/cpumask",
+-               "%s/bus/event_source/devices/%s/cpus",
+-               NULL
++              CPUS_TEMPLATE_UNCORE,
++              CPUS_TEMPLATE_CPU,
++              NULL
+       };
+       const char **template;
+@@ -489,20 +508,25 @@ static struct cpu_map *pmu_cpumask(const
+       for (template = templates; *template; template++) {
+               snprintf(path, PATH_MAX, *template, sysfs, name);
+-              if (stat(path, &st) == 0)
+-                      break;
++              cpus = __pmu_cpumask(path);
++              if (cpus)
++                      return cpus;
+       }
+-      if (!*template)
+-              return NULL;
++      return NULL;
++}
+-      file = fopen(path, "r");
+-      if (!file)
+-              return NULL;
++static bool pmu_is_uncore(const char *name)
++{
++      char path[PATH_MAX];
++      struct cpu_map *cpus;
++      const char *sysfs = sysfs__mountpoint();
+-      cpus = cpu_map__read(file);
+-      fclose(file);
+-      return cpus;
++      snprintf(path, PATH_MAX, CPUS_TEMPLATE_UNCORE, sysfs, name);
++      cpus = __pmu_cpumask(path);
++      cpu_map__put(cpus);
++
++      return !!cpus;
+ }
+ /*
+@@ -617,6 +641,8 @@ static struct perf_pmu *pmu_lookup(const
+       pmu->cpus = pmu_cpumask(name);
++      pmu->is_uncore = pmu_is_uncore(name);
++
+       INIT_LIST_HEAD(&pmu->format);
+       INIT_LIST_HEAD(&pmu->aliases);
+       list_splice(&format, &pmu->format);
+--- a/tools/perf/util/pmu.h
++++ b/tools/perf/util/pmu.h
+@@ -22,6 +22,7 @@ struct perf_pmu {
+       char *name;
+       __u32 type;
+       bool selectable;
++      bool is_uncore;
+       struct perf_event_attr *default_config;
+       struct cpu_map *cpus;
+       struct list_head format;  /* HEAD struct perf_pmu_format -> list */
diff --git a/queue-4.13/series b/queue-4.13/series
new file mode 100644 (file)
index 0000000..d446ef9
--- /dev/null
@@ -0,0 +1,7 @@
+x86-apic-silence-fw_bug-tsc_deadline-disabled-due-to-errata-on-cpus-without-the-feature.patch
+x86-apic-silence-fw_bug-tsc_deadline-disabled-due-to-errata-on-hypervisors.patch
+perf-pmu-unbreak-perf-record-for-arm-arm64-with-events-with-explicit-pmu.patch
+mm-page_vma_mapped-ensure-pmd-is-loaded-with-read_once-outside-of-lock.patch
+hid-hid-elecom-extend-to-fix-descriptor-for-huge-trackball.patch
+drivers-hv-vmbus-fix-rescind-handling-issues.patch
+drivers-hv-vmbus-fix-bugs-in-rescind-handling.patch
diff --git a/queue-4.13/x86-apic-silence-fw_bug-tsc_deadline-disabled-due-to-errata-on-cpus-without-the-feature.patch b/queue-4.13/x86-apic-silence-fw_bug-tsc_deadline-disabled-due-to-errata-on-cpus-without-the-feature.patch
new file mode 100644 (file)
index 0000000..daa8a65
--- /dev/null
@@ -0,0 +1,57 @@
+From 594a30fb12424717a41c62323d2a8bf167dbccad Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Wed, 30 Aug 2017 12:58:11 +0200
+Subject: x86/apic: Silence "FW_BUG TSC_DEADLINE disabled due to Errata" on CPUs without the feature
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+commit 594a30fb12424717a41c62323d2a8bf167dbccad upstream.
+
+When booting 4.13 on a VirtualBox VM on a Skylake host the following
+error shows up in the logs:
+
+ [    0.000000] [Firmware Bug]: TSC_DEADLINE disabled due to Errata;
+                please update microcode to version: 0xb2 (or later)
+
+This is caused by apic_check_deadline_errata() only checking CPU model
+and not the X86_FEATURE_TSC_DEADLINE_TIMER flag (which VirtualBox does
+NOT export to the guest), combined with VirtualBox not exporting the
+micro-code version to the guest.
+
+This commit adds a check for X86_FEATURE_TSC_DEADLINE_TIMER to
+apic_check_deadline_errata(), silencing this error on VirtualBox VMs.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Acked-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: Frank Mehnert <frank.mehnert@oracle.com>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Michael Thayer <michael.thayer@oracle.com>
+Cc: Michal Necasek <michal.necasek@oracle.com>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Fixes: bd9240a18e ("x86/apic: Add TSC_DEADLINE quirk due to errata")
+Link: http://lkml.kernel.org/r/20170830105811.27539-1-hdegoede@redhat.com
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/kernel/apic/apic.c |    6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/arch/x86/kernel/apic/apic.c
++++ b/arch/x86/kernel/apic/apic.c
+@@ -599,9 +599,13 @@ static const struct x86_cpu_id deadline_
+ static void apic_check_deadline_errata(void)
+ {
+-      const struct x86_cpu_id *m = x86_match_cpu(deadline_match);
++      const struct x86_cpu_id *m;
+       u32 rev;
++      if (!boot_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER))
++              return;
++
++      m = x86_match_cpu(deadline_match);
+       if (!m)
+               return;
diff --git a/queue-4.13/x86-apic-silence-fw_bug-tsc_deadline-disabled-due-to-errata-on-hypervisors.patch b/queue-4.13/x86-apic-silence-fw_bug-tsc_deadline-disabled-due-to-errata-on-hypervisors.patch
new file mode 100644 (file)
index 0000000..d41faa7
--- /dev/null
@@ -0,0 +1,52 @@
+From cc6afe2240298049585e86b1ade85efc8a7f225d Mon Sep 17 00:00:00 2001
+From: Paolo Bonzini <pbonzini@redhat.com>
+Date: Tue, 10 Oct 2017 12:12:57 +0200
+Subject: x86/apic: Silence "FW_BUG TSC_DEADLINE disabled due to Errata" on hypervisors
+
+From: Paolo Bonzini <pbonzini@redhat.com>
+
+commit cc6afe2240298049585e86b1ade85efc8a7f225d upstream.
+
+Commit 594a30fb1242 ("x86/apic: Silence "FW_BUG TSC_DEADLINE disabled
+due to Errata" on CPUs without the feature", 2017-08-30) was also about
+silencing the warning on VirtualBox; however, KVM does expose the TSC
+deadline timer, and it's virtualized so that it is immune from CPU errata.
+
+Therefore, booting 4.13 with "-cpu Haswell" shows this in the logs:
+
+     [    0.000000] [Firmware Bug]: TSC_DEADLINE disabled due to Errata;
+                    please update microcode to version: 0xb2 (or later)
+
+Even if you had a hypervisor that does _not_ virtualize the TSC deadline
+and rather exposes the hardware one, it should be the hypervisors task
+to update microcode and possibly hide the flag from CPUID.  So just
+hide the message when running on _any_ hypervisor, not just those that
+do not support the TSC deadline timer.
+
+The older check still makes sense, so keep it.
+
+Fixes: bd9240a18e ("x86/apic: Add TSC_DEADLINE quirk due to errata")
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Hans de Goede <hdegoede@redhat.com>
+Cc: kvm@vger.kernel.org
+Link: https://lkml.kernel.org/r/1507630377-54471-1-git-send-email-pbonzini@redhat.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/kernel/apic/apic.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/arch/x86/kernel/apic/apic.c
++++ b/arch/x86/kernel/apic/apic.c
+@@ -602,7 +602,8 @@ static void apic_check_deadline_errata(v
+       const struct x86_cpu_id *m;
+       u32 rev;
+-      if (!boot_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER))
++      if (!boot_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER) ||
++          boot_cpu_has(X86_FEATURE_HYPERVISOR))
+               return;
+       m = x86_match_cpu(deadline_match);