From 1a83f0694797120f3d38047f2897b699ab8347b7 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 18 Feb 2022 10:18:16 +0100 Subject: [PATCH] 5.16-stable patches added patches: drm-amd-pm-correct-the-sequence-of-sending-gpu-reset-msg.patch drm-amdgpu-skipping-sdma-hw_init-and-hw_fini-for-s0ix.patch drm-atomic-don-t-pollute-crtc_state-mode_blob-with-error-pointers.patch drm-i915-fix-dbuf-slice-config-lookup.patch drm-i915-fix-mbus-join-config-lookup.patch drm-i915-opregion-check-port-number-bounds-for-swsci-display-power-state.patch drm-mediatek-mtk_dsi-avoid-eprobe_defer-loop-with-external-bridge.patch drm-radeon-fix-backlight-control-on-imac-12-1.patch iwlwifi-fix-use-after-free.patch iwlwifi-remove-deprecated-broadcast-filtering-feature.patch kvm-x86-nsvm-fix-potential-null-derefernce-on-nested-migration.patch kvm-x86-nsvm-mark-vmcb01-as-dirty-when-restoring-smm-saved-state.patch kvm-x86-nsvm-nvmx-set-nested_run_pending-on-vm-entry-which-is-a-result-of-rsm.patch kvm-x86-svm-don-t-passthrough-smap-smep-pke-bits-in-npt-gcr0.pg-case.patch kvm-x86-xen-fix-runstate-updates-to-be-atomic-when-preempting-vcpu.patch --- ...he-sequence-of-sending-gpu-reset-msg.patch | 41 + ...ng-sdma-hw_init-and-hw_fini-for-s0ix.patch | 55 ++ ..._state-mode_blob-with-error-pointers.patch | 52 ++ ...rm-i915-fix-dbuf-slice-config-lookup.patch | 46 ++ ...drm-i915-fix-mbus-join-config-lookup.patch | 39 + ...bounds-for-swsci-display-power-state.patch | 62 ++ ...robe_defer-loop-with-external-bridge.patch | 263 +++++++ ...n-fix-backlight-control-on-imac-12-1.patch | 33 + queue-5.16/iwlwifi-fix-use-after-free.patch | 48 ++ ...precated-broadcast-filtering-feature.patch | 728 ++++++++++++++++++ ...-null-derefernce-on-nested-migration.patch | 72 ++ ...dirty-when-restoring-smm-saved-state.patch | 49 ++ ...on-vm-entry-which-is-a-result-of-rsm.patch | 51 ++ ...ap-smep-pke-bits-in-npt-gcr0.pg-case.patch | 78 ++ ...es-to-be-atomic-when-preempting-vcpu.patch | 214 +++++ queue-5.16/series | 15 + 16 files changed, 1846 insertions(+) create mode 100644 queue-5.16/drm-amd-pm-correct-the-sequence-of-sending-gpu-reset-msg.patch create mode 100644 queue-5.16/drm-amdgpu-skipping-sdma-hw_init-and-hw_fini-for-s0ix.patch create mode 100644 queue-5.16/drm-atomic-don-t-pollute-crtc_state-mode_blob-with-error-pointers.patch create mode 100644 queue-5.16/drm-i915-fix-dbuf-slice-config-lookup.patch create mode 100644 queue-5.16/drm-i915-fix-mbus-join-config-lookup.patch create mode 100644 queue-5.16/drm-i915-opregion-check-port-number-bounds-for-swsci-display-power-state.patch create mode 100644 queue-5.16/drm-mediatek-mtk_dsi-avoid-eprobe_defer-loop-with-external-bridge.patch create mode 100644 queue-5.16/drm-radeon-fix-backlight-control-on-imac-12-1.patch create mode 100644 queue-5.16/iwlwifi-fix-use-after-free.patch create mode 100644 queue-5.16/iwlwifi-remove-deprecated-broadcast-filtering-feature.patch create mode 100644 queue-5.16/kvm-x86-nsvm-fix-potential-null-derefernce-on-nested-migration.patch create mode 100644 queue-5.16/kvm-x86-nsvm-mark-vmcb01-as-dirty-when-restoring-smm-saved-state.patch create mode 100644 queue-5.16/kvm-x86-nsvm-nvmx-set-nested_run_pending-on-vm-entry-which-is-a-result-of-rsm.patch create mode 100644 queue-5.16/kvm-x86-svm-don-t-passthrough-smap-smep-pke-bits-in-npt-gcr0.pg-case.patch create mode 100644 queue-5.16/kvm-x86-xen-fix-runstate-updates-to-be-atomic-when-preempting-vcpu.patch diff --git a/queue-5.16/drm-amd-pm-correct-the-sequence-of-sending-gpu-reset-msg.patch b/queue-5.16/drm-amd-pm-correct-the-sequence-of-sending-gpu-reset-msg.patch new file mode 100644 index 00000000000..fac7ff1e173 --- /dev/null +++ b/queue-5.16/drm-amd-pm-correct-the-sequence-of-sending-gpu-reset-msg.patch @@ -0,0 +1,41 @@ +From 9c4f59ea3f865693150edf0c91d1cc6b451360dd Mon Sep 17 00:00:00 2001 +From: Yifan Zhang +Date: Fri, 11 Feb 2022 17:58:08 +0800 +Subject: drm/amd/pm: correct the sequence of sending gpu reset msg + +From: Yifan Zhang + +commit 9c4f59ea3f865693150edf0c91d1cc6b451360dd upstream. + +the 2nd parameter should be smu msg type rather than asic msg index. + +Fixes: 7d38d9dc4ecc ("drm/amdgpu: add mode2 reset support for yellow carp") +Signed-off-by: Yifan Zhang +Acked-by: Aaron Liu +Reviewed-by: Huang Rui +Signed-off-by: Alex Deucher +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c | 9 ++------- + 1 file changed, 2 insertions(+), 7 deletions(-) + +--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c ++++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c +@@ -282,14 +282,9 @@ static int yellow_carp_post_smu_init(str + + static int yellow_carp_mode_reset(struct smu_context *smu, int type) + { +- int ret = 0, index = 0; ++ int ret = 0; + +- index = smu_cmn_to_asic_specific_index(smu, CMN2ASIC_MAPPING_MSG, +- SMU_MSG_GfxDeviceDriverReset); +- if (index < 0) +- return index == -EACCES ? 0 : index; +- +- ret = smu_cmn_send_smc_msg_with_param(smu, (uint16_t)index, type, NULL); ++ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GfxDeviceDriverReset, type, NULL); + if (ret) + dev_err(smu->adev->dev, "Failed to mode reset!\n"); + diff --git a/queue-5.16/drm-amdgpu-skipping-sdma-hw_init-and-hw_fini-for-s0ix.patch b/queue-5.16/drm-amdgpu-skipping-sdma-hw_init-and-hw_fini-for-s0ix.patch new file mode 100644 index 00000000000..6754683a846 --- /dev/null +++ b/queue-5.16/drm-amdgpu-skipping-sdma-hw_init-and-hw_fini-for-s0ix.patch @@ -0,0 +1,55 @@ +From f8f4e2a518347063179def4e64580b2d28233d03 Mon Sep 17 00:00:00 2001 +From: Rajib Mahapatra +Date: Thu, 10 Feb 2022 18:46:40 +0530 +Subject: drm/amdgpu: skipping SDMA hw_init and hw_fini for S0ix. + +From: Rajib Mahapatra + +commit f8f4e2a518347063179def4e64580b2d28233d03 upstream. + +[Why] +SDMA ring buffer test failed if suspend is aborted during +S0i3 resume. + +[How] +If suspend is aborted for some reason during S0i3 resume +cycle, it follows SDMA ring test failing and errors in amdgpu +resume. For RN/CZN/Picasso, SMU saves and restores SDMA +registers during S0ix cycle. So, skipping SDMA suspend and +resume from driver solves the issue. This time, the system +is able to resume gracefully even the suspend is aborted. + +Reviewed-by: Mario Limonciello +Reviewed-by: Alex Deucher +Signed-off-by: Rajib Mahapatra +Signed-off-by: Alex Deucher +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +@@ -2057,6 +2057,10 @@ static int sdma_v4_0_suspend(void *handl + { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + ++ /* SMU saves SDMA state for us */ ++ if (adev->in_s0ix) ++ return 0; ++ + return sdma_v4_0_hw_fini(adev); + } + +@@ -2064,6 +2068,10 @@ static int sdma_v4_0_resume(void *handle + { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + ++ /* SMU restores SDMA state for us */ ++ if (adev->in_s0ix) ++ return 0; ++ + return sdma_v4_0_hw_init(adev); + } + diff --git a/queue-5.16/drm-atomic-don-t-pollute-crtc_state-mode_blob-with-error-pointers.patch b/queue-5.16/drm-atomic-don-t-pollute-crtc_state-mode_blob-with-error-pointers.patch new file mode 100644 index 00000000000..19b190cbbea --- /dev/null +++ b/queue-5.16/drm-atomic-don-t-pollute-crtc_state-mode_blob-with-error-pointers.patch @@ -0,0 +1,52 @@ +From 439cf34c8e0a8a33d8c15a31be1b7423426bc765 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= +Date: Wed, 9 Feb 2022 11:19:27 +0200 +Subject: drm/atomic: Don't pollute crtc_state->mode_blob with error pointers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ville Syrjälä + +commit 439cf34c8e0a8a33d8c15a31be1b7423426bc765 upstream. + +Make sure we don't assign an error pointer to crtc_state->mode_blob +as that will break all kinds of places that assume either NULL or a +valid pointer (eg. drm_property_blob_put()). + +Cc: stable@vger.kernel.org +Reported-by: fuyufan +Signed-off-by: Ville Syrjälä +Link: https://patchwork.freedesktop.org/patch/msgid/20220209091928.14766-1-ville.syrjala@linux.intel.com +Acked-by: Maxime Ripard +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/drm_atomic_uapi.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +--- a/drivers/gpu/drm/drm_atomic_uapi.c ++++ b/drivers/gpu/drm/drm_atomic_uapi.c +@@ -76,15 +76,17 @@ int drm_atomic_set_mode_for_crtc(struct + state->mode_blob = NULL; + + if (mode) { ++ struct drm_property_blob *blob; ++ + drm_mode_convert_to_umode(&umode, mode); +- state->mode_blob = +- drm_property_create_blob(state->crtc->dev, +- sizeof(umode), +- &umode); +- if (IS_ERR(state->mode_blob)) +- return PTR_ERR(state->mode_blob); ++ blob = drm_property_create_blob(crtc->dev, ++ sizeof(umode), &umode); ++ if (IS_ERR(blob)) ++ return PTR_ERR(blob); + + drm_mode_copy(&state->mode, mode); ++ ++ state->mode_blob = blob; + state->enable = true; + drm_dbg_atomic(crtc->dev, + "Set [MODE:%s] for [CRTC:%d:%s] state %p\n", diff --git a/queue-5.16/drm-i915-fix-dbuf-slice-config-lookup.patch b/queue-5.16/drm-i915-fix-dbuf-slice-config-lookup.patch new file mode 100644 index 00000000000..7654d27e5e7 --- /dev/null +++ b/queue-5.16/drm-i915-fix-dbuf-slice-config-lookup.patch @@ -0,0 +1,46 @@ +From 698bef8ff5d2edea5d1c9d6e5adf1bfed1e8a106 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= +Date: Mon, 7 Feb 2022 15:26:59 +0200 +Subject: drm/i915: Fix dbuf slice config lookup +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ville Syrjälä + +commit 698bef8ff5d2edea5d1c9d6e5adf1bfed1e8a106 upstream. + +Apparently I totally fumbled the loop condition when I +removed the ARRAY_SIZE() stuff from the dbuf slice config +lookup. Comparing the loop index with the active_pipes bitmask +is utter nonsense, what we want to do is check to see if the +mask is zero or not. + +Note that the code actually ended up working correctly despite +the fumble, up until commit eef173954432 ("drm/i915: Allow +!join_mbus cases for adlp+ dbuf configuration") when things +broke for real. + +Cc: stable@vger.kernel.org +Fixes: 05e8155afe35 ("drm/i915: Use a sentinel to terminate the dbuf slice arrays") +Signed-off-by: Ville Syrjälä +Link: https://patchwork.freedesktop.org/patch/msgid/20220207132700.481-1-ville.syrjala@linux.intel.com +Reviewed-by: Jani Nikula +(cherry picked from commit a28fde308c3c1c174249ff9559b57f24e6850086) +Signed-off-by: Tvrtko Ursulin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/intel_pm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/i915/intel_pm.c ++++ b/drivers/gpu/drm/i915/intel_pm.c +@@ -4860,7 +4860,7 @@ static u8 compute_dbuf_slices(enum pipe + { + int i; + +- for (i = 0; i < dbuf_slices[i].active_pipes; i++) { ++ for (i = 0; dbuf_slices[i].active_pipes != 0; i++) { + if (dbuf_slices[i].active_pipes == active_pipes && + dbuf_slices[i].join_mbus == join_mbus) + return dbuf_slices[i].dbuf_mask[pipe]; diff --git a/queue-5.16/drm-i915-fix-mbus-join-config-lookup.patch b/queue-5.16/drm-i915-fix-mbus-join-config-lookup.patch new file mode 100644 index 00000000000..d18b1d8a4f0 --- /dev/null +++ b/queue-5.16/drm-i915-fix-mbus-join-config-lookup.patch @@ -0,0 +1,39 @@ +From 8d9d2a723d64b650f2e6423024ccb4a33f0cdc40 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= +Date: Mon, 7 Feb 2022 15:27:00 +0200 +Subject: drm/i915: Fix mbus join config lookup +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ville Syrjälä + +commit 8d9d2a723d64b650f2e6423024ccb4a33f0cdc40 upstream. + +The bogus loop from compute_dbuf_slices() was copied into +check_mbus_joined() as well. So this lookup is wrong as well. +Fix it. + +Cc: stable@vger.kernel.org +Fixes: f4dc00863226 ("drm/i915/adl_p: MBUS programming") +Signed-off-by: Ville Syrjälä +Link: https://patchwork.freedesktop.org/patch/msgid/20220207132700.481-2-ville.syrjala@linux.intel.com +Reviewed-by: Jani Nikula +(cherry picked from commit 053f2b85631316a9226f6340c1c0fd95634f7a5b) +Signed-off-by: Tvrtko Ursulin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/intel_pm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/i915/intel_pm.c ++++ b/drivers/gpu/drm/i915/intel_pm.c +@@ -4843,7 +4843,7 @@ static bool check_mbus_joined(u8 active_ + { + int i; + +- for (i = 0; i < dbuf_slices[i].active_pipes; i++) { ++ for (i = 0; dbuf_slices[i].active_pipes != 0; i++) { + if (dbuf_slices[i].active_pipes == active_pipes) + return dbuf_slices[i].join_mbus; + } diff --git a/queue-5.16/drm-i915-opregion-check-port-number-bounds-for-swsci-display-power-state.patch b/queue-5.16/drm-i915-opregion-check-port-number-bounds-for-swsci-display-power-state.patch new file mode 100644 index 00000000000..583f8b1fc7c --- /dev/null +++ b/queue-5.16/drm-i915-opregion-check-port-number-bounds-for-swsci-display-power-state.patch @@ -0,0 +1,62 @@ +From ea958422291de248b9e2eaaeea36004e84b64043 Mon Sep 17 00:00:00 2001 +From: Jani Nikula +Date: Thu, 10 Feb 2022 12:36:42 +0200 +Subject: drm/i915/opregion: check port number bounds for SWSCI display power state +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jani Nikula + +commit ea958422291de248b9e2eaaeea36004e84b64043 upstream. + +The mapping from enum port to whatever port numbering scheme is used by +the SWSCI Display Power State Notification is odd, and the memory of it +has faded. In any case, the parameter only has space for ports numbered +[0..4], and UBSAN reports bit shift beyond it when the platform has port +F or more. + +Since the SWSCI functionality is supposed to be obsolete for new +platforms (i.e. ones that might have port F or more), just bail out +early if the mapped and mangled port number is beyond what the Display +Power State Notification can support. + +Fixes: 9c4b0a683193 ("drm/i915: add opregion function to notify bios of encoder enable/disable") +Cc: # v3.13+ +Cc: Ville Syrjälä +Cc: Lucas De Marchi +Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/4800 +Signed-off-by: Jani Nikula +Reviewed-by: Ville Syrjälä +Link: https://patchwork.freedesktop.org/patch/msgid/cc363f42d6b5a5932b6d218fefcc8bdfb15dbbe5.1644489329.git.jani.nikula@intel.com +(cherry picked from commit 24a644ebbfd3b13cda702f98907f9dd123e34bf9) +Signed-off-by: Tvrtko Ursulin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/display/intel_opregion.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +--- a/drivers/gpu/drm/i915/display/intel_opregion.c ++++ b/drivers/gpu/drm/i915/display/intel_opregion.c +@@ -360,6 +360,21 @@ int intel_opregion_notify_encoder(struct + port++; + } + ++ /* ++ * The port numbering and mapping here is bizarre. The now-obsolete ++ * swsci spec supports ports numbered [0..4]. Port E is handled as a ++ * special case, but port F and beyond are not. The functionality is ++ * supposed to be obsolete for new platforms. Just bail out if the port ++ * number is out of bounds after mapping. ++ */ ++ if (port > 4) { ++ drm_dbg_kms(&dev_priv->drm, ++ "[ENCODER:%d:%s] port %c (index %u) out of bounds for display power state notification\n", ++ intel_encoder->base.base.id, intel_encoder->base.name, ++ port_name(intel_encoder->port), port); ++ return -EINVAL; ++ } ++ + if (!enable) + parm |= 4 << 8; + diff --git a/queue-5.16/drm-mediatek-mtk_dsi-avoid-eprobe_defer-loop-with-external-bridge.patch b/queue-5.16/drm-mediatek-mtk_dsi-avoid-eprobe_defer-loop-with-external-bridge.patch new file mode 100644 index 00000000000..84577be48f5 --- /dev/null +++ b/queue-5.16/drm-mediatek-mtk_dsi-avoid-eprobe_defer-loop-with-external-bridge.patch @@ -0,0 +1,263 @@ +From 647474b8d980256b26b1cd112d7333a4dbd4260a Mon Sep 17 00:00:00 2001 +From: AngeloGioacchino Del Regno +Date: Mon, 31 Jan 2022 09:55:20 +0100 +Subject: drm/mediatek: mtk_dsi: Avoid EPROBE_DEFER loop with external bridge +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: AngeloGioacchino Del Regno + +commit 647474b8d980256b26b1cd112d7333a4dbd4260a upstream. + +DRM bridge drivers are now attaching their DSI device at probe time, +which requires us to register our DSI host in order to let the bridge +to probe: this recently started producing an endless -EPROBE_DEFER +loop on some machines that are using external bridges, like the +parade-ps8640, found on the ACER Chromebook R13. + +Now that the DSI hosts/devices probe sequence is documented, we can +do adjustments to the mtk_dsi driver as to both fix now and make sure +to avoid this situation in the future: for this, following what is +documented in drm_bridge.c, move the mtk_dsi component_add() to the +mtk_dsi_ops.attach callback and delete it in the detach callback; +keeping in mind that we are registering a drm_bridge for our DSI, +which is only used/attached if the DSI Host is bound, it wouldn't +make sense to keep adding our bridge at probe time (as it would +be useless to have it if mtk_dsi_ops.attach() fails!), so also move +that one to the dsi host attach function (and remove it in detach). + +Cc: # 5.15.x +Signed-off-by: AngeloGioacchino Del Regno +Reviewed-by: Andrzej Hajda +Reviewed-by: Jagan Teki +Tested-by: Nícolas F. R. A. Prado +Signed-off-by: Chun-Kuang Hu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/mediatek/mtk_dsi.c | 167 ++++++++++++++++++------------------- + 1 file changed, 84 insertions(+), 83 deletions(-) + +--- a/drivers/gpu/drm/mediatek/mtk_dsi.c ++++ b/drivers/gpu/drm/mediatek/mtk_dsi.c +@@ -786,18 +786,101 @@ void mtk_dsi_ddp_stop(struct device *dev + mtk_dsi_poweroff(dsi); + } + ++static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi) ++{ ++ int ret; ++ ++ ret = drm_simple_encoder_init(drm, &dsi->encoder, ++ DRM_MODE_ENCODER_DSI); ++ if (ret) { ++ DRM_ERROR("Failed to encoder init to drm\n"); ++ return ret; ++ } ++ ++ dsi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm, dsi->host.dev); ++ ++ ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL, ++ DRM_BRIDGE_ATTACH_NO_CONNECTOR); ++ if (ret) ++ goto err_cleanup_encoder; ++ ++ dsi->connector = drm_bridge_connector_init(drm, &dsi->encoder); ++ if (IS_ERR(dsi->connector)) { ++ DRM_ERROR("Unable to create bridge connector\n"); ++ ret = PTR_ERR(dsi->connector); ++ goto err_cleanup_encoder; ++ } ++ drm_connector_attach_encoder(dsi->connector, &dsi->encoder); ++ ++ return 0; ++ ++err_cleanup_encoder: ++ drm_encoder_cleanup(&dsi->encoder); ++ return ret; ++} ++ ++static int mtk_dsi_bind(struct device *dev, struct device *master, void *data) ++{ ++ int ret; ++ struct drm_device *drm = data; ++ struct mtk_dsi *dsi = dev_get_drvdata(dev); ++ ++ ret = mtk_dsi_encoder_init(drm, dsi); ++ if (ret) ++ return ret; ++ ++ return device_reset_optional(dev); ++} ++ ++static void mtk_dsi_unbind(struct device *dev, struct device *master, ++ void *data) ++{ ++ struct mtk_dsi *dsi = dev_get_drvdata(dev); ++ ++ drm_encoder_cleanup(&dsi->encoder); ++} ++ ++static const struct component_ops mtk_dsi_component_ops = { ++ .bind = mtk_dsi_bind, ++ .unbind = mtk_dsi_unbind, ++}; ++ + static int mtk_dsi_host_attach(struct mipi_dsi_host *host, + struct mipi_dsi_device *device) + { + struct mtk_dsi *dsi = host_to_dsi(host); ++ struct device *dev = host->dev; ++ int ret; + + dsi->lanes = device->lanes; + dsi->format = device->format; + dsi->mode_flags = device->mode_flags; ++ dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0); ++ if (IS_ERR(dsi->next_bridge)) ++ return PTR_ERR(dsi->next_bridge); ++ ++ drm_bridge_add(&dsi->bridge); ++ ++ ret = component_add(host->dev, &mtk_dsi_component_ops); ++ if (ret) { ++ DRM_ERROR("failed to add dsi_host component: %d\n", ret); ++ drm_bridge_remove(&dsi->bridge); ++ return ret; ++ } + + return 0; + } + ++static int mtk_dsi_host_detach(struct mipi_dsi_host *host, ++ struct mipi_dsi_device *device) ++{ ++ struct mtk_dsi *dsi = host_to_dsi(host); ++ ++ component_del(host->dev, &mtk_dsi_component_ops); ++ drm_bridge_remove(&dsi->bridge); ++ return 0; ++} ++ + static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi) + { + int ret; +@@ -938,73 +1021,14 @@ static ssize_t mtk_dsi_host_transfer(str + + static const struct mipi_dsi_host_ops mtk_dsi_ops = { + .attach = mtk_dsi_host_attach, ++ .detach = mtk_dsi_host_detach, + .transfer = mtk_dsi_host_transfer, + }; + +-static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi) +-{ +- int ret; +- +- ret = drm_simple_encoder_init(drm, &dsi->encoder, +- DRM_MODE_ENCODER_DSI); +- if (ret) { +- DRM_ERROR("Failed to encoder init to drm\n"); +- return ret; +- } +- +- dsi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm, dsi->host.dev); +- +- ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL, +- DRM_BRIDGE_ATTACH_NO_CONNECTOR); +- if (ret) +- goto err_cleanup_encoder; +- +- dsi->connector = drm_bridge_connector_init(drm, &dsi->encoder); +- if (IS_ERR(dsi->connector)) { +- DRM_ERROR("Unable to create bridge connector\n"); +- ret = PTR_ERR(dsi->connector); +- goto err_cleanup_encoder; +- } +- drm_connector_attach_encoder(dsi->connector, &dsi->encoder); +- +- return 0; +- +-err_cleanup_encoder: +- drm_encoder_cleanup(&dsi->encoder); +- return ret; +-} +- +-static int mtk_dsi_bind(struct device *dev, struct device *master, void *data) +-{ +- int ret; +- struct drm_device *drm = data; +- struct mtk_dsi *dsi = dev_get_drvdata(dev); +- +- ret = mtk_dsi_encoder_init(drm, dsi); +- if (ret) +- return ret; +- +- return device_reset_optional(dev); +-} +- +-static void mtk_dsi_unbind(struct device *dev, struct device *master, +- void *data) +-{ +- struct mtk_dsi *dsi = dev_get_drvdata(dev); +- +- drm_encoder_cleanup(&dsi->encoder); +-} +- +-static const struct component_ops mtk_dsi_component_ops = { +- .bind = mtk_dsi_bind, +- .unbind = mtk_dsi_unbind, +-}; +- + static int mtk_dsi_probe(struct platform_device *pdev) + { + struct mtk_dsi *dsi; + struct device *dev = &pdev->dev; +- struct drm_panel *panel; + struct resource *regs; + int irq_num; + int ret; +@@ -1021,19 +1045,6 @@ static int mtk_dsi_probe(struct platform + return ret; + } + +- ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, +- &panel, &dsi->next_bridge); +- if (ret) +- goto err_unregister_host; +- +- if (panel) { +- dsi->next_bridge = devm_drm_panel_bridge_add(dev, panel); +- if (IS_ERR(dsi->next_bridge)) { +- ret = PTR_ERR(dsi->next_bridge); +- goto err_unregister_host; +- } +- } +- + dsi->driver_data = of_device_get_match_data(dev); + + dsi->engine_clk = devm_clk_get(dev, "engine"); +@@ -1098,14 +1109,6 @@ static int mtk_dsi_probe(struct platform + dsi->bridge.of_node = dev->of_node; + dsi->bridge.type = DRM_MODE_CONNECTOR_DSI; + +- drm_bridge_add(&dsi->bridge); +- +- ret = component_add(&pdev->dev, &mtk_dsi_component_ops); +- if (ret) { +- dev_err(&pdev->dev, "failed to add component: %d\n", ret); +- goto err_unregister_host; +- } +- + return 0; + + err_unregister_host: +@@ -1118,8 +1121,6 @@ static int mtk_dsi_remove(struct platfor + struct mtk_dsi *dsi = platform_get_drvdata(pdev); + + mtk_output_dsi_disable(dsi); +- drm_bridge_remove(&dsi->bridge); +- component_del(&pdev->dev, &mtk_dsi_component_ops); + mipi_dsi_host_unregister(&dsi->host); + + return 0; diff --git a/queue-5.16/drm-radeon-fix-backlight-control-on-imac-12-1.patch b/queue-5.16/drm-radeon-fix-backlight-control-on-imac-12-1.patch new file mode 100644 index 00000000000..dcf174876e1 --- /dev/null +++ b/queue-5.16/drm-radeon-fix-backlight-control-on-imac-12-1.patch @@ -0,0 +1,33 @@ +From 364438fd629f7611a84c8e6d7de91659300f1502 Mon Sep 17 00:00:00 2001 +From: Nicholas Bishop +Date: Fri, 11 Feb 2022 14:57:39 -0500 +Subject: drm/radeon: Fix backlight control on iMac 12,1 + +From: Nicholas Bishop + +commit 364438fd629f7611a84c8e6d7de91659300f1502 upstream. + +The iMac 12,1 does not use the gmux driver for backlight, so the radeon +backlight device is needed to set the brightness. + +Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1838 +Signed-off-by: Nicholas Bishop +Signed-off-by: Alex Deucher +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/radeon/atombios_encoders.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/radeon/atombios_encoders.c ++++ b/drivers/gpu/drm/radeon/atombios_encoders.c +@@ -198,7 +198,8 @@ void radeon_atom_backlight_init(struct r + * so don't register a backlight device + */ + if ((rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE) && +- (rdev->pdev->device == 0x6741)) ++ (rdev->pdev->device == 0x6741) && ++ !dmi_match(DMI_PRODUCT_NAME, "iMac12,1")) + return; + + if (!radeon_encoder->enc_priv) diff --git a/queue-5.16/iwlwifi-fix-use-after-free.patch b/queue-5.16/iwlwifi-fix-use-after-free.patch new file mode 100644 index 00000000000..2cd3e14aacb --- /dev/null +++ b/queue-5.16/iwlwifi-fix-use-after-free.patch @@ -0,0 +1,48 @@ +From bea2662e7818e15d7607d17d57912ac984275d94 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Tue, 8 Feb 2022 11:47:30 +0100 +Subject: iwlwifi: fix use-after-free +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Johannes Berg + +commit bea2662e7818e15d7607d17d57912ac984275d94 upstream. + +If no firmware was present at all (or, presumably, all of the +firmware files failed to parse), we end up unbinding by calling +device_release_driver(), which calls remove(), which then in +iwlwifi calls iwl_drv_stop(), freeing the 'drv' struct. However +the new code I added will still erroneously access it after it +was freed. + +Set 'failure=false' in this case to avoid the access, all data +was already freed anyway. + +Cc: stable@vger.kernel.org +Reported-by: Stefan Agner +Reported-by: Wolfgang Walter +Reported-by: Jason Self +Reported-by: Dominik Behr +Reported-by: Marek Marczykowski-Górecki +Fixes: ab07506b0454 ("iwlwifi: fix leaks/bad data after failed firmware load") +Signed-off-by: Johannes Berg +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20220208114728.e6b514cf4c85.Iffb575ca2a623d7859b542c33b2a507d01554251@changeid +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c ++++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +@@ -1656,6 +1656,8 @@ static void iwl_req_fw_callback(const st + out_unbind: + complete(&drv->request_firmware_complete); + device_release_driver(drv->trans->dev); ++ /* drv has just been freed by the release */ ++ failure = false; + free: + if (failure) + iwl_dealloc_ucode(drv); diff --git a/queue-5.16/iwlwifi-remove-deprecated-broadcast-filtering-feature.patch b/queue-5.16/iwlwifi-remove-deprecated-broadcast-filtering-feature.patch new file mode 100644 index 00000000000..4529e88d7a1 --- /dev/null +++ b/queue-5.16/iwlwifi-remove-deprecated-broadcast-filtering-feature.patch @@ -0,0 +1,728 @@ +From 92883a524ae918736a7b8acef98698075507b8c1 Mon Sep 17 00:00:00 2001 +From: Luca Coelho +Date: Fri, 28 Jan 2022 14:48:50 +0200 +Subject: iwlwifi: remove deprecated broadcast filtering feature + +From: Luca Coelho + +commit 92883a524ae918736a7b8acef98698075507b8c1 upstream. + +This feature has been deprecated and should not be used anymore. With +newer firmwares, namely *-67.ucode and above, trying to use it causes an +assertion failure in the FW, similar to this: + +[Tue Jan 11 20:05:24 2022] iwlwifi 0000:04:00.0: 0x00001062 | ADVANCED_SYSASSERT + +In order to prevent this feature from being used, remove it entirely +and get rid of the Kconfig option that +enables it (IWLWIFI_BCAST_FILTERING). + +Fixes: cbaa6aeedee5 ("iwlwifi: bump FW API to 67 for AX devices") +Link: https://bugzilla.kernel.org/show_bug.cgi?id=215488 +Cc: stable@vger.kernel.org # 5.16.x +Signed-off-by: Luca Coelho +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/iwlwifi.20220128144623.9241e049f13e.Ia4f282813ca2ddd24c13427823519113f2bbebf2@changeid +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wireless/intel/iwlwifi/Kconfig | 13 - + drivers/net/wireless/intel/iwlwifi/fw/api/commands.h | 5 + drivers/net/wireless/intel/iwlwifi/fw/api/filter.h | 88 ------ + drivers/net/wireless/intel/iwlwifi/fw/file.h | 2 + drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c | 203 ---------------- + drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 240 ------------------- + drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 13 - + drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 1 + 8 files changed, 565 deletions(-) + +--- a/drivers/net/wireless/intel/iwlwifi/Kconfig ++++ b/drivers/net/wireless/intel/iwlwifi/Kconfig +@@ -79,19 +79,6 @@ config IWLWIFI_OPMODE_MODULAR + comment "WARNING: iwlwifi is useless without IWLDVM or IWLMVM" + depends on IWLDVM=n && IWLMVM=n + +-config IWLWIFI_BCAST_FILTERING +- bool "Enable broadcast filtering" +- depends on IWLMVM +- help +- Say Y here to enable default bcast filtering configuration. +- +- Enabling broadcast filtering will drop any incoming wireless +- broadcast frames, except some very specific predefined +- patterns (e.g. incoming arp requests). +- +- If unsure, don't enable this option, as some programs might +- expect incoming broadcasts for their normal operations. +- + menu "Debugging Options" + + config IWLWIFI_DEBUG +--- a/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h ++++ b/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h +@@ -506,11 +506,6 @@ enum iwl_legacy_cmds { + DEBUG_LOG_MSG = 0xf7, + + /** +- * @BCAST_FILTER_CMD: &struct iwl_bcast_filter_cmd +- */ +- BCAST_FILTER_CMD = 0xcf, +- +- /** + * @MCAST_FILTER_CMD: &struct iwl_mcast_filter_cmd + */ + MCAST_FILTER_CMD = 0xd0, +--- a/drivers/net/wireless/intel/iwlwifi/fw/api/filter.h ++++ b/drivers/net/wireless/intel/iwlwifi/fw/api/filter.h +@@ -36,92 +36,4 @@ struct iwl_mcast_filter_cmd { + u8 addr_list[0]; + } __packed; /* MCAST_FILTERING_CMD_API_S_VER_1 */ + +-#define MAX_BCAST_FILTERS 8 +-#define MAX_BCAST_FILTER_ATTRS 2 +- +-/** +- * enum iwl_mvm_bcast_filter_attr_offset - written by fw for each Rx packet +- * @BCAST_FILTER_OFFSET_PAYLOAD_START: offset is from payload start. +- * @BCAST_FILTER_OFFSET_IP_END: offset is from ip header end (i.e. +- * start of ip payload). +- */ +-enum iwl_mvm_bcast_filter_attr_offset { +- BCAST_FILTER_OFFSET_PAYLOAD_START = 0, +- BCAST_FILTER_OFFSET_IP_END = 1, +-}; +- +-/** +- * struct iwl_fw_bcast_filter_attr - broadcast filter attribute +- * @offset_type: &enum iwl_mvm_bcast_filter_attr_offset. +- * @offset: starting offset of this pattern. +- * @reserved1: reserved +- * @val: value to match - big endian (MSB is the first +- * byte to match from offset pos). +- * @mask: mask to match (big endian). +- */ +-struct iwl_fw_bcast_filter_attr { +- u8 offset_type; +- u8 offset; +- __le16 reserved1; +- __be32 val; +- __be32 mask; +-} __packed; /* BCAST_FILTER_ATT_S_VER_1 */ +- +-/** +- * enum iwl_mvm_bcast_filter_frame_type - filter frame type +- * @BCAST_FILTER_FRAME_TYPE_ALL: consider all frames. +- * @BCAST_FILTER_FRAME_TYPE_IPV4: consider only ipv4 frames +- */ +-enum iwl_mvm_bcast_filter_frame_type { +- BCAST_FILTER_FRAME_TYPE_ALL = 0, +- BCAST_FILTER_FRAME_TYPE_IPV4 = 1, +-}; +- +-/** +- * struct iwl_fw_bcast_filter - broadcast filter +- * @discard: discard frame (1) or let it pass (0). +- * @frame_type: &enum iwl_mvm_bcast_filter_frame_type. +- * @reserved1: reserved +- * @num_attrs: number of valid attributes in this filter. +- * @attrs: attributes of this filter. a filter is considered matched +- * only when all its attributes are matched (i.e. AND relationship) +- */ +-struct iwl_fw_bcast_filter { +- u8 discard; +- u8 frame_type; +- u8 num_attrs; +- u8 reserved1; +- struct iwl_fw_bcast_filter_attr attrs[MAX_BCAST_FILTER_ATTRS]; +-} __packed; /* BCAST_FILTER_S_VER_1 */ +- +-/** +- * struct iwl_fw_bcast_mac - per-mac broadcast filtering configuration. +- * @default_discard: default action for this mac (discard (1) / pass (0)). +- * @reserved1: reserved +- * @attached_filters: bitmap of relevant filters for this mac. +- */ +-struct iwl_fw_bcast_mac { +- u8 default_discard; +- u8 reserved1; +- __le16 attached_filters; +-} __packed; /* BCAST_MAC_CONTEXT_S_VER_1 */ +- +-/** +- * struct iwl_bcast_filter_cmd - broadcast filtering configuration +- * @disable: enable (0) / disable (1) +- * @max_bcast_filters: max number of filters (MAX_BCAST_FILTERS) +- * @max_macs: max number of macs (NUM_MAC_INDEX_DRIVER) +- * @reserved1: reserved +- * @filters: broadcast filters +- * @macs: broadcast filtering configuration per-mac +- */ +-struct iwl_bcast_filter_cmd { +- u8 disable; +- u8 max_bcast_filters; +- u8 max_macs; +- u8 reserved1; +- struct iwl_fw_bcast_filter filters[MAX_BCAST_FILTERS]; +- struct iwl_fw_bcast_mac macs[NUM_MAC_INDEX_DRIVER]; +-} __packed; /* BCAST_FILTERING_HCMD_API_S_VER_1 */ +- + #endif /* __iwl_fw_api_filter_h__ */ +--- a/drivers/net/wireless/intel/iwlwifi/fw/file.h ++++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h +@@ -182,7 +182,6 @@ struct iwl_ucode_capa { + * @IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE: new NS offload (large version) + * @IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT: General support for uAPSD + * @IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD: P2P client supports uAPSD power save +- * @IWL_UCODE_TLV_FLAGS_BCAST_FILTERING: uCode supports broadcast filtering. + * @IWL_UCODE_TLV_FLAGS_EBS_SUPPORT: this uCode image supports EBS. + */ + enum iwl_ucode_tlv_flag { +@@ -197,7 +196,6 @@ enum iwl_ucode_tlv_flag { + IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT = BIT(24), + IWL_UCODE_TLV_FLAGS_EBS_SUPPORT = BIT(25), + IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD = BIT(26), +- IWL_UCODE_TLV_FLAGS_BCAST_FILTERING = BIT(29), + }; + + typedef unsigned int __bitwise iwl_ucode_tlv_api_t; +--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +@@ -1361,189 +1361,6 @@ static ssize_t iwl_dbgfs_dbg_time_point_ + return count; + } + +-#define ADD_TEXT(...) pos += scnprintf(buf + pos, bufsz - pos, __VA_ARGS__) +-#ifdef CONFIG_IWLWIFI_BCAST_FILTERING +-static ssize_t iwl_dbgfs_bcast_filters_read(struct file *file, +- char __user *user_buf, +- size_t count, loff_t *ppos) +-{ +- struct iwl_mvm *mvm = file->private_data; +- struct iwl_bcast_filter_cmd cmd; +- const struct iwl_fw_bcast_filter *filter; +- char *buf; +- int bufsz = 1024; +- int i, j, pos = 0; +- ssize_t ret; +- +- buf = kzalloc(bufsz, GFP_KERNEL); +- if (!buf) +- return -ENOMEM; +- +- mutex_lock(&mvm->mutex); +- if (!iwl_mvm_bcast_filter_build_cmd(mvm, &cmd)) { +- ADD_TEXT("None\n"); +- mutex_unlock(&mvm->mutex); +- goto out; +- } +- mutex_unlock(&mvm->mutex); +- +- for (i = 0; cmd.filters[i].attrs[0].mask; i++) { +- filter = &cmd.filters[i]; +- +- ADD_TEXT("Filter [%d]:\n", i); +- ADD_TEXT("\tDiscard=%d\n", filter->discard); +- ADD_TEXT("\tFrame Type: %s\n", +- filter->frame_type ? "IPv4" : "Generic"); +- +- for (j = 0; j < ARRAY_SIZE(filter->attrs); j++) { +- const struct iwl_fw_bcast_filter_attr *attr; +- +- attr = &filter->attrs[j]; +- if (!attr->mask) +- break; +- +- ADD_TEXT("\tAttr [%d]: offset=%d (from %s), mask=0x%x, value=0x%x reserved=0x%x\n", +- j, attr->offset, +- attr->offset_type ? "IP End" : +- "Payload Start", +- be32_to_cpu(attr->mask), +- be32_to_cpu(attr->val), +- le16_to_cpu(attr->reserved1)); +- } +- } +-out: +- ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); +- kfree(buf); +- return ret; +-} +- +-static ssize_t iwl_dbgfs_bcast_filters_write(struct iwl_mvm *mvm, char *buf, +- size_t count, loff_t *ppos) +-{ +- int pos, next_pos; +- struct iwl_fw_bcast_filter filter = {}; +- struct iwl_bcast_filter_cmd cmd; +- u32 filter_id, attr_id, mask, value; +- int err = 0; +- +- if (sscanf(buf, "%d %hhi %hhi %n", &filter_id, &filter.discard, +- &filter.frame_type, &pos) != 3) +- return -EINVAL; +- +- if (filter_id >= ARRAY_SIZE(mvm->dbgfs_bcast_filtering.cmd.filters) || +- filter.frame_type > BCAST_FILTER_FRAME_TYPE_IPV4) +- return -EINVAL; +- +- for (attr_id = 0; attr_id < ARRAY_SIZE(filter.attrs); +- attr_id++) { +- struct iwl_fw_bcast_filter_attr *attr = +- &filter.attrs[attr_id]; +- +- if (pos >= count) +- break; +- +- if (sscanf(&buf[pos], "%hhi %hhi %i %i %n", +- &attr->offset, &attr->offset_type, +- &mask, &value, &next_pos) != 4) +- return -EINVAL; +- +- attr->mask = cpu_to_be32(mask); +- attr->val = cpu_to_be32(value); +- if (mask) +- filter.num_attrs++; +- +- pos += next_pos; +- } +- +- mutex_lock(&mvm->mutex); +- memcpy(&mvm->dbgfs_bcast_filtering.cmd.filters[filter_id], +- &filter, sizeof(filter)); +- +- /* send updated bcast filtering configuration */ +- if (iwl_mvm_firmware_running(mvm) && +- mvm->dbgfs_bcast_filtering.override && +- iwl_mvm_bcast_filter_build_cmd(mvm, &cmd)) +- err = iwl_mvm_send_cmd_pdu(mvm, BCAST_FILTER_CMD, 0, +- sizeof(cmd), &cmd); +- mutex_unlock(&mvm->mutex); +- +- return err ?: count; +-} +- +-static ssize_t iwl_dbgfs_bcast_filters_macs_read(struct file *file, +- char __user *user_buf, +- size_t count, loff_t *ppos) +-{ +- struct iwl_mvm *mvm = file->private_data; +- struct iwl_bcast_filter_cmd cmd; +- char *buf; +- int bufsz = 1024; +- int i, pos = 0; +- ssize_t ret; +- +- buf = kzalloc(bufsz, GFP_KERNEL); +- if (!buf) +- return -ENOMEM; +- +- mutex_lock(&mvm->mutex); +- if (!iwl_mvm_bcast_filter_build_cmd(mvm, &cmd)) { +- ADD_TEXT("None\n"); +- mutex_unlock(&mvm->mutex); +- goto out; +- } +- mutex_unlock(&mvm->mutex); +- +- for (i = 0; i < ARRAY_SIZE(cmd.macs); i++) { +- const struct iwl_fw_bcast_mac *mac = &cmd.macs[i]; +- +- ADD_TEXT("Mac [%d]: discard=%d attached_filters=0x%x\n", +- i, mac->default_discard, mac->attached_filters); +- } +-out: +- ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); +- kfree(buf); +- return ret; +-} +- +-static ssize_t iwl_dbgfs_bcast_filters_macs_write(struct iwl_mvm *mvm, +- char *buf, size_t count, +- loff_t *ppos) +-{ +- struct iwl_bcast_filter_cmd cmd; +- struct iwl_fw_bcast_mac mac = {}; +- u32 mac_id, attached_filters; +- int err = 0; +- +- if (!mvm->bcast_filters) +- return -ENOENT; +- +- if (sscanf(buf, "%d %hhi %i", &mac_id, &mac.default_discard, +- &attached_filters) != 3) +- return -EINVAL; +- +- if (mac_id >= ARRAY_SIZE(cmd.macs) || +- mac.default_discard > 1 || +- attached_filters >= BIT(ARRAY_SIZE(cmd.filters))) +- return -EINVAL; +- +- mac.attached_filters = cpu_to_le16(attached_filters); +- +- mutex_lock(&mvm->mutex); +- memcpy(&mvm->dbgfs_bcast_filtering.cmd.macs[mac_id], +- &mac, sizeof(mac)); +- +- /* send updated bcast filtering configuration */ +- if (iwl_mvm_firmware_running(mvm) && +- mvm->dbgfs_bcast_filtering.override && +- iwl_mvm_bcast_filter_build_cmd(mvm, &cmd)) +- err = iwl_mvm_send_cmd_pdu(mvm, BCAST_FILTER_CMD, 0, +- sizeof(cmd), &cmd); +- mutex_unlock(&mvm->mutex); +- +- return err ?: count; +-} +-#endif +- + #define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \ + _MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct iwl_mvm) + #define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \ +@@ -1873,11 +1690,6 @@ MVM_DEBUGFS_WRITE_FILE_OPS(inject_beacon + + MVM_DEBUGFS_READ_FILE_OPS(uapsd_noagg_bssids); + +-#ifdef CONFIG_IWLWIFI_BCAST_FILTERING +-MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256); +-MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256); +-#endif +- + #ifdef CONFIG_ACPI + MVM_DEBUGFS_READ_FILE_OPS(sar_geo_profile); + #endif +@@ -2088,21 +1900,6 @@ void iwl_mvm_dbgfs_register(struct iwl_m + + MVM_DEBUGFS_ADD_FILE(uapsd_noagg_bssids, mvm->debugfs_dir, S_IRUSR); + +-#ifdef CONFIG_IWLWIFI_BCAST_FILTERING +- if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BCAST_FILTERING) { +- bcast_dir = debugfs_create_dir("bcast_filtering", +- mvm->debugfs_dir); +- +- debugfs_create_bool("override", 0600, bcast_dir, +- &mvm->dbgfs_bcast_filtering.override); +- +- MVM_DEBUGFS_ADD_FILE_ALIAS("filters", bcast_filters, +- bcast_dir, 0600); +- MVM_DEBUGFS_ADD_FILE_ALIAS("macs", bcast_filters_macs, +- bcast_dir, 0600); +- } +-#endif +- + #ifdef CONFIG_PM_SLEEP + MVM_DEBUGFS_ADD_FILE(d3_test, mvm->debugfs_dir, 0400); + debugfs_create_bool("d3_wake_sysassert", 0600, mvm->debugfs_dir, +--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +@@ -55,79 +55,6 @@ static const struct ieee80211_iface_comb + }, + }; + +-#ifdef CONFIG_IWLWIFI_BCAST_FILTERING +-/* +- * Use the reserved field to indicate magic values. +- * these values will only be used internally by the driver, +- * and won't make it to the fw (reserved will be 0). +- * BC_FILTER_MAGIC_IP - configure the val of this attribute to +- * be the vif's ip address. in case there is not a single +- * ip address (0, or more than 1), this attribute will +- * be skipped. +- * BC_FILTER_MAGIC_MAC - set the val of this attribute to +- * the LSB bytes of the vif's mac address +- */ +-enum { +- BC_FILTER_MAGIC_NONE = 0, +- BC_FILTER_MAGIC_IP, +- BC_FILTER_MAGIC_MAC, +-}; +- +-static const struct iwl_fw_bcast_filter iwl_mvm_default_bcast_filters[] = { +- { +- /* arp */ +- .discard = 0, +- .frame_type = BCAST_FILTER_FRAME_TYPE_ALL, +- .attrs = { +- { +- /* frame type - arp, hw type - ethernet */ +- .offset_type = +- BCAST_FILTER_OFFSET_PAYLOAD_START, +- .offset = sizeof(rfc1042_header), +- .val = cpu_to_be32(0x08060001), +- .mask = cpu_to_be32(0xffffffff), +- }, +- { +- /* arp dest ip */ +- .offset_type = +- BCAST_FILTER_OFFSET_PAYLOAD_START, +- .offset = sizeof(rfc1042_header) + 2 + +- sizeof(struct arphdr) + +- ETH_ALEN + sizeof(__be32) + +- ETH_ALEN, +- .mask = cpu_to_be32(0xffffffff), +- /* mark it as special field */ +- .reserved1 = cpu_to_le16(BC_FILTER_MAGIC_IP), +- }, +- }, +- }, +- { +- /* dhcp offer bcast */ +- .discard = 0, +- .frame_type = BCAST_FILTER_FRAME_TYPE_IPV4, +- .attrs = { +- { +- /* udp dest port - 68 (bootp client)*/ +- .offset_type = BCAST_FILTER_OFFSET_IP_END, +- .offset = offsetof(struct udphdr, dest), +- .val = cpu_to_be32(0x00440000), +- .mask = cpu_to_be32(0xffff0000), +- }, +- { +- /* dhcp - lsb bytes of client hw address */ +- .offset_type = BCAST_FILTER_OFFSET_IP_END, +- .offset = 38, +- .mask = cpu_to_be32(0xffffffff), +- /* mark it as special field */ +- .reserved1 = cpu_to_le16(BC_FILTER_MAGIC_MAC), +- }, +- }, +- }, +- /* last filter must be empty */ +- {}, +-}; +-#endif +- + static const struct cfg80211_pmsr_capabilities iwl_mvm_pmsr_capa = { + .max_peers = IWL_MVM_TOF_MAX_APS, + .report_ap_tsf = 1, +@@ -683,11 +610,6 @@ int iwl_mvm_mac_setup_register(struct iw + } + #endif + +-#ifdef CONFIG_IWLWIFI_BCAST_FILTERING +- /* assign default bcast filtering configuration */ +- mvm->bcast_filters = iwl_mvm_default_bcast_filters; +-#endif +- + ret = iwl_mvm_leds_init(mvm); + if (ret) + return ret; +@@ -1803,162 +1725,6 @@ static void iwl_mvm_config_iface_filter( + mutex_unlock(&mvm->mutex); + } + +-#ifdef CONFIG_IWLWIFI_BCAST_FILTERING +-struct iwl_bcast_iter_data { +- struct iwl_mvm *mvm; +- struct iwl_bcast_filter_cmd *cmd; +- u8 current_filter; +-}; +- +-static void +-iwl_mvm_set_bcast_filter(struct ieee80211_vif *vif, +- const struct iwl_fw_bcast_filter *in_filter, +- struct iwl_fw_bcast_filter *out_filter) +-{ +- struct iwl_fw_bcast_filter_attr *attr; +- int i; +- +- memcpy(out_filter, in_filter, sizeof(*out_filter)); +- +- for (i = 0; i < ARRAY_SIZE(out_filter->attrs); i++) { +- attr = &out_filter->attrs[i]; +- +- if (!attr->mask) +- break; +- +- switch (attr->reserved1) { +- case cpu_to_le16(BC_FILTER_MAGIC_IP): +- if (vif->bss_conf.arp_addr_cnt != 1) { +- attr->mask = 0; +- continue; +- } +- +- attr->val = vif->bss_conf.arp_addr_list[0]; +- break; +- case cpu_to_le16(BC_FILTER_MAGIC_MAC): +- attr->val = *(__be32 *)&vif->addr[2]; +- break; +- default: +- break; +- } +- attr->reserved1 = 0; +- out_filter->num_attrs++; +- } +-} +- +-static void iwl_mvm_bcast_filter_iterator(void *_data, u8 *mac, +- struct ieee80211_vif *vif) +-{ +- struct iwl_bcast_iter_data *data = _data; +- struct iwl_mvm *mvm = data->mvm; +- struct iwl_bcast_filter_cmd *cmd = data->cmd; +- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); +- struct iwl_fw_bcast_mac *bcast_mac; +- int i; +- +- if (WARN_ON(mvmvif->id >= ARRAY_SIZE(cmd->macs))) +- return; +- +- bcast_mac = &cmd->macs[mvmvif->id]; +- +- /* +- * enable filtering only for associated stations, but not for P2P +- * Clients +- */ +- if (vif->type != NL80211_IFTYPE_STATION || vif->p2p || +- !vif->bss_conf.assoc) +- return; +- +- bcast_mac->default_discard = 1; +- +- /* copy all configured filters */ +- for (i = 0; mvm->bcast_filters[i].attrs[0].mask; i++) { +- /* +- * Make sure we don't exceed our filters limit. +- * if there is still a valid filter to be configured, +- * be on the safe side and just allow bcast for this mac. +- */ +- if (WARN_ON_ONCE(data->current_filter >= +- ARRAY_SIZE(cmd->filters))) { +- bcast_mac->default_discard = 0; +- bcast_mac->attached_filters = 0; +- break; +- } +- +- iwl_mvm_set_bcast_filter(vif, +- &mvm->bcast_filters[i], +- &cmd->filters[data->current_filter]); +- +- /* skip current filter if it contains no attributes */ +- if (!cmd->filters[data->current_filter].num_attrs) +- continue; +- +- /* attach the filter to current mac */ +- bcast_mac->attached_filters |= +- cpu_to_le16(BIT(data->current_filter)); +- +- data->current_filter++; +- } +-} +- +-bool iwl_mvm_bcast_filter_build_cmd(struct iwl_mvm *mvm, +- struct iwl_bcast_filter_cmd *cmd) +-{ +- struct iwl_bcast_iter_data iter_data = { +- .mvm = mvm, +- .cmd = cmd, +- }; +- +- if (IWL_MVM_FW_BCAST_FILTER_PASS_ALL) +- return false; +- +- memset(cmd, 0, sizeof(*cmd)); +- cmd->max_bcast_filters = ARRAY_SIZE(cmd->filters); +- cmd->max_macs = ARRAY_SIZE(cmd->macs); +- +-#ifdef CONFIG_IWLWIFI_DEBUGFS +- /* use debugfs filters/macs if override is configured */ +- if (mvm->dbgfs_bcast_filtering.override) { +- memcpy(cmd->filters, &mvm->dbgfs_bcast_filtering.cmd.filters, +- sizeof(cmd->filters)); +- memcpy(cmd->macs, &mvm->dbgfs_bcast_filtering.cmd.macs, +- sizeof(cmd->macs)); +- return true; +- } +-#endif +- +- /* if no filters are configured, do nothing */ +- if (!mvm->bcast_filters) +- return false; +- +- /* configure and attach these filters for each associated sta vif */ +- ieee80211_iterate_active_interfaces( +- mvm->hw, IEEE80211_IFACE_ITER_NORMAL, +- iwl_mvm_bcast_filter_iterator, &iter_data); +- +- return true; +-} +- +-static int iwl_mvm_configure_bcast_filter(struct iwl_mvm *mvm) +-{ +- struct iwl_bcast_filter_cmd cmd; +- +- if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BCAST_FILTERING)) +- return 0; +- +- if (!iwl_mvm_bcast_filter_build_cmd(mvm, &cmd)) +- return 0; +- +- return iwl_mvm_send_cmd_pdu(mvm, BCAST_FILTER_CMD, 0, +- sizeof(cmd), &cmd); +-} +-#else +-static inline int iwl_mvm_configure_bcast_filter(struct iwl_mvm *mvm) +-{ +- return 0; +-} +-#endif +- + static int iwl_mvm_update_mu_groups(struct iwl_mvm *mvm, + struct ieee80211_vif *vif) + { +@@ -2469,7 +2235,6 @@ static void iwl_mvm_bss_info_changed_sta + } + + iwl_mvm_recalc_multicast(mvm); +- iwl_mvm_configure_bcast_filter(mvm); + + /* reset rssi values */ + mvmvif->bf_data.ave_beacon_signal = 0; +@@ -2519,11 +2284,6 @@ static void iwl_mvm_bss_info_changed_sta + } + } + +- if (changes & BSS_CHANGED_ARP_FILTER) { +- IWL_DEBUG_MAC80211(mvm, "arp filter changed\n"); +- iwl_mvm_configure_bcast_filter(mvm); +- } +- + if (changes & BSS_CHANGED_BANDWIDTH) + iwl_mvm_apply_fw_smps_request(vif); + } +--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +@@ -872,17 +872,6 @@ struct iwl_mvm { + /* rx chain antennas set through debugfs for the scan command */ + u8 scan_rx_ant; + +-#ifdef CONFIG_IWLWIFI_BCAST_FILTERING +- /* broadcast filters to configure for each associated station */ +- const struct iwl_fw_bcast_filter *bcast_filters; +-#ifdef CONFIG_IWLWIFI_DEBUGFS +- struct { +- bool override; +- struct iwl_bcast_filter_cmd cmd; +- } dbgfs_bcast_filtering; +-#endif +-#endif +- + /* Internal station */ + struct iwl_mvm_int_sta aux_sta; + struct iwl_mvm_int_sta snif_sta; +@@ -1570,8 +1559,6 @@ int iwl_mvm_up(struct iwl_mvm *mvm); + int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm); + + int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm); +-bool iwl_mvm_bcast_filter_build_cmd(struct iwl_mvm *mvm, +- struct iwl_bcast_filter_cmd *cmd); + + /* + * FW notifications / CMD responses handlers +--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +@@ -474,7 +474,6 @@ static const struct iwl_hcmd_names iwl_m + HCMD_NAME(MCC_CHUB_UPDATE_CMD), + HCMD_NAME(MARKER_CMD), + HCMD_NAME(BT_PROFILE_NOTIFICATION), +- HCMD_NAME(BCAST_FILTER_CMD), + HCMD_NAME(MCAST_FILTER_CMD), + HCMD_NAME(REPLY_SF_CFG_CMD), + HCMD_NAME(REPLY_BEACON_FILTERING_CMD), diff --git a/queue-5.16/kvm-x86-nsvm-fix-potential-null-derefernce-on-nested-migration.patch b/queue-5.16/kvm-x86-nsvm-fix-potential-null-derefernce-on-nested-migration.patch new file mode 100644 index 00000000000..7d5e6a8c0aa --- /dev/null +++ b/queue-5.16/kvm-x86-nsvm-fix-potential-null-derefernce-on-nested-migration.patch @@ -0,0 +1,72 @@ +From e1779c2714c3023e4629825762bcbc43a3b943df Mon Sep 17 00:00:00 2001 +From: Maxim Levitsky +Date: Mon, 7 Feb 2022 17:54:19 +0200 +Subject: KVM: x86: nSVM: fix potential NULL derefernce on nested migration + +From: Maxim Levitsky + +commit e1779c2714c3023e4629825762bcbc43a3b943df upstream. + +Turns out that due to review feedback and/or rebases +I accidentally moved the call to nested_svm_load_cr3 to be too early, +before the NPT is enabled, which is very wrong to do. + +KVM can't even access guest memory at that point as nested NPT +is needed for that, and of course it won't initialize the walk_mmu, +which is main issue the patch was addressing. + +Fix this for real. + +Fixes: 232f75d3b4b5 ("KVM: nSVM: call nested_svm_load_cr3 on nested state load") +Cc: stable@vger.kernel.org + +Signed-off-by: Maxim Levitsky +Message-Id: <20220207155447.840194-3-mlevitsk@redhat.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/svm/nested.c | 26 ++++++++++++++------------ + 1 file changed, 14 insertions(+), 12 deletions(-) + +--- a/arch/x86/kvm/svm/nested.c ++++ b/arch/x86/kvm/svm/nested.c +@@ -1389,18 +1389,6 @@ static int svm_set_nested_state(struct k + !nested_vmcb_valid_sregs(vcpu, save)) + goto out_free; + +- /* +- * While the nested guest CR3 is already checked and set by +- * KVM_SET_SREGS, it was set when nested state was yet loaded, +- * thus MMU might not be initialized correctly. +- * Set it again to fix this. +- */ +- +- ret = nested_svm_load_cr3(&svm->vcpu, vcpu->arch.cr3, +- nested_npt_enabled(svm), false); +- if (WARN_ON_ONCE(ret)) +- goto out_free; +- + + /* + * All checks done, we can enter guest mode. Userspace provides +@@ -1426,6 +1414,20 @@ static int svm_set_nested_state(struct k + + svm_switch_vmcb(svm, &svm->nested.vmcb02); + nested_vmcb02_prepare_control(svm); ++ ++ /* ++ * While the nested guest CR3 is already checked and set by ++ * KVM_SET_SREGS, it was set when nested state was yet loaded, ++ * thus MMU might not be initialized correctly. ++ * Set it again to fix this. ++ */ ++ ++ ret = nested_svm_load_cr3(&svm->vcpu, vcpu->arch.cr3, ++ nested_npt_enabled(svm), false); ++ if (WARN_ON_ONCE(ret)) ++ goto out_free; ++ ++ + kvm_make_request(KVM_REQ_GET_NESTED_STATE_PAGES, vcpu); + ret = 0; + out_free: diff --git a/queue-5.16/kvm-x86-nsvm-mark-vmcb01-as-dirty-when-restoring-smm-saved-state.patch b/queue-5.16/kvm-x86-nsvm-mark-vmcb01-as-dirty-when-restoring-smm-saved-state.patch new file mode 100644 index 00000000000..760531b0c54 --- /dev/null +++ b/queue-5.16/kvm-x86-nsvm-mark-vmcb01-as-dirty-when-restoring-smm-saved-state.patch @@ -0,0 +1,49 @@ +From e8efa4ff00374d2e6f47f6e4628ca3b541c001af Mon Sep 17 00:00:00 2001 +From: Maxim Levitsky +Date: Mon, 7 Feb 2022 17:54:20 +0200 +Subject: KVM: x86: nSVM: mark vmcb01 as dirty when restoring SMM saved state + +From: Maxim Levitsky + +commit e8efa4ff00374d2e6f47f6e4628ca3b541c001af upstream. + +While usually, restoring the smm state makes the KVM enter +the nested guest thus a different vmcb (vmcb02 vs vmcb01), +KVM should still mark it as dirty, since hardware +can in theory cache multiple vmcbs. + +Failure to do so, combined with lack of setting the +nested_run_pending (which is fixed in the next patch), +might make KVM re-enter vmcb01, which was just exited from, +with completely different set of guest state registers +(SMM vs non SMM) and without proper dirty bits set, +which results in the CPU reusing stale IDTR pointer +which leads to a guest shutdown on any interrupt. + +On the real hardware this usually doesn't happen, +but when running nested, L0's KVM does check and +honour few dirty bits, causing this issue to happen. + +This patch fixes boot of hyperv and SMM enabled +windows VM running nested on KVM. + +Signed-off-by: Maxim Levitsky +Cc: stable@vger.kernel.org +Message-Id: <20220207155447.840194-4-mlevitsk@redhat.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/svm/svm.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/x86/kvm/svm/svm.c ++++ b/arch/x86/kvm/svm/svm.c +@@ -4449,6 +4449,8 @@ static int svm_leave_smm(struct kvm_vcpu + * Enter the nested guest now + */ + ++ vmcb_mark_all_dirty(svm->vmcb01.ptr); ++ + vmcb12 = map.hva; + nested_load_control_from_vmcb12(svm, &vmcb12->control); + ret = enter_svm_guest_mode(vcpu, vmcb12_gpa, vmcb12, false); diff --git a/queue-5.16/kvm-x86-nsvm-nvmx-set-nested_run_pending-on-vm-entry-which-is-a-result-of-rsm.patch b/queue-5.16/kvm-x86-nsvm-nvmx-set-nested_run_pending-on-vm-entry-which-is-a-result-of-rsm.patch new file mode 100644 index 00000000000..4bd1237baea --- /dev/null +++ b/queue-5.16/kvm-x86-nsvm-nvmx-set-nested_run_pending-on-vm-entry-which-is-a-result-of-rsm.patch @@ -0,0 +1,51 @@ +From 759cbd59674a6c0aec616a3f4f0740ebd3f5fbef Mon Sep 17 00:00:00 2001 +From: Maxim Levitsky +Date: Mon, 7 Feb 2022 17:54:21 +0200 +Subject: KVM: x86: nSVM/nVMX: set nested_run_pending on VM entry which is a result of RSM + +From: Maxim Levitsky + +commit 759cbd59674a6c0aec616a3f4f0740ebd3f5fbef upstream. + +While RSM induced VM entries are not full VM entries, +they still need to be followed by actual VM entry to complete it, +unlike setting the nested state. + +This patch fixes boot of hyperv and SMM enabled +windows VM running nested on KVM, which fail due +to this issue combined with lack of dirty bit setting. + +Signed-off-by: Maxim Levitsky +Cc: stable@vger.kernel.org +Message-Id: <20220207155447.840194-5-mlevitsk@redhat.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/svm/svm.c | 5 +++++ + arch/x86/kvm/vmx/vmx.c | 1 + + 2 files changed, 6 insertions(+) + +--- a/arch/x86/kvm/svm/svm.c ++++ b/arch/x86/kvm/svm/svm.c +@@ -4445,6 +4445,11 @@ static int svm_leave_smm(struct kvm_vcpu + nested_load_control_from_vmcb12(svm, &vmcb12->control); + ret = enter_svm_guest_mode(vcpu, vmcb12_gpa, vmcb12, false); + ++ if (ret) ++ goto unmap_save; ++ ++ svm->nested.nested_run_pending = 1; ++ + unmap_save: + kvm_vcpu_unmap(vcpu, &map_save, true); + unmap_map: +--- a/arch/x86/kvm/vmx/vmx.c ++++ b/arch/x86/kvm/vmx/vmx.c +@@ -7534,6 +7534,7 @@ static int vmx_leave_smm(struct kvm_vcpu + if (ret) + return ret; + ++ vmx->nested.nested_run_pending = 1; + vmx->nested.smm.guest_mode = false; + } + return 0; diff --git a/queue-5.16/kvm-x86-svm-don-t-passthrough-smap-smep-pke-bits-in-npt-gcr0.pg-case.patch b/queue-5.16/kvm-x86-svm-don-t-passthrough-smap-smep-pke-bits-in-npt-gcr0.pg-case.patch new file mode 100644 index 00000000000..191b129234c --- /dev/null +++ b/queue-5.16/kvm-x86-svm-don-t-passthrough-smap-smep-pke-bits-in-npt-gcr0.pg-case.patch @@ -0,0 +1,78 @@ +From c53bbe2145f51d3bc0438c2db02e737b9b598bf3 Mon Sep 17 00:00:00 2001 +From: Maxim Levitsky +Date: Mon, 7 Feb 2022 17:54:18 +0200 +Subject: KVM: x86: SVM: don't passthrough SMAP/SMEP/PKE bits in !NPT && !gCR0.PG case + +From: Maxim Levitsky + +commit c53bbe2145f51d3bc0438c2db02e737b9b598bf3 upstream. + +When the guest doesn't enable paging, and NPT/EPT is disabled, we +use guest't paging CR3's as KVM's shadow paging pointer and +we are technically in direct mode as if we were to use NPT/EPT. + +In direct mode we create SPTEs with user mode permissions +because usually in the direct mode the NPT/EPT doesn't +need to restrict access based on guest CPL +(there are MBE/GMET extenstions for that but KVM doesn't use them). + +In this special "use guest paging as direct" mode however, +and if CR4.SMAP/CR4.SMEP are enabled, that will make the CPU +fault on each access and KVM will enter endless loop of page faults. + +Since page protection doesn't have any meaning in !PG case, +just don't passthrough these bits. + +The fix is the same as was done for VMX in commit: +commit 656ec4a4928a ("KVM: VMX: fix SMEP and SMAP without EPT") + +This fixes the boot of windows 10 without NPT for good. +(Without this patch, BSP boots, but APs were stuck in endless +loop of page faults, causing the VM boot with 1 CPU) + +Signed-off-by: Maxim Levitsky +Cc: stable@vger.kernel.org +Message-Id: <20220207155447.840194-2-mlevitsk@redhat.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/svm/svm.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +--- a/arch/x86/kvm/svm/svm.c ++++ b/arch/x86/kvm/svm/svm.c +@@ -1795,6 +1795,7 @@ void svm_set_cr0(struct kvm_vcpu *vcpu, + { + struct vcpu_svm *svm = to_svm(vcpu); + u64 hcr0 = cr0; ++ bool old_paging = is_paging(vcpu); + + #ifdef CONFIG_X86_64 + if (vcpu->arch.efer & EFER_LME && !vcpu->arch.guest_state_protected) { +@@ -1811,8 +1812,11 @@ void svm_set_cr0(struct kvm_vcpu *vcpu, + #endif + vcpu->arch.cr0 = cr0; + +- if (!npt_enabled) ++ if (!npt_enabled) { + hcr0 |= X86_CR0_PG | X86_CR0_WP; ++ if (old_paging != is_paging(vcpu)) ++ svm_set_cr4(vcpu, kvm_read_cr4(vcpu)); ++ } + + /* + * re-enable caching here because the QEMU bios +@@ -1856,8 +1860,12 @@ void svm_set_cr4(struct kvm_vcpu *vcpu, + svm_flush_tlb(vcpu); + + vcpu->arch.cr4 = cr4; +- if (!npt_enabled) ++ if (!npt_enabled) { + cr4 |= X86_CR4_PAE; ++ ++ if (!is_paging(vcpu)) ++ cr4 &= ~(X86_CR4_SMEP | X86_CR4_SMAP | X86_CR4_PKE); ++ } + cr4 |= host_cr4_mce; + to_svm(vcpu)->vmcb->save.cr4 = cr4; + vmcb_mark_dirty(to_svm(vcpu)->vmcb, VMCB_CR); diff --git a/queue-5.16/kvm-x86-xen-fix-runstate-updates-to-be-atomic-when-preempting-vcpu.patch b/queue-5.16/kvm-x86-xen-fix-runstate-updates-to-be-atomic-when-preempting-vcpu.patch new file mode 100644 index 00000000000..c2deb578622 --- /dev/null +++ b/queue-5.16/kvm-x86-xen-fix-runstate-updates-to-be-atomic-when-preempting-vcpu.patch @@ -0,0 +1,214 @@ +From fcb732d8f8cf6084f8480015ad41d25fb023a4dd Mon Sep 17 00:00:00 2001 +From: David Woodhouse +Date: Mon, 25 Oct 2021 14:29:01 +0100 +Subject: KVM: x86/xen: Fix runstate updates to be atomic when preempting vCPU +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: David Woodhouse + +commit fcb732d8f8cf6084f8480015ad41d25fb023a4dd upstream. + +There are circumstances whem kvm_xen_update_runstate_guest() should not +sleep because it ends up being called from __schedule() when the vCPU +is preempted: + +[ 222.830825] kvm_xen_update_runstate_guest+0x24/0x100 +[ 222.830878] kvm_arch_vcpu_put+0x14c/0x200 +[ 222.830920] kvm_sched_out+0x30/0x40 +[ 222.830960] __schedule+0x55c/0x9f0 + +To handle this, make it use the same trick as __kvm_xen_has_interrupt(), +of using the hva from the gfn_to_hva_cache directly. Then it can use +pagefault_disable() around the accesses and just bail out if the page +is absent (which is unlikely). + +I almost switched to using a gfn_to_pfn_cache here and bailing out if +kvm_map_gfn() fails, like kvm_steal_time_set_preempted() does — but on +closer inspection it looks like kvm_map_gfn() will *always* fail in +atomic context for a page in IOMEM, which means it will silently fail +to make the update every single time for such guests, AFAICT. So I +didn't do it that way after all. And will probably fix that one too. + +Cc: stable@vger.kernel.org +Fixes: 30b5c851af79 ("KVM: x86/xen: Add support for vCPU runstate information") +Signed-off-by: David Woodhouse +Message-Id: +Signed-off-by: Paolo Bonzini +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/xen.c | 97 ++++++++++++++++++++++++++++++++++++----------------- + 1 file changed, 67 insertions(+), 30 deletions(-) + +--- a/arch/x86/kvm/xen.c ++++ b/arch/x86/kvm/xen.c +@@ -93,32 +93,57 @@ static void kvm_xen_update_runstate(stru + void kvm_xen_update_runstate_guest(struct kvm_vcpu *v, int state) + { + struct kvm_vcpu_xen *vx = &v->arch.xen; ++ struct gfn_to_hva_cache *ghc = &vx->runstate_cache; ++ struct kvm_memslots *slots = kvm_memslots(v->kvm); ++ bool atomic = (state == RUNSTATE_runnable); + uint64_t state_entry_time; +- unsigned int offset; ++ int __user *user_state; ++ uint64_t __user *user_times; + + kvm_xen_update_runstate(v, state); + + if (!vx->runstate_set) + return; + +- BUILD_BUG_ON(sizeof(struct compat_vcpu_runstate_info) != 0x2c); ++ if (unlikely(slots->generation != ghc->generation || kvm_is_error_hva(ghc->hva)) && ++ kvm_gfn_to_hva_cache_init(v->kvm, ghc, ghc->gpa, ghc->len)) ++ return; ++ ++ /* We made sure it fits in a single page */ ++ BUG_ON(!ghc->memslot); ++ ++ if (atomic) ++ pagefault_disable(); + +- offset = offsetof(struct compat_vcpu_runstate_info, state_entry_time); +-#ifdef CONFIG_X86_64 + /* +- * The only difference is alignment of uint64_t in 32-bit. +- * So the first field 'state' is accessed directly using +- * offsetof() (where its offset happens to be zero), while the +- * remaining fields which are all uint64_t, start at 'offset' +- * which we tweak here by adding 4. ++ * The only difference between 32-bit and 64-bit versions of the ++ * runstate struct us the alignment of uint64_t in 32-bit, which ++ * means that the 64-bit version has an additional 4 bytes of ++ * padding after the first field 'state'. ++ * ++ * So we use 'int __user *user_state' to point to the state field, ++ * and 'uint64_t __user *user_times' for runstate_entry_time. So ++ * the actual array of time[] in each state starts at user_times[1]. + */ ++ BUILD_BUG_ON(offsetof(struct vcpu_runstate_info, state) != 0); ++ BUILD_BUG_ON(offsetof(struct compat_vcpu_runstate_info, state) != 0); ++ user_state = (int __user *)ghc->hva; ++ ++ BUILD_BUG_ON(sizeof(struct compat_vcpu_runstate_info) != 0x2c); ++ ++ user_times = (uint64_t __user *)(ghc->hva + ++ offsetof(struct compat_vcpu_runstate_info, ++ state_entry_time)); ++#ifdef CONFIG_X86_64 + BUILD_BUG_ON(offsetof(struct vcpu_runstate_info, state_entry_time) != + offsetof(struct compat_vcpu_runstate_info, state_entry_time) + 4); + BUILD_BUG_ON(offsetof(struct vcpu_runstate_info, time) != + offsetof(struct compat_vcpu_runstate_info, time) + 4); + + if (v->kvm->arch.xen.long_mode) +- offset = offsetof(struct vcpu_runstate_info, state_entry_time); ++ user_times = (uint64_t __user *)(ghc->hva + ++ offsetof(struct vcpu_runstate_info, ++ state_entry_time)); + #endif + /* + * First write the updated state_entry_time at the appropriate +@@ -132,10 +157,8 @@ void kvm_xen_update_runstate_guest(struc + BUILD_BUG_ON(sizeof_field(struct compat_vcpu_runstate_info, state_entry_time) != + sizeof(state_entry_time)); + +- if (kvm_write_guest_offset_cached(v->kvm, &v->arch.xen.runstate_cache, +- &state_entry_time, offset, +- sizeof(state_entry_time))) +- return; ++ if (__put_user(state_entry_time, user_times)) ++ goto out; + smp_wmb(); + + /* +@@ -149,11 +172,8 @@ void kvm_xen_update_runstate_guest(struc + BUILD_BUG_ON(sizeof_field(struct compat_vcpu_runstate_info, state) != + sizeof(vx->current_runstate)); + +- if (kvm_write_guest_offset_cached(v->kvm, &v->arch.xen.runstate_cache, +- &vx->current_runstate, +- offsetof(struct vcpu_runstate_info, state), +- sizeof(vx->current_runstate))) +- return; ++ if (__put_user(vx->current_runstate, user_state)) ++ goto out; + + /* + * Write the actual runstate times immediately after the +@@ -168,24 +188,23 @@ void kvm_xen_update_runstate_guest(struc + BUILD_BUG_ON(sizeof_field(struct vcpu_runstate_info, time) != + sizeof(vx->runstate_times)); + +- if (kvm_write_guest_offset_cached(v->kvm, &v->arch.xen.runstate_cache, +- &vx->runstate_times[0], +- offset + sizeof(u64), +- sizeof(vx->runstate_times))) +- return; +- ++ if (__copy_to_user(user_times + 1, vx->runstate_times, sizeof(vx->runstate_times))) ++ goto out; + smp_wmb(); + + /* + * Finally, clear the XEN_RUNSTATE_UPDATE bit in the guest's + * runstate_entry_time field. + */ +- + state_entry_time &= ~XEN_RUNSTATE_UPDATE; +- if (kvm_write_guest_offset_cached(v->kvm, &v->arch.xen.runstate_cache, +- &state_entry_time, offset, +- sizeof(state_entry_time))) +- return; ++ __put_user(state_entry_time, user_times); ++ smp_wmb(); ++ ++ out: ++ mark_page_dirty_in_slot(v->kvm, ghc->memslot, ghc->gpa >> PAGE_SHIFT); ++ ++ if (atomic) ++ pagefault_enable(); + } + + int __kvm_xen_has_interrupt(struct kvm_vcpu *v) +@@ -337,6 +356,12 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcp + break; + } + ++ /* It must fit within a single page */ ++ if ((data->u.gpa & ~PAGE_MASK) + sizeof(struct vcpu_info) > PAGE_SIZE) { ++ r = -EINVAL; ++ break; ++ } ++ + r = kvm_gfn_to_hva_cache_init(vcpu->kvm, + &vcpu->arch.xen.vcpu_info_cache, + data->u.gpa, +@@ -354,6 +379,12 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcp + break; + } + ++ /* It must fit within a single page */ ++ if ((data->u.gpa & ~PAGE_MASK) + sizeof(struct pvclock_vcpu_time_info) > PAGE_SIZE) { ++ r = -EINVAL; ++ break; ++ } ++ + r = kvm_gfn_to_hva_cache_init(vcpu->kvm, + &vcpu->arch.xen.vcpu_time_info_cache, + data->u.gpa, +@@ -375,6 +406,12 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcp + break; + } + ++ /* It must fit within a single page */ ++ if ((data->u.gpa & ~PAGE_MASK) + sizeof(struct vcpu_runstate_info) > PAGE_SIZE) { ++ r = -EINVAL; ++ break; ++ } ++ + r = kvm_gfn_to_hva_cache_init(vcpu->kvm, + &vcpu->arch.xen.runstate_cache, + data->u.gpa, diff --git a/queue-5.16/series b/queue-5.16/series index 14abcb06b3a..157879a6e2f 100644 --- a/queue-5.16/series +++ b/queue-5.16/series @@ -68,3 +68,18 @@ x86-xen-streamline-and-fix-pv-cpu-enumeration.patch revert-module-async-async_synchronize_full-on-module.patch gcc-plugins-stackleak-use-noinstr-in-favor-of-notrac.patch random-wake-up-dev-random-writers-after-zap.patch +kvm-x86-xen-fix-runstate-updates-to-be-atomic-when-preempting-vcpu.patch +kvm-x86-nsvm-nvmx-set-nested_run_pending-on-vm-entry-which-is-a-result-of-rsm.patch +kvm-x86-svm-don-t-passthrough-smap-smep-pke-bits-in-npt-gcr0.pg-case.patch +kvm-x86-nsvm-fix-potential-null-derefernce-on-nested-migration.patch +kvm-x86-nsvm-mark-vmcb01-as-dirty-when-restoring-smm-saved-state.patch +iwlwifi-remove-deprecated-broadcast-filtering-feature.patch +iwlwifi-fix-use-after-free.patch +drm-mediatek-mtk_dsi-avoid-eprobe_defer-loop-with-external-bridge.patch +drm-radeon-fix-backlight-control-on-imac-12-1.patch +drm-atomic-don-t-pollute-crtc_state-mode_blob-with-error-pointers.patch +drm-amd-pm-correct-the-sequence-of-sending-gpu-reset-msg.patch +drm-amdgpu-skipping-sdma-hw_init-and-hw_fini-for-s0ix.patch +drm-i915-opregion-check-port-number-bounds-for-swsci-display-power-state.patch +drm-i915-fix-dbuf-slice-config-lookup.patch +drm-i915-fix-mbus-join-config-lookup.patch -- 2.47.3