From: Greg Kroah-Hartman Date: Thu, 19 Oct 2017 09:43:38 +0000 (+0200) Subject: 4.13-stable patches X-Git-Tag: v3.18.77~13 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9e2c8ece760e3a3d6eb1f5788aa12a1369df291c;p=thirdparty%2Fkernel%2Fstable-queue.git 4.13-stable patches 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 --- 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 index 00000000000..b49d2e8cd96 --- /dev/null +++ b/queue-4.13/drivers-hv-vmbus-fix-bugs-in-rescind-handling.patch @@ -0,0 +1,193 @@ +From 192b2d78722ffea188e5ec6ae5d55010dce05a4b Mon Sep 17 00:00:00 2001 +From: "K. Y. Srinivasan" +Date: Fri, 29 Sep 2017 21:09:36 -0700 +Subject: Drivers: hv: vmbus: Fix bugs in rescind handling + +From: K. Y. Srinivasan + +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 +Reviewed-by: Dexuan Cui +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..8d1412d28d5 --- /dev/null +++ b/queue-4.13/drivers-hv-vmbus-fix-rescind-handling-issues.patch @@ -0,0 +1,159 @@ +From 6f3d791f300618caf82a2be0c27456edd76d5164 Mon Sep 17 00:00:00 2001 +From: "K. Y. Srinivasan" +Date: Fri, 11 Aug 2017 10:03:59 -0700 +Subject: Drivers: hv: vmbus: Fix rescind handling issues + +From: K. Y. Srinivasan + +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 +Reviewed-by: Dexuan Cui +Tested-by: Dexuan Cui +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..43ecde1b015 --- /dev/null +++ b/queue-4.13/hid-hid-elecom-extend-to-fix-descriptor-for-huge-trackball.patch @@ -0,0 +1,101 @@ +From a0933a456ff83a3b5ffa3a1903e0b8de4a56adf5 Mon Sep 17 00:00:00 2001 +From: Alex Manoussakis +Date: Thu, 5 Oct 2017 13:41:20 -0400 +Subject: HID: hid-elecom: extend to fix descriptor for HUGE trackball + +From: Alex Manoussakis + +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 +Signed-off-by: Alex Manoussakis +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman + +--- + 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 + * Copyright (c) 2016 Yuxuan Shui + * Copyright (c) 2017 Diego Elio Pettenò ++ * Copyright (c) 2017 Alex Manoussakis + */ + + /* +@@ -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 index 00000000000..3fc44cf6c85 --- /dev/null +++ b/queue-4.13/mm-page_vma_mapped-ensure-pmd-is-loaded-with-read_once-outside-of-lock.patch @@ -0,0 +1,122 @@ +From a7b100953aa33a5bbdc3e5e7f2241b9c0704606e Mon Sep 17 00:00:00 2001 +From: Will Deacon +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 + +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 +Tested-by: Yury Norov +Tested-by: Richard Ruigrok +Acked-by: Kirill A. Shutemov +Cc: "Paul E. McKenney" +Cc: Peter Zijlstra +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +[will: backport to 4.13.y] +Signed-off-by: Will Deacon +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..6534734cee6 --- /dev/null +++ b/queue-4.13/perf-pmu-unbreak-perf-record-for-arm-arm64-with-events-with-explicit-pmu.patch @@ -0,0 +1,200 @@ +From 66ec11919a0f96e936bb731fdbc2851316077d26 Mon Sep 17 00:00:00 2001 +From: Mark Rutland +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 + +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 +Tested-by Will Deacon +Acked-by: Jiri Olsa +Cc: Adrian Hunter +Cc: Borislav Petkov +Cc: David Ahern +Cc: Namhyung Kim +Cc: Peter Zijlstra +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..d446ef9c7ad --- /dev/null +++ b/queue-4.13/series @@ -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 index 00000000000..daa8a65d84b --- /dev/null +++ b/queue-4.13/x86-apic-silence-fw_bug-tsc_deadline-disabled-due-to-errata-on-cpus-without-the-feature.patch @@ -0,0 +1,57 @@ +From 594a30fb12424717a41c62323d2a8bf167dbccad Mon Sep 17 00:00:00 2001 +From: Hans de Goede +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 + +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 +Acked-by: Thomas Gleixner +Cc: Frank Mehnert +Cc: Linus Torvalds +Cc: Michael Thayer +Cc: Michal Necasek +Cc: Peter Zijlstra +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 +Signed-off-by: Paolo Bonzini +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..d41faa73d04 --- /dev/null +++ b/queue-4.13/x86-apic-silence-fw_bug-tsc_deadline-disabled-due-to-errata-on-hypervisors.patch @@ -0,0 +1,52 @@ +From cc6afe2240298049585e86b1ade85efc8a7f225d Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +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 + +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 +Signed-off-by: Thomas Gleixner +Cc: Peter Zijlstra +Cc: Hans de Goede +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 + +--- + 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);