--- /dev/null
+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);
+ /*
--- /dev/null
+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)
--- /dev/null
+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
--- /dev/null
+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;
--- /dev/null
+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 */
--- /dev/null
+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
--- /dev/null
+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;
+
--- /dev/null
+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);