]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.16-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 18 Feb 2022 09:18:16 +0000 (10:18 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 18 Feb 2022 09:18:16 +0000 (10:18 +0100)
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

16 files changed:
queue-5.16/drm-amd-pm-correct-the-sequence-of-sending-gpu-reset-msg.patch [new file with mode: 0644]
queue-5.16/drm-amdgpu-skipping-sdma-hw_init-and-hw_fini-for-s0ix.patch [new file with mode: 0644]
queue-5.16/drm-atomic-don-t-pollute-crtc_state-mode_blob-with-error-pointers.patch [new file with mode: 0644]
queue-5.16/drm-i915-fix-dbuf-slice-config-lookup.patch [new file with mode: 0644]
queue-5.16/drm-i915-fix-mbus-join-config-lookup.patch [new file with mode: 0644]
queue-5.16/drm-i915-opregion-check-port-number-bounds-for-swsci-display-power-state.patch [new file with mode: 0644]
queue-5.16/drm-mediatek-mtk_dsi-avoid-eprobe_defer-loop-with-external-bridge.patch [new file with mode: 0644]
queue-5.16/drm-radeon-fix-backlight-control-on-imac-12-1.patch [new file with mode: 0644]
queue-5.16/iwlwifi-fix-use-after-free.patch [new file with mode: 0644]
queue-5.16/iwlwifi-remove-deprecated-broadcast-filtering-feature.patch [new file with mode: 0644]
queue-5.16/kvm-x86-nsvm-fix-potential-null-derefernce-on-nested-migration.patch [new file with mode: 0644]
queue-5.16/kvm-x86-nsvm-mark-vmcb01-as-dirty-when-restoring-smm-saved-state.patch [new file with mode: 0644]
queue-5.16/kvm-x86-nsvm-nvmx-set-nested_run_pending-on-vm-entry-which-is-a-result-of-rsm.patch [new file with mode: 0644]
queue-5.16/kvm-x86-svm-don-t-passthrough-smap-smep-pke-bits-in-npt-gcr0.pg-case.patch [new file with mode: 0644]
queue-5.16/kvm-x86-xen-fix-runstate-updates-to-be-atomic-when-preempting-vcpu.patch [new file with mode: 0644]
queue-5.16/series

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 (file)
index 0000000..fac7ff1
--- /dev/null
@@ -0,0 +1,41 @@
+From 9c4f59ea3f865693150edf0c91d1cc6b451360dd Mon Sep 17 00:00:00 2001
+From: Yifan Zhang <yifan1.zhang@amd.com>
+Date: Fri, 11 Feb 2022 17:58:08 +0800
+Subject: drm/amd/pm: correct the sequence of sending gpu reset msg
+
+From: Yifan Zhang <yifan1.zhang@amd.com>
+
+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 <yifan1.zhang@amd.com>
+Acked-by: Aaron Liu <aaron.liu@amd.com>
+Reviewed-by: Huang Rui <ray.huang@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..6754683
--- /dev/null
@@ -0,0 +1,55 @@
+From f8f4e2a518347063179def4e64580b2d28233d03 Mon Sep 17 00:00:00 2001
+From: Rajib Mahapatra <rajib.mahapatra@amd.com>
+Date: Thu, 10 Feb 2022 18:46:40 +0530
+Subject: drm/amdgpu: skipping SDMA hw_init and hw_fini for S0ix.
+
+From: Rajib Mahapatra <rajib.mahapatra@amd.com>
+
+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 <mario.limonciello@amd.com>
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Rajib Mahapatra <rajib.mahapatra@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..19b190c
--- /dev/null
@@ -0,0 +1,52 @@
+From 439cf34c8e0a8a33d8c15a31be1b7423426bc765 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com>
+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ä <ville.syrjala@linux.intel.com>
+
+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 <fuyufan@huawei.com>
+Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20220209091928.14766-1-ville.syrjala@linux.intel.com
+Acked-by: Maxime Ripard <maxime@cerno.tech>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..7654d27
--- /dev/null
@@ -0,0 +1,46 @@
+From 698bef8ff5d2edea5d1c9d6e5adf1bfed1e8a106 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com>
+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ä <ville.syrjala@linux.intel.com>
+
+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ä <ville.syrjala@linux.intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20220207132700.481-1-ville.syrjala@linux.intel.com
+Reviewed-by: Jani Nikula <jani.nikula@intel.com>
+(cherry picked from commit a28fde308c3c1c174249ff9559b57f24e6850086)
+Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..d18b1d8
--- /dev/null
@@ -0,0 +1,39 @@
+From 8d9d2a723d64b650f2e6423024ccb4a33f0cdc40 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com>
+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ä <ville.syrjala@linux.intel.com>
+
+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ä <ville.syrjala@linux.intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20220207132700.481-2-ville.syrjala@linux.intel.com
+Reviewed-by: Jani Nikula <jani.nikula@intel.com>
+(cherry picked from commit 053f2b85631316a9226f6340c1c0fd95634f7a5b)
+Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..583f8b1
--- /dev/null
@@ -0,0 +1,62 @@
+From ea958422291de248b9e2eaaeea36004e84b64043 Mon Sep 17 00:00:00 2001
+From: Jani Nikula <jani.nikula@intel.com>
+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 <jani.nikula@intel.com>
+
+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: <stable@vger.kernel.org> # v3.13+
+Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
+Cc: Lucas De Marchi <lucas.demarchi@intel.com>
+Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/4800
+Signed-off-by: Jani Nikula <jani.nikula@intel.com>
+Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/cc363f42d6b5a5932b6d218fefcc8bdfb15dbbe5.1644489329.git.jani.nikula@intel.com
+(cherry picked from commit 24a644ebbfd3b13cda702f98907f9dd123e34bf9)
+Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..84577be
--- /dev/null
@@ -0,0 +1,263 @@
+From 647474b8d980256b26b1cd112d7333a4dbd4260a Mon Sep 17 00:00:00 2001
+From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+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 <angelogioacchino.delregno@collabora.com>
+
+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: <stable@vger.kernel.org> # 5.15.x
+Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Reviewed-by: Andrzej Hajda <andrzej.hajda@intel.com>
+Reviewed-by: Jagan Teki <jagan@amarulasolutions.com>
+Tested-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
+Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..dcf1748
--- /dev/null
@@ -0,0 +1,33 @@
+From 364438fd629f7611a84c8e6d7de91659300f1502 Mon Sep 17 00:00:00 2001
+From: Nicholas Bishop <nicholasbishop@google.com>
+Date: Fri, 11 Feb 2022 14:57:39 -0500
+Subject: drm/radeon: Fix backlight control on iMac 12,1
+
+From: Nicholas Bishop <nicholasbishop@google.com>
+
+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 <nicholasbishop@google.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..2cd3e14
--- /dev/null
@@ -0,0 +1,48 @@
+From bea2662e7818e15d7607d17d57912ac984275d94 Mon Sep 17 00:00:00 2001
+From: Johannes Berg <johannes.berg@intel.com>
+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 <johannes.berg@intel.com>
+
+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 <stefan@agner.ch>
+Reported-by: Wolfgang Walter <linux@stwm.de>
+Reported-by: Jason Self <jason@bluehome.net>
+Reported-by: Dominik Behr <dominik@dominikbehr.com>
+Reported-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
+Fixes: ab07506b0454 ("iwlwifi: fix leaks/bad data after failed firmware load")
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Kalle Valo <kvalo@kernel.org>
+Link: https://lore.kernel.org/r/20220208114728.e6b514cf4c85.Iffb575ca2a623d7859b542c33b2a507d01554251@changeid
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..4529e88
--- /dev/null
@@ -0,0 +1,728 @@
+From 92883a524ae918736a7b8acef98698075507b8c1 Mon Sep 17 00:00:00 2001
+From: Luca Coelho <luciano.coelho@intel.com>
+Date: Fri, 28 Jan 2022 14:48:50 +0200
+Subject: iwlwifi: remove deprecated broadcast filtering feature
+
+From: Luca Coelho <luciano.coelho@intel.com>
+
+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 <luciano.coelho@intel.com>
+Signed-off-by: Kalle Valo <kvalo@kernel.org>
+Link: https://lore.kernel.org/r/iwlwifi.20220128144623.9241e049f13e.Ia4f282813ca2ddd24c13427823519113f2bbebf2@changeid
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..7d5e6a8
--- /dev/null
@@ -0,0 +1,72 @@
+From e1779c2714c3023e4629825762bcbc43a3b943df Mon Sep 17 00:00:00 2001
+From: Maxim Levitsky <mlevitsk@redhat.com>
+Date: Mon, 7 Feb 2022 17:54:19 +0200
+Subject: KVM: x86: nSVM: fix potential NULL derefernce on nested migration
+
+From: Maxim Levitsky <mlevitsk@redhat.com>
+
+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 <mlevitsk@redhat.com>
+Message-Id: <20220207155447.840194-3-mlevitsk@redhat.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..760531b
--- /dev/null
@@ -0,0 +1,49 @@
+From e8efa4ff00374d2e6f47f6e4628ca3b541c001af Mon Sep 17 00:00:00 2001
+From: Maxim Levitsky <mlevitsk@redhat.com>
+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 <mlevitsk@redhat.com>
+
+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 <mlevitsk@redhat.com>
+Cc: stable@vger.kernel.org
+Message-Id: <20220207155447.840194-4-mlevitsk@redhat.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..4bd1237
--- /dev/null
@@ -0,0 +1,51 @@
+From 759cbd59674a6c0aec616a3f4f0740ebd3f5fbef Mon Sep 17 00:00:00 2001
+From: Maxim Levitsky <mlevitsk@redhat.com>
+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 <mlevitsk@redhat.com>
+
+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 <mlevitsk@redhat.com>
+Cc: stable@vger.kernel.org
+Message-Id: <20220207155447.840194-5-mlevitsk@redhat.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..191b129
--- /dev/null
@@ -0,0 +1,78 @@
+From c53bbe2145f51d3bc0438c2db02e737b9b598bf3 Mon Sep 17 00:00:00 2001
+From: Maxim Levitsky <mlevitsk@redhat.com>
+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 <mlevitsk@redhat.com>
+
+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 <mlevitsk@redhat.com>
+Cc: stable@vger.kernel.org
+Message-Id: <20220207155447.840194-2-mlevitsk@redhat.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..c2deb57
--- /dev/null
@@ -0,0 +1,214 @@
+From fcb732d8f8cf6084f8480015ad41d25fb023a4dd Mon Sep 17 00:00:00 2001
+From: David Woodhouse <dwmw@amazon.co.uk>
+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 <dwmw@amazon.co.uk>
+
+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 <dwmw@amazon.co.uk>
+Message-Id: <b17a93e5ff4561e57b1238e3e7ccd0b613eb827e.camel@infradead.org>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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,
index 14abcb06b3ad3c034177163709c96185fb582299..157879a6e2f755b6a79f96fbce59fe2c95133ee6 100644 (file)
@@ -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