]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.15
authorSasha Levin <sashal@kernel.org>
Mon, 25 Jul 2022 18:15:15 +0000 (14:15 -0400)
committerSasha Levin <sashal@kernel.org>
Mon, 25 Jul 2022 18:15:15 +0000 (14:15 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
39 files changed:
queue-5.15/bitfield.h-fix-type-of-reg-too-small-for-mask-test.patch [new file with mode: 0644]
queue-5.15/crypto-qat-add-backlog-mechanism.patch [new file with mode: 0644]
queue-5.15/crypto-qat-add-param-check-for-dh.patch [new file with mode: 0644]
queue-5.15/crypto-qat-add-param-check-for-rsa.patch [new file with mode: 0644]
queue-5.15/crypto-qat-fix-memory-leak-in-rsa.patch [new file with mode: 0644]
queue-5.15/crypto-qat-re-enable-registration-of-algorithms.patch [new file with mode: 0644]
queue-5.15/crypto-qat-refactor-submission-logic.patch [new file with mode: 0644]
queue-5.15/crypto-qat-remove-dma_free_coherent-for-dh.patch [new file with mode: 0644]
queue-5.15/crypto-qat-remove-dma_free_coherent-for-rsa.patch [new file with mode: 0644]
queue-5.15/crypto-qat-set-to-zero-dh-parameters-before-free.patch [new file with mode: 0644]
queue-5.15/crypto-qat-use-pre-allocated-buffers-in-datapath.patch [new file with mode: 0644]
queue-5.15/dlm-fix-pending-remove-if-msg-allocation-fails.patch [new file with mode: 0644]
queue-5.15/exfat-fix-referencing-wrong-parent-directory-informa.patch [new file with mode: 0644]
queue-5.15/iwlwifi-fw-uefi-add-missing-include-guards.patch [new file with mode: 0644]
queue-5.15/kvm-x86-use-__try_cmpxchg_user-to-emulate-atomic-acc.patch [new file with mode: 0644]
queue-5.15/mt76-fix-use-after-free-by-removing-a-non-rcu-wcid-p.patch [new file with mode: 0644]
queue-5.15/series
queue-5.15/tracing-fix-return-value-of-trace_pid_write.patch [new file with mode: 0644]
queue-5.15/tracing-have-event-format-check-not-flag-p-on-__get_.patch [new file with mode: 0644]
queue-5.15/tracing-place-trace_pid_list-logic-into-abstract-fun.patch [new file with mode: 0644]
queue-5.15/um-virtio_uml-allow-probing-from-devicetree.patch [new file with mode: 0644]
queue-5.15/um-virtio_uml-fix-broken-device-handling-in-time-tra.patch [new file with mode: 0644]
queue-5.15/x86-entry_32-remove-.fixup-usage.patch [new file with mode: 0644]
queue-5.15/x86-extable-extend-extable-functionality.patch [new file with mode: 0644]
queue-5.15/x86-extable-get-rid-of-redundant-macros.patch [new file with mode: 0644]
queue-5.15/x86-extable-provide-ex_type_default_mce_safe-and-ex_.patch [new file with mode: 0644]
queue-5.15/x86-extable-provide-ex_type_default_mce_safe-and-ex_.patch-2687 [new file with mode: 0644]
queue-5.15/x86-extable-rework-the-exception-table-mechanics.patch [new file with mode: 0644]
queue-5.15/x86-extable-tidy-up-redundant-handler-functions.patch [new file with mode: 0644]
queue-5.15/x86-futex-remove-.fixup-usage.patch [new file with mode: 0644]
queue-5.15/x86-mce-deduplicate-exception-handling.patch [new file with mode: 0644]
queue-5.15/x86-msr-remove-.fixup-usage.patch [new file with mode: 0644]
queue-5.15/x86-uaccess-implement-macros-for-cmpxchg-on-user-add.patch [new file with mode: 0644]
queue-5.15/x86-uaccess-implement-macros-for-cmpxchg-on-user-add.patch-12415 [new file with mode: 0644]
queue-5.15/x86-uaccess-implement-macros-for-cmpxchg-on-user-add.patch-32473 [new file with mode: 0644]
queue-5.15/xhci-dbc-create-and-remove-dbc-structure-in-dbgtty-d.patch [new file with mode: 0644]
queue-5.15/xhci-dbc-refactor-xhci_dbc_init.patch [new file with mode: 0644]
queue-5.15/xhci-dbc-rename-xhci_dbc_init-and-xhci_dbc_exit.patch [new file with mode: 0644]
queue-5.15/xhci-set-hcd-flag-to-defer-primary-roothub-registrat.patch [new file with mode: 0644]

diff --git a/queue-5.15/bitfield.h-fix-type-of-reg-too-small-for-mask-test.patch b/queue-5.15/bitfield.h-fix-type-of-reg-too-small-for-mask-test.patch
new file mode 100644 (file)
index 0000000..390214d
--- /dev/null
@@ -0,0 +1,63 @@
+From fdc08170907d754143e9a13298cc48ac7011b099 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 10 Nov 2021 11:01:03 +0100
+Subject: bitfield.h: Fix "type of reg too small for mask" test
+
+From: Peter Zijlstra <peterz@infradead.org>
+
+[ Upstream commit bff8c3848e071d387d8b0784dc91fa49cd563774 ]
+
+The test: 'mask > (typeof(_reg))~0ull' only works correctly when both
+sides are unsigned, consider:
+
+ - 0xff000000 vs (int)~0ull
+ - 0x000000ff vs (int)~0ull
+
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Reviewed-by: Josh Poimboeuf <jpoimboe@redhat.com>
+Link: https://lore.kernel.org/r/20211110101324.950210584@infradead.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/bitfield.h | 19 ++++++++++++++++++-
+ 1 file changed, 18 insertions(+), 1 deletion(-)
+
+diff --git a/include/linux/bitfield.h b/include/linux/bitfield.h
+index 4e035aca6f7e..6093fa6db260 100644
+--- a/include/linux/bitfield.h
++++ b/include/linux/bitfield.h
+@@ -41,6 +41,22 @@
+ #define __bf_shf(x) (__builtin_ffsll(x) - 1)
++#define __scalar_type_to_unsigned_cases(type)                         \
++              unsigned type:  (unsigned type)0,                       \
++              signed type:    (unsigned type)0
++
++#define __unsigned_scalar_typeof(x) typeof(                           \
++              _Generic((x),                                           \
++                      char:   (unsigned char)0,                       \
++                      __scalar_type_to_unsigned_cases(char),          \
++                      __scalar_type_to_unsigned_cases(short),         \
++                      __scalar_type_to_unsigned_cases(int),           \
++                      __scalar_type_to_unsigned_cases(long),          \
++                      __scalar_type_to_unsigned_cases(long long),     \
++                      default: (x)))
++
++#define __bf_cast_unsigned(type, x)   ((__unsigned_scalar_typeof(type))(x))
++
+ #define __BF_FIELD_CHECK(_mask, _reg, _val, _pfx)                     \
+       ({                                                              \
+               BUILD_BUG_ON_MSG(!__builtin_constant_p(_mask),          \
+@@ -49,7 +65,8 @@
+               BUILD_BUG_ON_MSG(__builtin_constant_p(_val) ?           \
+                                ~((_mask) >> __bf_shf(_mask)) & (_val) : 0, \
+                                _pfx "value too large for the field"); \
+-              BUILD_BUG_ON_MSG((_mask) > (typeof(_reg))~0ull,         \
++              BUILD_BUG_ON_MSG(__bf_cast_unsigned(_mask, _mask) >     \
++                               __bf_cast_unsigned(_reg, ~0ull),       \
+                                _pfx "type of reg too small for mask"); \
+               __BUILD_BUG_ON_NOT_POWER_OF_2((_mask) +                 \
+                                             (1ULL << __bf_shf(_mask))); \
+-- 
+2.35.1
+
diff --git a/queue-5.15/crypto-qat-add-backlog-mechanism.patch b/queue-5.15/crypto-qat-add-backlog-mechanism.patch
new file mode 100644 (file)
index 0000000..2fed5be
--- /dev/null
@@ -0,0 +1,408 @@
+From 7b81debcf9ab48cfe42bec0eec20b5fd081e222a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 May 2022 14:34:10 +0100
+Subject: crypto: qat - add backlog mechanism
+
+From: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+
+[ Upstream commit 38682383973280e5be2802ba8a8d4a636d36cb19 ]
+
+The implementations of the crypto algorithms (aead, skcipher, etc) in
+the QAT driver do not properly support requests with the
+CRYPTO_TFM_REQ_MAY_BACKLOG flag set. If the HW queue is full, the driver
+returns -EBUSY but does not enqueue the request. This can result in
+applications like dm-crypt waiting indefinitely for the completion of a
+request that was never submitted to the hardware.
+
+Fix this by adding a software backlog queue: if the ring buffer is more
+than eighty percent full, then the request is enqueued to a backlog
+list and the error code -EBUSY is returned back to the caller.
+Requests in the backlog queue are resubmitted at a later time, in the
+context of the callback of a previously submitted request.
+The request for which -EBUSY is returned is then marked as -EINPROGRESS
+once submitted to the HW queues.
+
+The submission loop inside the function qat_alg_send_message() has been
+modified to decide which submission policy to use based on the request
+flags. If the request does not have the CRYPTO_TFM_REQ_MAY_BACKLOG set,
+the previous behaviour has been preserved.
+
+Based on a patch by
+Vishnu Das Ramachandran <vishnu.dasx.ramachandran@intel.com>
+
+Cc: stable@vger.kernel.org
+Fixes: d370cec32194 ("crypto: qat - Intel(R) QAT crypto interface")
+Reported-by: Mikulas Patocka <mpatocka@redhat.com>
+Reported-by: Kyle Sanderson <kyle.leet@gmail.com>
+Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+Reviewed-by: Marco Chiappero <marco.chiappero@intel.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/crypto/qat/qat_common/adf_transport.c | 11 +++
+ drivers/crypto/qat/qat_common/adf_transport.h |  1 +
+ .../qat/qat_common/adf_transport_internal.h   |  1 +
+ drivers/crypto/qat/qat_common/qat_algs.c      | 24 ++++---
+ drivers/crypto/qat/qat_common/qat_algs_send.c | 67 ++++++++++++++++++-
+ drivers/crypto/qat/qat_common/qat_algs_send.h |  1 +
+ drivers/crypto/qat/qat_common/qat_asym_algs.c | 23 ++++---
+ drivers/crypto/qat/qat_common/qat_crypto.c    |  3 +
+ drivers/crypto/qat/qat_common/qat_crypto.h    | 10 +++
+ 9 files changed, 123 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/crypto/qat/qat_common/adf_transport.c b/drivers/crypto/qat/qat_common/adf_transport.c
+index 8ba28409fb74..630d0483c4e0 100644
+--- a/drivers/crypto/qat/qat_common/adf_transport.c
++++ b/drivers/crypto/qat/qat_common/adf_transport.c
+@@ -8,6 +8,9 @@
+ #include "adf_cfg.h"
+ #include "adf_common_drv.h"
++#define ADF_MAX_RING_THRESHOLD                80
++#define ADF_PERCENT(tot, percent)     (((tot) * (percent)) / 100)
++
+ static inline u32 adf_modulo(u32 data, u32 shift)
+ {
+       u32 div = data >> shift;
+@@ -77,6 +80,11 @@ static void adf_disable_ring_irq(struct adf_etr_bank_data *bank, u32 ring)
+                                     bank->irq_mask);
+ }
++bool adf_ring_nearly_full(struct adf_etr_ring_data *ring)
++{
++      return atomic_read(ring->inflights) > ring->threshold;
++}
++
+ int adf_send_message(struct adf_etr_ring_data *ring, u32 *msg)
+ {
+       struct adf_hw_csr_ops *csr_ops = GET_CSR_OPS(ring->bank->accel_dev);
+@@ -217,6 +225,7 @@ int adf_create_ring(struct adf_accel_dev *accel_dev, const char *section,
+       struct adf_etr_bank_data *bank;
+       struct adf_etr_ring_data *ring;
+       char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
++      int max_inflights;
+       u32 ring_num;
+       int ret;
+@@ -263,6 +272,8 @@ int adf_create_ring(struct adf_accel_dev *accel_dev, const char *section,
+       ring->ring_size = adf_verify_ring_size(msg_size, num_msgs);
+       ring->head = 0;
+       ring->tail = 0;
++      max_inflights = ADF_MAX_INFLIGHTS(ring->ring_size, ring->msg_size);
++      ring->threshold = ADF_PERCENT(max_inflights, ADF_MAX_RING_THRESHOLD);
+       atomic_set(ring->inflights, 0);
+       ret = adf_init_ring(ring);
+       if (ret)
+diff --git a/drivers/crypto/qat/qat_common/adf_transport.h b/drivers/crypto/qat/qat_common/adf_transport.h
+index 2c95f1697c76..e6ef6f9b7691 100644
+--- a/drivers/crypto/qat/qat_common/adf_transport.h
++++ b/drivers/crypto/qat/qat_common/adf_transport.h
+@@ -14,6 +14,7 @@ int adf_create_ring(struct adf_accel_dev *accel_dev, const char *section,
+                   const char *ring_name, adf_callback_fn callback,
+                   int poll_mode, struct adf_etr_ring_data **ring_ptr);
++bool adf_ring_nearly_full(struct adf_etr_ring_data *ring);
+ int adf_send_message(struct adf_etr_ring_data *ring, u32 *msg);
+ void adf_remove_ring(struct adf_etr_ring_data *ring);
+ #endif
+diff --git a/drivers/crypto/qat/qat_common/adf_transport_internal.h b/drivers/crypto/qat/qat_common/adf_transport_internal.h
+index 501bcf0f1809..8b2c92ba7ca1 100644
+--- a/drivers/crypto/qat/qat_common/adf_transport_internal.h
++++ b/drivers/crypto/qat/qat_common/adf_transport_internal.h
+@@ -22,6 +22,7 @@ struct adf_etr_ring_data {
+       spinlock_t lock;        /* protects ring data struct */
+       u16 head;
+       u16 tail;
++      u32 threshold;
+       u8 ring_number;
+       u8 ring_size;
+       u8 msg_size;
+diff --git a/drivers/crypto/qat/qat_common/qat_algs.c b/drivers/crypto/qat/qat_common/qat_algs.c
+index 6017ae82c713..873533dc43a7 100644
+--- a/drivers/crypto/qat/qat_common/qat_algs.c
++++ b/drivers/crypto/qat/qat_common/qat_algs.c
+@@ -935,19 +935,25 @@ void qat_alg_callback(void *resp)
+       struct icp_qat_fw_la_resp *qat_resp = resp;
+       struct qat_crypto_request *qat_req =
+                               (void *)(__force long)qat_resp->opaque_data;
++      struct qat_instance_backlog *backlog = qat_req->alg_req.backlog;
+       qat_req->cb(qat_resp, qat_req);
++
++      qat_alg_send_backlog(backlog);
+ }
+ static int qat_alg_send_sym_message(struct qat_crypto_request *qat_req,
+-                                  struct qat_crypto_instance *inst)
++                                  struct qat_crypto_instance *inst,
++                                  struct crypto_async_request *base)
+ {
+-      struct qat_alg_req req;
++      struct qat_alg_req *alg_req = &qat_req->alg_req;
+-      req.fw_req = (u32 *)&qat_req->req;
+-      req.tx_ring = inst->sym_tx;
++      alg_req->fw_req = (u32 *)&qat_req->req;
++      alg_req->tx_ring = inst->sym_tx;
++      alg_req->base = base;
++      alg_req->backlog = &inst->backlog;
+-      return qat_alg_send_message(&req);
++      return qat_alg_send_message(alg_req);
+ }
+ static int qat_alg_aead_dec(struct aead_request *areq)
+@@ -987,7 +993,7 @@ static int qat_alg_aead_dec(struct aead_request *areq)
+       auth_param->auth_off = 0;
+       auth_param->auth_len = areq->assoclen + cipher_param->cipher_length;
+-      ret = qat_alg_send_sym_message(qat_req, ctx->inst);
++      ret = qat_alg_send_sym_message(qat_req, ctx->inst, &areq->base);
+       if (ret == -ENOSPC)
+               qat_alg_free_bufl(ctx->inst, qat_req);
+@@ -1031,7 +1037,7 @@ static int qat_alg_aead_enc(struct aead_request *areq)
+       auth_param->auth_off = 0;
+       auth_param->auth_len = areq->assoclen + areq->cryptlen;
+-      ret = qat_alg_send_sym_message(qat_req, ctx->inst);
++      ret = qat_alg_send_sym_message(qat_req, ctx->inst, &areq->base);
+       if (ret == -ENOSPC)
+               qat_alg_free_bufl(ctx->inst, qat_req);
+@@ -1212,7 +1218,7 @@ static int qat_alg_skcipher_encrypt(struct skcipher_request *req)
+       qat_alg_set_req_iv(qat_req);
+-      ret = qat_alg_send_sym_message(qat_req, ctx->inst);
++      ret = qat_alg_send_sym_message(qat_req, ctx->inst, &req->base);
+       if (ret == -ENOSPC)
+               qat_alg_free_bufl(ctx->inst, qat_req);
+@@ -1278,7 +1284,7 @@ static int qat_alg_skcipher_decrypt(struct skcipher_request *req)
+       qat_alg_set_req_iv(qat_req);
+       qat_alg_update_iv(qat_req);
+-      ret = qat_alg_send_sym_message(qat_req, ctx->inst);
++      ret = qat_alg_send_sym_message(qat_req, ctx->inst, &req->base);
+       if (ret == -ENOSPC)
+               qat_alg_free_bufl(ctx->inst, qat_req);
+diff --git a/drivers/crypto/qat/qat_common/qat_algs_send.c b/drivers/crypto/qat/qat_common/qat_algs_send.c
+index 78f1bb8c26c0..ff5b4347f783 100644
+--- a/drivers/crypto/qat/qat_common/qat_algs_send.c
++++ b/drivers/crypto/qat/qat_common/qat_algs_send.c
+@@ -6,7 +6,7 @@
+ #define ADF_MAX_RETRIES               20
+-int qat_alg_send_message(struct qat_alg_req *req)
++static int qat_alg_send_message_retry(struct qat_alg_req *req)
+ {
+       int ret = 0, ctr = 0;
+@@ -19,3 +19,68 @@ int qat_alg_send_message(struct qat_alg_req *req)
+       return -EINPROGRESS;
+ }
++
++void qat_alg_send_backlog(struct qat_instance_backlog *backlog)
++{
++      struct qat_alg_req *req, *tmp;
++
++      spin_lock_bh(&backlog->lock);
++      list_for_each_entry_safe(req, tmp, &backlog->list, list) {
++              if (adf_send_message(req->tx_ring, req->fw_req)) {
++                      /* The HW ring is full. Do nothing.
++                       * qat_alg_send_backlog() will be invoked again by
++                       * another callback.
++                       */
++                      break;
++              }
++              list_del(&req->list);
++              req->base->complete(req->base, -EINPROGRESS);
++      }
++      spin_unlock_bh(&backlog->lock);
++}
++
++static void qat_alg_backlog_req(struct qat_alg_req *req,
++                              struct qat_instance_backlog *backlog)
++{
++      INIT_LIST_HEAD(&req->list);
++
++      spin_lock_bh(&backlog->lock);
++      list_add_tail(&req->list, &backlog->list);
++      spin_unlock_bh(&backlog->lock);
++}
++
++static int qat_alg_send_message_maybacklog(struct qat_alg_req *req)
++{
++      struct qat_instance_backlog *backlog = req->backlog;
++      struct adf_etr_ring_data *tx_ring = req->tx_ring;
++      u32 *fw_req = req->fw_req;
++
++      /* If any request is already backlogged, then add to backlog list */
++      if (!list_empty(&backlog->list))
++              goto enqueue;
++
++      /* If ring is nearly full, then add to backlog list */
++      if (adf_ring_nearly_full(tx_ring))
++              goto enqueue;
++
++      /* If adding request to HW ring fails, then add to backlog list */
++      if (adf_send_message(tx_ring, fw_req))
++              goto enqueue;
++
++      return -EINPROGRESS;
++
++enqueue:
++      qat_alg_backlog_req(req, backlog);
++
++      return -EBUSY;
++}
++
++int qat_alg_send_message(struct qat_alg_req *req)
++{
++      u32 flags = req->base->flags;
++
++      if (flags & CRYPTO_TFM_REQ_MAY_BACKLOG)
++              return qat_alg_send_message_maybacklog(req);
++      else
++              return qat_alg_send_message_retry(req);
++}
+diff --git a/drivers/crypto/qat/qat_common/qat_algs_send.h b/drivers/crypto/qat/qat_common/qat_algs_send.h
+index 3fa685d0c293..5ce9f4f69d8f 100644
+--- a/drivers/crypto/qat/qat_common/qat_algs_send.h
++++ b/drivers/crypto/qat/qat_common/qat_algs_send.h
+@@ -6,5 +6,6 @@
+ #include "qat_crypto.h"
+ int qat_alg_send_message(struct qat_alg_req *req);
++void qat_alg_send_backlog(struct qat_instance_backlog *backlog);
+ #endif
+diff --git a/drivers/crypto/qat/qat_common/qat_asym_algs.c b/drivers/crypto/qat/qat_common/qat_asym_algs.c
+index 08b8d83e070a..ff7249c093c9 100644
+--- a/drivers/crypto/qat/qat_common/qat_asym_algs.c
++++ b/drivers/crypto/qat/qat_common/qat_asym_algs.c
+@@ -136,17 +136,21 @@ struct qat_asym_request {
+       } areq;
+       int err;
+       void (*cb)(struct icp_qat_fw_pke_resp *resp);
++      struct qat_alg_req alg_req;
+ } __aligned(64);
+ static int qat_alg_send_asym_message(struct qat_asym_request *qat_req,
+-                                   struct qat_crypto_instance *inst)
++                                   struct qat_crypto_instance *inst,
++                                   struct crypto_async_request *base)
+ {
+-      struct qat_alg_req req;
++      struct qat_alg_req *alg_req = &qat_req->alg_req;
+-      req.fw_req = (u32 *)&qat_req->req;
+-      req.tx_ring = inst->pke_tx;
++      alg_req->fw_req = (u32 *)&qat_req->req;
++      alg_req->tx_ring = inst->pke_tx;
++      alg_req->base = base;
++      alg_req->backlog = &inst->backlog;
+-      return qat_alg_send_message(&req);
++      return qat_alg_send_message(alg_req);
+ }
+ static void qat_dh_cb(struct icp_qat_fw_pke_resp *resp)
+@@ -350,7 +354,7 @@ static int qat_dh_compute_value(struct kpp_request *req)
+       msg->input_param_count = n_input_params;
+       msg->output_param_count = 1;
+-      ret = qat_alg_send_asym_message(qat_req, ctx->inst);
++      ret = qat_alg_send_asym_message(qat_req, inst, &req->base);
+       if (ret == -ENOSPC)
+               goto unmap_all;
+@@ -557,8 +561,11 @@ void qat_alg_asym_callback(void *_resp)
+ {
+       struct icp_qat_fw_pke_resp *resp = _resp;
+       struct qat_asym_request *areq = (void *)(__force long)resp->opaque;
++      struct qat_instance_backlog *backlog = areq->alg_req.backlog;
+       areq->cb(resp);
++
++      qat_alg_send_backlog(backlog);
+ }
+ #define PKE_RSA_EP_512 0x1c161b21
+@@ -748,7 +755,7 @@ static int qat_rsa_enc(struct akcipher_request *req)
+       msg->input_param_count = 3;
+       msg->output_param_count = 1;
+-      ret = qat_alg_send_asym_message(qat_req, ctx->inst);
++      ret = qat_alg_send_asym_message(qat_req, inst, &req->base);
+       if (ret == -ENOSPC)
+               goto unmap_all;
+@@ -901,7 +908,7 @@ static int qat_rsa_dec(struct akcipher_request *req)
+       msg->output_param_count = 1;
+-      ret = qat_alg_send_asym_message(qat_req, ctx->inst);
++      ret = qat_alg_send_asym_message(qat_req, inst, &req->base);
+       if (ret == -ENOSPC)
+               goto unmap_all;
+diff --git a/drivers/crypto/qat/qat_common/qat_crypto.c b/drivers/crypto/qat/qat_common/qat_crypto.c
+index 3efbb3883601..59e122afa434 100644
+--- a/drivers/crypto/qat/qat_common/qat_crypto.c
++++ b/drivers/crypto/qat/qat_common/qat_crypto.c
+@@ -328,6 +328,9 @@ static int qat_crypto_create_instances(struct adf_accel_dev *accel_dev)
+                                     &inst->pke_rx);
+               if (ret)
+                       goto err;
++
++              INIT_LIST_HEAD(&inst->backlog.list);
++              spin_lock_init(&inst->backlog.lock);
+       }
+       return 0;
+ err:
+diff --git a/drivers/crypto/qat/qat_common/qat_crypto.h b/drivers/crypto/qat/qat_common/qat_crypto.h
+index 0dcba6fc358c..245b6d9a3650 100644
+--- a/drivers/crypto/qat/qat_common/qat_crypto.h
++++ b/drivers/crypto/qat/qat_common/qat_crypto.h
+@@ -9,9 +9,17 @@
+ #include "adf_accel_devices.h"
+ #include "icp_qat_fw_la.h"
++struct qat_instance_backlog {
++      struct list_head list;
++      spinlock_t lock; /* protects backlog list */
++};
++
+ struct qat_alg_req {
+       u32 *fw_req;
+       struct adf_etr_ring_data *tx_ring;
++      struct crypto_async_request *base;
++      struct list_head list;
++      struct qat_instance_backlog *backlog;
+ };
+ struct qat_crypto_instance {
+@@ -24,6 +32,7 @@ struct qat_crypto_instance {
+       unsigned long state;
+       int id;
+       atomic_t refctr;
++      struct qat_instance_backlog backlog;
+ };
+ #define QAT_MAX_BUFF_DESC     4
+@@ -82,6 +91,7 @@ struct qat_crypto_request {
+               u8 iv[AES_BLOCK_SIZE];
+       };
+       bool encryption;
++      struct qat_alg_req alg_req;
+ };
+ static inline bool adf_hw_dev_has_crypto(struct adf_accel_dev *accel_dev)
+-- 
+2.35.1
+
diff --git a/queue-5.15/crypto-qat-add-param-check-for-dh.patch b/queue-5.15/crypto-qat-add-param-check-for-dh.patch
new file mode 100644 (file)
index 0000000..d986503
--- /dev/null
@@ -0,0 +1,41 @@
+From 5383cc9354f96990402731466133de2b537ea349 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 May 2022 14:34:15 +0100
+Subject: crypto: qat - add param check for DH
+
+From: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+
+[ Upstream commit 2acbb8771f6ac82422886e63832ee7a0f4b1635b ]
+
+Reject requests with a source buffer that is bigger than the size of the
+key. This is to prevent a possible integer underflow that might happen
+when copying the source scatterlist into a linear buffer.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+Reviewed-by: Adam Guerin <adam.guerin@intel.com>
+Reviewed-by: Wojciech Ziemba <wojciech.ziemba@intel.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/crypto/qat/qat_common/qat_asym_algs.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/crypto/qat/qat_common/qat_asym_algs.c b/drivers/crypto/qat/qat_common/qat_asym_algs.c
+index 947eeff181b4..7173a2a0a484 100644
+--- a/drivers/crypto/qat/qat_common/qat_asym_algs.c
++++ b/drivers/crypto/qat/qat_common/qat_asym_algs.c
+@@ -235,6 +235,10 @@ static int qat_dh_compute_value(struct kpp_request *req)
+               req->dst_len = ctx->p_size;
+               return -EOVERFLOW;
+       }
++
++      if (req->src_len > ctx->p_size)
++              return -EINVAL;
++
+       memset(msg, '\0', sizeof(*msg));
+       ICP_QAT_FW_PKE_HDR_VALID_FLAG_SET(msg->pke_hdr,
+                                         ICP_QAT_FW_COMN_REQ_FLAG_SET);
+-- 
+2.35.1
+
diff --git a/queue-5.15/crypto-qat-add-param-check-for-rsa.patch b/queue-5.15/crypto-qat-add-param-check-for-rsa.patch
new file mode 100644 (file)
index 0000000..15a324d
--- /dev/null
@@ -0,0 +1,52 @@
+From 9a9d8c8f792723722eecd5bdd9b9e55455800aaa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 May 2022 14:34:14 +0100
+Subject: crypto: qat - add param check for RSA
+
+From: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+
+[ Upstream commit 9714061423b8b24b8afb31b8eb4df977c63f19c4 ]
+
+Reject requests with a source buffer that is bigger than the size of the
+key. This is to prevent a possible integer underflow that might happen
+when copying the source scatterlist into a linear buffer.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+Reviewed-by: Adam Guerin <adam.guerin@intel.com>
+Reviewed-by: Wojciech Ziemba <wojciech.ziemba@intel.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/crypto/qat/qat_common/qat_asym_algs.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/drivers/crypto/qat/qat_common/qat_asym_algs.c b/drivers/crypto/qat/qat_common/qat_asym_algs.c
+index 25bbd22085c3..947eeff181b4 100644
+--- a/drivers/crypto/qat/qat_common/qat_asym_algs.c
++++ b/drivers/crypto/qat/qat_common/qat_asym_algs.c
+@@ -656,6 +656,10 @@ static int qat_rsa_enc(struct akcipher_request *req)
+               req->dst_len = ctx->key_sz;
+               return -EOVERFLOW;
+       }
++
++      if (req->src_len > ctx->key_sz)
++              return -EINVAL;
++
+       memset(msg, '\0', sizeof(*msg));
+       ICP_QAT_FW_PKE_HDR_VALID_FLAG_SET(msg->pke_hdr,
+                                         ICP_QAT_FW_COMN_REQ_FLAG_SET);
+@@ -785,6 +789,10 @@ static int qat_rsa_dec(struct akcipher_request *req)
+               req->dst_len = ctx->key_sz;
+               return -EOVERFLOW;
+       }
++
++      if (req->src_len > ctx->key_sz)
++              return -EINVAL;
++
+       memset(msg, '\0', sizeof(*msg));
+       ICP_QAT_FW_PKE_HDR_VALID_FLAG_SET(msg->pke_hdr,
+                                         ICP_QAT_FW_COMN_REQ_FLAG_SET);
+-- 
+2.35.1
+
diff --git a/queue-5.15/crypto-qat-fix-memory-leak-in-rsa.patch b/queue-5.15/crypto-qat-fix-memory-leak-in-rsa.patch
new file mode 100644 (file)
index 0000000..fb3788c
--- /dev/null
@@ -0,0 +1,54 @@
+From 4bd21510822b9afcb74765de49b9615415cd19b8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 May 2022 14:34:11 +0100
+Subject: crypto: qat - fix memory leak in RSA
+
+From: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+
+[ Upstream commit 80a52e1ee7757b742f96bfb0d58f0c14eb6583d0 ]
+
+When an RSA key represented in form 2 (as defined in PKCS #1 V2.1) is
+used, some components of the private key persist even after the TFM is
+released.
+Replace the explicit calls to free the buffers in qat_rsa_exit_tfm()
+with a call to qat_rsa_clear_ctx() which frees all buffers referenced in
+the TFM context.
+
+Cc: stable@vger.kernel.org
+Fixes: 879f77e9071f ("crypto: qat - Add RSA CRT mode")
+Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+Reviewed-by: Adam Guerin <adam.guerin@intel.com>
+Reviewed-by: Wojciech Ziemba <wojciech.ziemba@intel.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/crypto/qat/qat_common/qat_asym_algs.c | 12 +-----------
+ 1 file changed, 1 insertion(+), 11 deletions(-)
+
+diff --git a/drivers/crypto/qat/qat_common/qat_asym_algs.c b/drivers/crypto/qat/qat_common/qat_asym_algs.c
+index ff7249c093c9..2bc02c75398e 100644
+--- a/drivers/crypto/qat/qat_common/qat_asym_algs.c
++++ b/drivers/crypto/qat/qat_common/qat_asym_algs.c
+@@ -1257,18 +1257,8 @@ static void qat_rsa_exit_tfm(struct crypto_akcipher *tfm)
+       struct qat_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+       struct device *dev = &GET_DEV(ctx->inst->accel_dev);
+-      if (ctx->n)
+-              dma_free_coherent(dev, ctx->key_sz, ctx->n, ctx->dma_n);
+-      if (ctx->e)
+-              dma_free_coherent(dev, ctx->key_sz, ctx->e, ctx->dma_e);
+-      if (ctx->d) {
+-              memset(ctx->d, '\0', ctx->key_sz);
+-              dma_free_coherent(dev, ctx->key_sz, ctx->d, ctx->dma_d);
+-      }
++      qat_rsa_clear_ctx(dev, ctx);
+       qat_crypto_put_instance(ctx->inst);
+-      ctx->n = NULL;
+-      ctx->e = NULL;
+-      ctx->d = NULL;
+ }
+ static struct akcipher_alg rsa = {
+-- 
+2.35.1
+
diff --git a/queue-5.15/crypto-qat-re-enable-registration-of-algorithms.patch b/queue-5.15/crypto-qat-re-enable-registration-of-algorithms.patch
new file mode 100644 (file)
index 0000000..dbe01aa
--- /dev/null
@@ -0,0 +1,66 @@
+From 9ce3a04e6488df1e887f3bfcec74f6bf02069397 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 May 2022 14:34:17 +0100
+Subject: crypto: qat - re-enable registration of algorithms
+
+From: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+
+[ Upstream commit d09144745959bf7852ccafd73243dd7d1eaeb163 ]
+
+Re-enable the registration of algorithms after fixes to (1) use
+pre-allocated buffers in the datapath and (2) support the
+CRYPTO_TFM_REQ_MAY_BACKLOG flag.
+
+This reverts commit 8893d27ffcaf6ec6267038a177cb87bcde4dd3de.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+Reviewed-by: Marco Chiappero <marco.chiappero@intel.com>
+Reviewed-by: Adam Guerin <adam.guerin@intel.com>
+Reviewed-by: Wojciech Ziemba <wojciech.ziemba@intel.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/crypto/qat/qat_4xxx/adf_drv.c      | 7 -------
+ drivers/crypto/qat/qat_common/qat_crypto.c | 7 -------
+ 2 files changed, 14 deletions(-)
+
+diff --git a/drivers/crypto/qat/qat_4xxx/adf_drv.c b/drivers/crypto/qat/qat_4xxx/adf_drv.c
+index 8fd44703115f..359fb7989dfb 100644
+--- a/drivers/crypto/qat/qat_4xxx/adf_drv.c
++++ b/drivers/crypto/qat/qat_4xxx/adf_drv.c
+@@ -52,13 +52,6 @@ static int adf_crypto_dev_config(struct adf_accel_dev *accel_dev)
+       if (ret)
+               goto err;
+-      /* Temporarily set the number of crypto instances to zero to avoid
+-       * registering the crypto algorithms.
+-       * This will be removed when the algorithms will support the
+-       * CRYPTO_TFM_REQ_MAY_BACKLOG flag
+-       */
+-      instances = 0;
+-
+       for (i = 0; i < instances; i++) {
+               val = i;
+               bank = i * 2;
+diff --git a/drivers/crypto/qat/qat_common/qat_crypto.c b/drivers/crypto/qat/qat_common/qat_crypto.c
+index 59e122afa434..994e43fab0a4 100644
+--- a/drivers/crypto/qat/qat_common/qat_crypto.c
++++ b/drivers/crypto/qat/qat_common/qat_crypto.c
+@@ -136,13 +136,6 @@ int qat_crypto_dev_config(struct adf_accel_dev *accel_dev)
+       if (ret)
+               goto err;
+-      /* Temporarily set the number of crypto instances to zero to avoid
+-       * registering the crypto algorithms.
+-       * This will be removed when the algorithms will support the
+-       * CRYPTO_TFM_REQ_MAY_BACKLOG flag
+-       */
+-      instances = 0;
+-
+       for (i = 0; i < instances; i++) {
+               val = i;
+               snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_ASYM_BANK_NUM, i);
+-- 
+2.35.1
+
diff --git a/queue-5.15/crypto-qat-refactor-submission-logic.patch b/queue-5.15/crypto-qat-refactor-submission-logic.patch
new file mode 100644 (file)
index 0000000..5dcebb5
--- /dev/null
@@ -0,0 +1,379 @@
+From 99b4a13c31aff837af03150dc1b0e79cf6474337 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 May 2022 14:34:09 +0100
+Subject: crypto: qat - refactor submission logic
+
+From: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+
+[ Upstream commit af88d3c109aa5edfaa11c9a26d9c0ff21ddf501c ]
+
+All the algorithms in qat_algs.c and qat_asym_algs.c use the same
+pattern to submit messages to the HW queues. Move the submission loop
+to a new function, qat_alg_send_message(), and share it between the
+symmetric and the asymmetric algorithms.
+
+As part of this rework, since the number of retries before returning an
+error is inconsistent between the symmetric and asymmetric
+implementations, set it to a value that works for both (i.e. 20, was 10
+in qat_algs.c and 100 in qat_asym_algs.c)
+
+In addition fix the return code reported when the HW queues are full.
+In that case return -ENOSPC instead of -EBUSY.
+
+Including stable in CC since (1) the error code returned if the HW queues
+are full is incorrect and (2) to facilitate the backport of the next fix
+"crypto: qat - add backlog mechanism".
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+Reviewed-by: Marco Chiappero <marco.chiappero@intel.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/crypto/qat/qat_common/Makefile        |  1 +
+ drivers/crypto/qat/qat_common/qat_algs.c      | 68 +++++++++----------
+ drivers/crypto/qat/qat_common/qat_algs_send.c | 21 ++++++
+ drivers/crypto/qat/qat_common/qat_algs_send.h | 10 +++
+ drivers/crypto/qat/qat_common/qat_asym_algs.c | 50 +++++++++-----
+ drivers/crypto/qat/qat_common/qat_crypto.h    |  5 ++
+ 6 files changed, 101 insertions(+), 54 deletions(-)
+ create mode 100644 drivers/crypto/qat/qat_common/qat_algs_send.c
+ create mode 100644 drivers/crypto/qat/qat_common/qat_algs_send.h
+
+diff --git a/drivers/crypto/qat/qat_common/Makefile b/drivers/crypto/qat/qat_common/Makefile
+index 9c57abdf56b7..fc477f016213 100644
+--- a/drivers/crypto/qat/qat_common/Makefile
++++ b/drivers/crypto/qat/qat_common/Makefile
+@@ -15,6 +15,7 @@ intel_qat-objs := adf_cfg.o \
+       qat_crypto.o \
+       qat_algs.o \
+       qat_asym_algs.o \
++      qat_algs_send.o \
+       qat_uclo.o \
+       qat_hal.o
+diff --git a/drivers/crypto/qat/qat_common/qat_algs.c b/drivers/crypto/qat/qat_common/qat_algs.c
+index ec635fe44c1f..6017ae82c713 100644
+--- a/drivers/crypto/qat/qat_common/qat_algs.c
++++ b/drivers/crypto/qat/qat_common/qat_algs.c
+@@ -17,7 +17,7 @@
+ #include <crypto/xts.h>
+ #include <linux/dma-mapping.h>
+ #include "adf_accel_devices.h"
+-#include "adf_transport.h"
++#include "qat_algs_send.h"
+ #include "adf_common_drv.h"
+ #include "qat_crypto.h"
+ #include "icp_qat_hw.h"
+@@ -939,6 +939,17 @@ void qat_alg_callback(void *resp)
+       qat_req->cb(qat_resp, qat_req);
+ }
++static int qat_alg_send_sym_message(struct qat_crypto_request *qat_req,
++                                  struct qat_crypto_instance *inst)
++{
++      struct qat_alg_req req;
++
++      req.fw_req = (u32 *)&qat_req->req;
++      req.tx_ring = inst->sym_tx;
++
++      return qat_alg_send_message(&req);
++}
++
+ static int qat_alg_aead_dec(struct aead_request *areq)
+ {
+       struct crypto_aead *aead_tfm = crypto_aead_reqtfm(areq);
+@@ -949,7 +960,7 @@ static int qat_alg_aead_dec(struct aead_request *areq)
+       struct icp_qat_fw_la_auth_req_params *auth_param;
+       struct icp_qat_fw_la_bulk_req *msg;
+       int digst_size = crypto_aead_authsize(aead_tfm);
+-      int ret, ctr = 0;
++      int ret;
+       u32 cipher_len;
+       cipher_len = areq->cryptlen - digst_size;
+@@ -975,15 +986,12 @@ static int qat_alg_aead_dec(struct aead_request *areq)
+       auth_param = (void *)((u8 *)cipher_param + sizeof(*cipher_param));
+       auth_param->auth_off = 0;
+       auth_param->auth_len = areq->assoclen + cipher_param->cipher_length;
+-      do {
+-              ret = adf_send_message(ctx->inst->sym_tx, (u32 *)msg);
+-      } while (ret == -EAGAIN && ctr++ < 10);
+-      if (ret == -EAGAIN) {
++      ret = qat_alg_send_sym_message(qat_req, ctx->inst);
++      if (ret == -ENOSPC)
+               qat_alg_free_bufl(ctx->inst, qat_req);
+-              return -EBUSY;
+-      }
+-      return -EINPROGRESS;
++
++      return ret;
+ }
+ static int qat_alg_aead_enc(struct aead_request *areq)
+@@ -996,7 +1004,7 @@ static int qat_alg_aead_enc(struct aead_request *areq)
+       struct icp_qat_fw_la_auth_req_params *auth_param;
+       struct icp_qat_fw_la_bulk_req *msg;
+       u8 *iv = areq->iv;
+-      int ret, ctr = 0;
++      int ret;
+       if (areq->cryptlen % AES_BLOCK_SIZE != 0)
+               return -EINVAL;
+@@ -1023,15 +1031,11 @@ static int qat_alg_aead_enc(struct aead_request *areq)
+       auth_param->auth_off = 0;
+       auth_param->auth_len = areq->assoclen + areq->cryptlen;
+-      do {
+-              ret = adf_send_message(ctx->inst->sym_tx, (u32 *)msg);
+-      } while (ret == -EAGAIN && ctr++ < 10);
+-
+-      if (ret == -EAGAIN) {
++      ret = qat_alg_send_sym_message(qat_req, ctx->inst);
++      if (ret == -ENOSPC)
+               qat_alg_free_bufl(ctx->inst, qat_req);
+-              return -EBUSY;
+-      }
+-      return -EINPROGRESS;
++
++      return ret;
+ }
+ static int qat_alg_skcipher_rekey(struct qat_alg_skcipher_ctx *ctx,
+@@ -1184,7 +1188,7 @@ static int qat_alg_skcipher_encrypt(struct skcipher_request *req)
+       struct qat_crypto_request *qat_req = skcipher_request_ctx(req);
+       struct icp_qat_fw_la_cipher_req_params *cipher_param;
+       struct icp_qat_fw_la_bulk_req *msg;
+-      int ret, ctr = 0;
++      int ret;
+       if (req->cryptlen == 0)
+               return 0;
+@@ -1208,15 +1212,11 @@ static int qat_alg_skcipher_encrypt(struct skcipher_request *req)
+       qat_alg_set_req_iv(qat_req);
+-      do {
+-              ret = adf_send_message(ctx->inst->sym_tx, (u32 *)msg);
+-      } while (ret == -EAGAIN && ctr++ < 10);
+-
+-      if (ret == -EAGAIN) {
++      ret = qat_alg_send_sym_message(qat_req, ctx->inst);
++      if (ret == -ENOSPC)
+               qat_alg_free_bufl(ctx->inst, qat_req);
+-              return -EBUSY;
+-      }
+-      return -EINPROGRESS;
++
++      return ret;
+ }
+ static int qat_alg_skcipher_blk_encrypt(struct skcipher_request *req)
+@@ -1253,7 +1253,7 @@ static int qat_alg_skcipher_decrypt(struct skcipher_request *req)
+       struct qat_crypto_request *qat_req = skcipher_request_ctx(req);
+       struct icp_qat_fw_la_cipher_req_params *cipher_param;
+       struct icp_qat_fw_la_bulk_req *msg;
+-      int ret, ctr = 0;
++      int ret;
+       if (req->cryptlen == 0)
+               return 0;
+@@ -1278,15 +1278,11 @@ static int qat_alg_skcipher_decrypt(struct skcipher_request *req)
+       qat_alg_set_req_iv(qat_req);
+       qat_alg_update_iv(qat_req);
+-      do {
+-              ret = adf_send_message(ctx->inst->sym_tx, (u32 *)msg);
+-      } while (ret == -EAGAIN && ctr++ < 10);
+-
+-      if (ret == -EAGAIN) {
++      ret = qat_alg_send_sym_message(qat_req, ctx->inst);
++      if (ret == -ENOSPC)
+               qat_alg_free_bufl(ctx->inst, qat_req);
+-              return -EBUSY;
+-      }
+-      return -EINPROGRESS;
++
++      return ret;
+ }
+ static int qat_alg_skcipher_blk_decrypt(struct skcipher_request *req)
+diff --git a/drivers/crypto/qat/qat_common/qat_algs_send.c b/drivers/crypto/qat/qat_common/qat_algs_send.c
+new file mode 100644
+index 000000000000..78f1bb8c26c0
+--- /dev/null
++++ b/drivers/crypto/qat/qat_common/qat_algs_send.c
+@@ -0,0 +1,21 @@
++// SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only)
++/* Copyright(c) 2022 Intel Corporation */
++#include "adf_transport.h"
++#include "qat_algs_send.h"
++#include "qat_crypto.h"
++
++#define ADF_MAX_RETRIES               20
++
++int qat_alg_send_message(struct qat_alg_req *req)
++{
++      int ret = 0, ctr = 0;
++
++      do {
++              ret = adf_send_message(req->tx_ring, req->fw_req);
++      } while (ret == -EAGAIN && ctr++ < ADF_MAX_RETRIES);
++
++      if (ret == -EAGAIN)
++              return -ENOSPC;
++
++      return -EINPROGRESS;
++}
+diff --git a/drivers/crypto/qat/qat_common/qat_algs_send.h b/drivers/crypto/qat/qat_common/qat_algs_send.h
+new file mode 100644
+index 000000000000..3fa685d0c293
+--- /dev/null
++++ b/drivers/crypto/qat/qat_common/qat_algs_send.h
+@@ -0,0 +1,10 @@
++/* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only) */
++/* Copyright(c) 2022 Intel Corporation */
++#ifndef QAT_ALGS_SEND_H
++#define QAT_ALGS_SEND_H
++
++#include "qat_crypto.h"
++
++int qat_alg_send_message(struct qat_alg_req *req);
++
++#endif
+diff --git a/drivers/crypto/qat/qat_common/qat_asym_algs.c b/drivers/crypto/qat/qat_common/qat_asym_algs.c
+index 5633f9df3b6f..08b8d83e070a 100644
+--- a/drivers/crypto/qat/qat_common/qat_asym_algs.c
++++ b/drivers/crypto/qat/qat_common/qat_asym_algs.c
+@@ -12,6 +12,7 @@
+ #include <crypto/scatterwalk.h>
+ #include "icp_qat_fw_pke.h"
+ #include "adf_accel_devices.h"
++#include "qat_algs_send.h"
+ #include "adf_transport.h"
+ #include "adf_common_drv.h"
+ #include "qat_crypto.h"
+@@ -137,6 +138,17 @@ struct qat_asym_request {
+       void (*cb)(struct icp_qat_fw_pke_resp *resp);
+ } __aligned(64);
++static int qat_alg_send_asym_message(struct qat_asym_request *qat_req,
++                                   struct qat_crypto_instance *inst)
++{
++      struct qat_alg_req req;
++
++      req.fw_req = (u32 *)&qat_req->req;
++      req.tx_ring = inst->pke_tx;
++
++      return qat_alg_send_message(&req);
++}
++
+ static void qat_dh_cb(struct icp_qat_fw_pke_resp *resp)
+ {
+       struct qat_asym_request *req = (void *)(__force long)resp->opaque;
+@@ -213,7 +225,7 @@ static int qat_dh_compute_value(struct kpp_request *req)
+       struct qat_asym_request *qat_req =
+                       PTR_ALIGN(kpp_request_ctx(req), 64);
+       struct icp_qat_fw_pke_request *msg = &qat_req->req;
+-      int ret, ctr = 0;
++      int ret;
+       int n_input_params = 0;
+       if (unlikely(!ctx->xa))
+@@ -338,13 +350,13 @@ static int qat_dh_compute_value(struct kpp_request *req)
+       msg->input_param_count = n_input_params;
+       msg->output_param_count = 1;
+-      do {
+-              ret = adf_send_message(ctx->inst->pke_tx, (u32 *)msg);
+-      } while (ret == -EBUSY && ctr++ < 100);
++      ret = qat_alg_send_asym_message(qat_req, ctx->inst);
++      if (ret == -ENOSPC)
++              goto unmap_all;
+-      if (!ret)
+-              return -EINPROGRESS;
++      return ret;
++unmap_all:
+       if (!dma_mapping_error(dev, qat_req->phy_out))
+               dma_unmap_single(dev, qat_req->phy_out,
+                                sizeof(struct qat_dh_output_params),
+@@ -645,7 +657,7 @@ static int qat_rsa_enc(struct akcipher_request *req)
+       struct qat_asym_request *qat_req =
+                       PTR_ALIGN(akcipher_request_ctx(req), 64);
+       struct icp_qat_fw_pke_request *msg = &qat_req->req;
+-      int ret, ctr = 0;
++      int ret;
+       if (unlikely(!ctx->n || !ctx->e))
+               return -EINVAL;
+@@ -735,13 +747,14 @@ static int qat_rsa_enc(struct akcipher_request *req)
+       msg->pke_mid.opaque = (u64)(__force long)qat_req;
+       msg->input_param_count = 3;
+       msg->output_param_count = 1;
+-      do {
+-              ret = adf_send_message(ctx->inst->pke_tx, (u32 *)msg);
+-      } while (ret == -EBUSY && ctr++ < 100);
+-      if (!ret)
+-              return -EINPROGRESS;
++      ret = qat_alg_send_asym_message(qat_req, ctx->inst);
++      if (ret == -ENOSPC)
++              goto unmap_all;
++
++      return ret;
++unmap_all:
+       if (!dma_mapping_error(dev, qat_req->phy_out))
+               dma_unmap_single(dev, qat_req->phy_out,
+                                sizeof(struct qat_rsa_output_params),
+@@ -779,7 +792,7 @@ static int qat_rsa_dec(struct akcipher_request *req)
+       struct qat_asym_request *qat_req =
+                       PTR_ALIGN(akcipher_request_ctx(req), 64);
+       struct icp_qat_fw_pke_request *msg = &qat_req->req;
+-      int ret, ctr = 0;
++      int ret;
+       if (unlikely(!ctx->n || !ctx->d))
+               return -EINVAL;
+@@ -887,13 +900,14 @@ static int qat_rsa_dec(struct akcipher_request *req)
+               msg->input_param_count = 3;
+       msg->output_param_count = 1;
+-      do {
+-              ret = adf_send_message(ctx->inst->pke_tx, (u32 *)msg);
+-      } while (ret == -EBUSY && ctr++ < 100);
+-      if (!ret)
+-              return -EINPROGRESS;
++      ret = qat_alg_send_asym_message(qat_req, ctx->inst);
++      if (ret == -ENOSPC)
++              goto unmap_all;
++
++      return ret;
++unmap_all:
+       if (!dma_mapping_error(dev, qat_req->phy_out))
+               dma_unmap_single(dev, qat_req->phy_out,
+                                sizeof(struct qat_rsa_output_params),
+diff --git a/drivers/crypto/qat/qat_common/qat_crypto.h b/drivers/crypto/qat/qat_common/qat_crypto.h
+index 0928f159ea99..0dcba6fc358c 100644
+--- a/drivers/crypto/qat/qat_common/qat_crypto.h
++++ b/drivers/crypto/qat/qat_common/qat_crypto.h
+@@ -9,6 +9,11 @@
+ #include "adf_accel_devices.h"
+ #include "icp_qat_fw_la.h"
++struct qat_alg_req {
++      u32 *fw_req;
++      struct adf_etr_ring_data *tx_ring;
++};
++
+ struct qat_crypto_instance {
+       struct adf_etr_ring_data *sym_tx;
+       struct adf_etr_ring_data *sym_rx;
+-- 
+2.35.1
+
diff --git a/queue-5.15/crypto-qat-remove-dma_free_coherent-for-dh.patch b/queue-5.15/crypto-qat-remove-dma_free_coherent-for-dh.patch
new file mode 100644 (file)
index 0000000..d722620
--- /dev/null
@@ -0,0 +1,181 @@
+From 997c0edb37fd39f3f31f5e821d2e23f816c70aa4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 May 2022 14:34:13 +0100
+Subject: crypto: qat - remove dma_free_coherent() for DH
+
+From: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+
+[ Upstream commit 029aa4624a7fe35233bdd3d1354dc7be260380bf ]
+
+The functions qat_dh_compute_value() allocates memory with
+dma_alloc_coherent() if the source or the destination buffers are made
+of multiple flat buffers or of a size that is not compatible with the
+hardware.
+This memory is then freed with dma_free_coherent() in the context of a
+tasklet invoked to handle the response for the corresponding request.
+
+According to Documentation/core-api/dma-api-howto.rst, the function
+dma_free_coherent() cannot be called in an interrupt context.
+
+Replace allocations with dma_alloc_coherent() in the function
+qat_dh_compute_value() with kmalloc() + dma_map_single().
+
+Cc: stable@vger.kernel.org
+Fixes: c9839143ebbf ("crypto: qat - Add DH support")
+Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+Reviewed-by: Adam Guerin <adam.guerin@intel.com>
+Reviewed-by: Wojciech Ziemba <wojciech.ziemba@intel.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/crypto/qat/qat_common/qat_asym_algs.c | 83 ++++++++-----------
+ 1 file changed, 34 insertions(+), 49 deletions(-)
+
+diff --git a/drivers/crypto/qat/qat_common/qat_asym_algs.c b/drivers/crypto/qat/qat_common/qat_asym_algs.c
+index b31372bddb96..25bbd22085c3 100644
+--- a/drivers/crypto/qat/qat_common/qat_asym_algs.c
++++ b/drivers/crypto/qat/qat_common/qat_asym_algs.c
+@@ -164,26 +164,21 @@ static void qat_dh_cb(struct icp_qat_fw_pke_resp *resp)
+       err = (err == ICP_QAT_FW_COMN_STATUS_FLAG_OK) ? 0 : -EINVAL;
+       if (areq->src) {
+-              if (req->src_align)
+-                      dma_free_coherent(dev, req->ctx.dh->p_size,
+-                                        req->src_align, req->in.dh.in.b);
+-              else
+-                      dma_unmap_single(dev, req->in.dh.in.b,
+-                                       req->ctx.dh->p_size, DMA_TO_DEVICE);
++              dma_unmap_single(dev, req->in.dh.in.b, req->ctx.dh->p_size,
++                               DMA_TO_DEVICE);
++              kfree_sensitive(req->src_align);
+       }
+       areq->dst_len = req->ctx.dh->p_size;
+       if (req->dst_align) {
+               scatterwalk_map_and_copy(req->dst_align, areq->dst, 0,
+                                        areq->dst_len, 1);
+-
+-              dma_free_coherent(dev, req->ctx.dh->p_size, req->dst_align,
+-                                req->out.dh.r);
+-      } else {
+-              dma_unmap_single(dev, req->out.dh.r, req->ctx.dh->p_size,
+-                               DMA_FROM_DEVICE);
++              kfree_sensitive(req->dst_align);
+       }
++      dma_unmap_single(dev, req->out.dh.r, req->ctx.dh->p_size,
++                       DMA_FROM_DEVICE);
++
+       dma_unmap_single(dev, req->phy_in, sizeof(struct qat_dh_input_params),
+                        DMA_TO_DEVICE);
+       dma_unmap_single(dev, req->phy_out,
+@@ -231,6 +226,7 @@ static int qat_dh_compute_value(struct kpp_request *req)
+       struct icp_qat_fw_pke_request *msg = &qat_req->req;
+       int ret;
+       int n_input_params = 0;
++      u8 *vaddr;
+       if (unlikely(!ctx->xa))
+               return -EINVAL;
+@@ -287,27 +283,24 @@ static int qat_dh_compute_value(struct kpp_request *req)
+                */
+               if (sg_is_last(req->src) && req->src_len == ctx->p_size) {
+                       qat_req->src_align = NULL;
+-                      qat_req->in.dh.in.b = dma_map_single(dev,
+-                                                           sg_virt(req->src),
+-                                                           req->src_len,
+-                                                           DMA_TO_DEVICE);
+-                      if (unlikely(dma_mapping_error(dev,
+-                                                     qat_req->in.dh.in.b)))
+-                              return ret;
+-
++                      vaddr = sg_virt(req->src);
+               } else {
+                       int shift = ctx->p_size - req->src_len;
+-                      qat_req->src_align = dma_alloc_coherent(dev,
+-                                                              ctx->p_size,
+-                                                              &qat_req->in.dh.in.b,
+-                                                              GFP_KERNEL);
++                      qat_req->src_align = kzalloc(ctx->p_size, GFP_KERNEL);
+                       if (unlikely(!qat_req->src_align))
+                               return ret;
+                       scatterwalk_map_and_copy(qat_req->src_align + shift,
+                                                req->src, 0, req->src_len, 0);
++
++                      vaddr = qat_req->src_align;
+               }
++
++              qat_req->in.dh.in.b = dma_map_single(dev, vaddr, ctx->p_size,
++                                                   DMA_TO_DEVICE);
++              if (unlikely(dma_mapping_error(dev, qat_req->in.dh.in.b)))
++                      goto unmap_src;
+       }
+       /*
+        * dst can be of any size in valid range, but HW expects it to be the
+@@ -318,20 +311,18 @@ static int qat_dh_compute_value(struct kpp_request *req)
+        */
+       if (sg_is_last(req->dst) && req->dst_len == ctx->p_size) {
+               qat_req->dst_align = NULL;
+-              qat_req->out.dh.r = dma_map_single(dev, sg_virt(req->dst),
+-                                                 req->dst_len,
+-                                                 DMA_FROM_DEVICE);
+-
+-              if (unlikely(dma_mapping_error(dev, qat_req->out.dh.r)))
+-                      goto unmap_src;
+-
++              vaddr = sg_virt(req->dst);
+       } else {
+-              qat_req->dst_align = dma_alloc_coherent(dev, ctx->p_size,
+-                                                      &qat_req->out.dh.r,
+-                                                      GFP_KERNEL);
++              qat_req->dst_align = kzalloc(ctx->p_size, GFP_KERNEL);
+               if (unlikely(!qat_req->dst_align))
+                       goto unmap_src;
++
++              vaddr = qat_req->dst_align;
+       }
++      qat_req->out.dh.r = dma_map_single(dev, vaddr, ctx->p_size,
++                                         DMA_FROM_DEVICE);
++      if (unlikely(dma_mapping_error(dev, qat_req->out.dh.r)))
++              goto unmap_dst;
+       qat_req->in.dh.in_tab[n_input_params] = 0;
+       qat_req->out.dh.out_tab[1] = 0;
+@@ -371,23 +362,17 @@ static int qat_dh_compute_value(struct kpp_request *req)
+                                sizeof(struct qat_dh_input_params),
+                                DMA_TO_DEVICE);
+ unmap_dst:
+-      if (qat_req->dst_align)
+-              dma_free_coherent(dev, ctx->p_size, qat_req->dst_align,
+-                                qat_req->out.dh.r);
+-      else
+-              if (!dma_mapping_error(dev, qat_req->out.dh.r))
+-                      dma_unmap_single(dev, qat_req->out.dh.r, ctx->p_size,
+-                                       DMA_FROM_DEVICE);
++      if (!dma_mapping_error(dev, qat_req->out.dh.r))
++              dma_unmap_single(dev, qat_req->out.dh.r, ctx->p_size,
++                               DMA_FROM_DEVICE);
++      kfree_sensitive(qat_req->dst_align);
+ unmap_src:
+       if (req->src) {
+-              if (qat_req->src_align)
+-                      dma_free_coherent(dev, ctx->p_size, qat_req->src_align,
+-                                        qat_req->in.dh.in.b);
+-              else
+-                      if (!dma_mapping_error(dev, qat_req->in.dh.in.b))
+-                              dma_unmap_single(dev, qat_req->in.dh.in.b,
+-                                               ctx->p_size,
+-                                               DMA_TO_DEVICE);
++              if (!dma_mapping_error(dev, qat_req->in.dh.in.b))
++                      dma_unmap_single(dev, qat_req->in.dh.in.b,
++                                       ctx->p_size,
++                                       DMA_TO_DEVICE);
++              kfree_sensitive(qat_req->src_align);
+       }
+       return ret;
+ }
+-- 
+2.35.1
+
diff --git a/queue-5.15/crypto-qat-remove-dma_free_coherent-for-rsa.patch b/queue-5.15/crypto-qat-remove-dma_free_coherent-for-rsa.patch
new file mode 100644 (file)
index 0000000..ba04c33
--- /dev/null
@@ -0,0 +1,269 @@
+From 0fd019b01348c0b3c7d9dc02114e46d7c8ed1d78 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 May 2022 14:34:12 +0100
+Subject: crypto: qat - remove dma_free_coherent() for RSA
+
+From: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+
+[ Upstream commit 3dfaf0071ed74d7a9c6b3c9ea4df7a6f8e423c2a ]
+
+After commit f5ff79fddf0e ("dma-mapping: remove CONFIG_DMA_REMAP"), if
+the algorithms are enabled, the driver crashes with a BUG_ON while
+executing vunmap() in the context of a tasklet. This is due to the fact
+that the function dma_free_coherent() cannot be called in an interrupt
+context (see Documentation/core-api/dma-api-howto.rst).
+
+The functions qat_rsa_enc() and qat_rsa_dec() allocate memory with
+dma_alloc_coherent() if the source or the destination buffers are made
+of multiple flat buffers or of a size that is not compatible with the
+hardware.
+This memory is then freed with dma_free_coherent() in the context of a
+tasklet invoked to handle the response for the corresponding request.
+
+Replace allocations with dma_alloc_coherent() in the functions
+qat_rsa_enc() and qat_rsa_dec() with kmalloc() + dma_map_single().
+
+Cc: stable@vger.kernel.org
+Fixes: a990532023b9 ("crypto: qat - Add support for RSA algorithm")
+Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+Reviewed-by: Adam Guerin <adam.guerin@intel.com>
+Reviewed-by: Wojciech Ziemba <wojciech.ziemba@intel.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/crypto/qat/qat_common/qat_asym_algs.c | 137 ++++++++----------
+ 1 file changed, 60 insertions(+), 77 deletions(-)
+
+diff --git a/drivers/crypto/qat/qat_common/qat_asym_algs.c b/drivers/crypto/qat/qat_common/qat_asym_algs.c
+index 2bc02c75398e..b31372bddb96 100644
+--- a/drivers/crypto/qat/qat_common/qat_asym_algs.c
++++ b/drivers/crypto/qat/qat_common/qat_asym_algs.c
+@@ -529,25 +529,22 @@ static void qat_rsa_cb(struct icp_qat_fw_pke_resp *resp)
+       err = (err == ICP_QAT_FW_COMN_STATUS_FLAG_OK) ? 0 : -EINVAL;
+-      if (req->src_align)
+-              dma_free_coherent(dev, req->ctx.rsa->key_sz, req->src_align,
+-                                req->in.rsa.enc.m);
+-      else
+-              dma_unmap_single(dev, req->in.rsa.enc.m, req->ctx.rsa->key_sz,
+-                               DMA_TO_DEVICE);
++      kfree_sensitive(req->src_align);
++
++      dma_unmap_single(dev, req->in.rsa.enc.m, req->ctx.rsa->key_sz,
++                       DMA_TO_DEVICE);
+       areq->dst_len = req->ctx.rsa->key_sz;
+       if (req->dst_align) {
+               scatterwalk_map_and_copy(req->dst_align, areq->dst, 0,
+                                        areq->dst_len, 1);
+-              dma_free_coherent(dev, req->ctx.rsa->key_sz, req->dst_align,
+-                                req->out.rsa.enc.c);
+-      } else {
+-              dma_unmap_single(dev, req->out.rsa.enc.c, req->ctx.rsa->key_sz,
+-                               DMA_FROM_DEVICE);
++              kfree_sensitive(req->dst_align);
+       }
++      dma_unmap_single(dev, req->out.rsa.enc.c, req->ctx.rsa->key_sz,
++                       DMA_FROM_DEVICE);
++
+       dma_unmap_single(dev, req->phy_in, sizeof(struct qat_rsa_input_params),
+                        DMA_TO_DEVICE);
+       dma_unmap_single(dev, req->phy_out,
+@@ -664,6 +661,7 @@ static int qat_rsa_enc(struct akcipher_request *req)
+       struct qat_asym_request *qat_req =
+                       PTR_ALIGN(akcipher_request_ctx(req), 64);
+       struct icp_qat_fw_pke_request *msg = &qat_req->req;
++      u8 *vaddr;
+       int ret;
+       if (unlikely(!ctx->n || !ctx->e))
+@@ -701,40 +699,39 @@ static int qat_rsa_enc(struct akcipher_request *req)
+        */
+       if (sg_is_last(req->src) && req->src_len == ctx->key_sz) {
+               qat_req->src_align = NULL;
+-              qat_req->in.rsa.enc.m = dma_map_single(dev, sg_virt(req->src),
+-                                                 req->src_len, DMA_TO_DEVICE);
+-              if (unlikely(dma_mapping_error(dev, qat_req->in.rsa.enc.m)))
+-                      return ret;
+-
++              vaddr = sg_virt(req->src);
+       } else {
+               int shift = ctx->key_sz - req->src_len;
+-              qat_req->src_align = dma_alloc_coherent(dev, ctx->key_sz,
+-                                                      &qat_req->in.rsa.enc.m,
+-                                                      GFP_KERNEL);
++              qat_req->src_align = kzalloc(ctx->key_sz, GFP_KERNEL);
+               if (unlikely(!qat_req->src_align))
+                       return ret;
+               scatterwalk_map_and_copy(qat_req->src_align + shift, req->src,
+                                        0, req->src_len, 0);
++              vaddr = qat_req->src_align;
+       }
+-      if (sg_is_last(req->dst) && req->dst_len == ctx->key_sz) {
+-              qat_req->dst_align = NULL;
+-              qat_req->out.rsa.enc.c = dma_map_single(dev, sg_virt(req->dst),
+-                                                      req->dst_len,
+-                                                      DMA_FROM_DEVICE);
+-              if (unlikely(dma_mapping_error(dev, qat_req->out.rsa.enc.c)))
+-                      goto unmap_src;
++      qat_req->in.rsa.enc.m = dma_map_single(dev, vaddr, ctx->key_sz,
++                                             DMA_TO_DEVICE);
++      if (unlikely(dma_mapping_error(dev, qat_req->in.rsa.enc.m)))
++              goto unmap_src;
++      if (sg_is_last(req->dst) && req->dst_len == ctx->key_sz) {
++              qat_req->dst_align = NULL;
++              vaddr = sg_virt(req->dst);
+       } else {
+-              qat_req->dst_align = dma_alloc_coherent(dev, ctx->key_sz,
+-                                                      &qat_req->out.rsa.enc.c,
+-                                                      GFP_KERNEL);
++              qat_req->dst_align = kzalloc(ctx->key_sz, GFP_KERNEL);
+               if (unlikely(!qat_req->dst_align))
+                       goto unmap_src;
+-
++              vaddr = qat_req->dst_align;
+       }
++
++      qat_req->out.rsa.enc.c = dma_map_single(dev, vaddr, ctx->key_sz,
++                                              DMA_FROM_DEVICE);
++      if (unlikely(dma_mapping_error(dev, qat_req->out.rsa.enc.c)))
++              goto unmap_dst;
++
+       qat_req->in.rsa.in_tab[3] = 0;
+       qat_req->out.rsa.out_tab[1] = 0;
+       qat_req->phy_in = dma_map_single(dev, &qat_req->in.rsa.enc.m,
+@@ -772,21 +769,15 @@ static int qat_rsa_enc(struct akcipher_request *req)
+                                sizeof(struct qat_rsa_input_params),
+                                DMA_TO_DEVICE);
+ unmap_dst:
+-      if (qat_req->dst_align)
+-              dma_free_coherent(dev, ctx->key_sz, qat_req->dst_align,
+-                                qat_req->out.rsa.enc.c);
+-      else
+-              if (!dma_mapping_error(dev, qat_req->out.rsa.enc.c))
+-                      dma_unmap_single(dev, qat_req->out.rsa.enc.c,
+-                                       ctx->key_sz, DMA_FROM_DEVICE);
++      if (!dma_mapping_error(dev, qat_req->out.rsa.enc.c))
++              dma_unmap_single(dev, qat_req->out.rsa.enc.c,
++                               ctx->key_sz, DMA_FROM_DEVICE);
++      kfree_sensitive(qat_req->dst_align);
+ unmap_src:
+-      if (qat_req->src_align)
+-              dma_free_coherent(dev, ctx->key_sz, qat_req->src_align,
+-                                qat_req->in.rsa.enc.m);
+-      else
+-              if (!dma_mapping_error(dev, qat_req->in.rsa.enc.m))
+-                      dma_unmap_single(dev, qat_req->in.rsa.enc.m,
+-                                       ctx->key_sz, DMA_TO_DEVICE);
++      if (!dma_mapping_error(dev, qat_req->in.rsa.enc.m))
++              dma_unmap_single(dev, qat_req->in.rsa.enc.m, ctx->key_sz,
++                               DMA_TO_DEVICE);
++      kfree_sensitive(qat_req->src_align);
+       return ret;
+ }
+@@ -799,6 +790,7 @@ static int qat_rsa_dec(struct akcipher_request *req)
+       struct qat_asym_request *qat_req =
+                       PTR_ALIGN(akcipher_request_ctx(req), 64);
+       struct icp_qat_fw_pke_request *msg = &qat_req->req;
++      u8 *vaddr;
+       int ret;
+       if (unlikely(!ctx->n || !ctx->d))
+@@ -846,40 +838,37 @@ static int qat_rsa_dec(struct akcipher_request *req)
+        */
+       if (sg_is_last(req->src) && req->src_len == ctx->key_sz) {
+               qat_req->src_align = NULL;
+-              qat_req->in.rsa.dec.c = dma_map_single(dev, sg_virt(req->src),
+-                                                 req->dst_len, DMA_TO_DEVICE);
+-              if (unlikely(dma_mapping_error(dev, qat_req->in.rsa.dec.c)))
+-                      return ret;
+-
++              vaddr = sg_virt(req->src);
+       } else {
+               int shift = ctx->key_sz - req->src_len;
+-              qat_req->src_align = dma_alloc_coherent(dev, ctx->key_sz,
+-                                                      &qat_req->in.rsa.dec.c,
+-                                                      GFP_KERNEL);
++              qat_req->src_align = kzalloc(ctx->key_sz, GFP_KERNEL);
+               if (unlikely(!qat_req->src_align))
+                       return ret;
+               scatterwalk_map_and_copy(qat_req->src_align + shift, req->src,
+                                        0, req->src_len, 0);
++              vaddr = qat_req->src_align;
+       }
+-      if (sg_is_last(req->dst) && req->dst_len == ctx->key_sz) {
+-              qat_req->dst_align = NULL;
+-              qat_req->out.rsa.dec.m = dma_map_single(dev, sg_virt(req->dst),
+-                                                  req->dst_len,
+-                                                  DMA_FROM_DEVICE);
+-              if (unlikely(dma_mapping_error(dev, qat_req->out.rsa.dec.m)))
+-                      goto unmap_src;
++      qat_req->in.rsa.dec.c = dma_map_single(dev, vaddr, ctx->key_sz,
++                                             DMA_TO_DEVICE);
++      if (unlikely(dma_mapping_error(dev, qat_req->in.rsa.dec.c)))
++              goto unmap_src;
++      if (sg_is_last(req->dst) && req->dst_len == ctx->key_sz) {
++              qat_req->dst_align = NULL;
++              vaddr = sg_virt(req->dst);
+       } else {
+-              qat_req->dst_align = dma_alloc_coherent(dev, ctx->key_sz,
+-                                                      &qat_req->out.rsa.dec.m,
+-                                                      GFP_KERNEL);
++              qat_req->dst_align = kzalloc(ctx->key_sz, GFP_KERNEL);
+               if (unlikely(!qat_req->dst_align))
+                       goto unmap_src;
+-
++              vaddr = qat_req->dst_align;
+       }
++      qat_req->out.rsa.dec.m = dma_map_single(dev, vaddr, ctx->key_sz,
++                                              DMA_FROM_DEVICE);
++      if (unlikely(dma_mapping_error(dev, qat_req->out.rsa.dec.m)))
++              goto unmap_dst;
+       if (ctx->crt_mode)
+               qat_req->in.rsa.in_tab[6] = 0;
+@@ -925,21 +914,15 @@ static int qat_rsa_dec(struct akcipher_request *req)
+                                sizeof(struct qat_rsa_input_params),
+                                DMA_TO_DEVICE);
+ unmap_dst:
+-      if (qat_req->dst_align)
+-              dma_free_coherent(dev, ctx->key_sz, qat_req->dst_align,
+-                                qat_req->out.rsa.dec.m);
+-      else
+-              if (!dma_mapping_error(dev, qat_req->out.rsa.dec.m))
+-                      dma_unmap_single(dev, qat_req->out.rsa.dec.m,
+-                                       ctx->key_sz, DMA_FROM_DEVICE);
++      if (!dma_mapping_error(dev, qat_req->out.rsa.dec.m))
++              dma_unmap_single(dev, qat_req->out.rsa.dec.m,
++                               ctx->key_sz, DMA_FROM_DEVICE);
++      kfree_sensitive(qat_req->dst_align);
+ unmap_src:
+-      if (qat_req->src_align)
+-              dma_free_coherent(dev, ctx->key_sz, qat_req->src_align,
+-                                qat_req->in.rsa.dec.c);
+-      else
+-              if (!dma_mapping_error(dev, qat_req->in.rsa.dec.c))
+-                      dma_unmap_single(dev, qat_req->in.rsa.dec.c,
+-                                       ctx->key_sz, DMA_TO_DEVICE);
++      if (!dma_mapping_error(dev, qat_req->in.rsa.dec.c))
++              dma_unmap_single(dev, qat_req->in.rsa.dec.c, ctx->key_sz,
++                               DMA_TO_DEVICE);
++      kfree_sensitive(qat_req->src_align);
+       return ret;
+ }
+-- 
+2.35.1
+
diff --git a/queue-5.15/crypto-qat-set-to-zero-dh-parameters-before-free.patch b/queue-5.15/crypto-qat-set-to-zero-dh-parameters-before-free.patch
new file mode 100644 (file)
index 0000000..986e087
--- /dev/null
@@ -0,0 +1,51 @@
+From e0a264c24ee61b90290dd986462452ef7b78cc59 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 May 2022 14:19:27 +0100
+Subject: crypto: qat - set to zero DH parameters before free
+
+From: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+
+[ Upstream commit 1731160ff7c7bbb11bb1aacb14dd25e18d522779 ]
+
+Set to zero the context buffers containing the DH key before they are
+freed.
+This is a defense in depth measure that avoids keys to be recovered from
+memory in case the system is compromised between the free of the buffer
+and when that area of memory (containing keys) gets overwritten.
+
+Cc: stable@vger.kernel.org
+Fixes: c9839143ebbf ("crypto: qat - Add DH support")
+Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+Reviewed-by: Adam Guerin <adam.guerin@intel.com>
+Reviewed-by: Wojciech Ziemba <wojciech.ziemba@intel.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/crypto/qat/qat_common/qat_asym_algs.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/crypto/qat/qat_common/qat_asym_algs.c b/drivers/crypto/qat/qat_common/qat_asym_algs.c
+index b0b78445418b..5633f9df3b6f 100644
+--- a/drivers/crypto/qat/qat_common/qat_asym_algs.c
++++ b/drivers/crypto/qat/qat_common/qat_asym_algs.c
+@@ -420,14 +420,17 @@ static int qat_dh_set_params(struct qat_dh_ctx *ctx, struct dh *params)
+ static void qat_dh_clear_ctx(struct device *dev, struct qat_dh_ctx *ctx)
+ {
+       if (ctx->g) {
++              memset(ctx->g, 0, ctx->p_size);
+               dma_free_coherent(dev, ctx->p_size, ctx->g, ctx->dma_g);
+               ctx->g = NULL;
+       }
+       if (ctx->xa) {
++              memset(ctx->xa, 0, ctx->p_size);
+               dma_free_coherent(dev, ctx->p_size, ctx->xa, ctx->dma_xa);
+               ctx->xa = NULL;
+       }
+       if (ctx->p) {
++              memset(ctx->p, 0, ctx->p_size);
+               dma_free_coherent(dev, ctx->p_size, ctx->p, ctx->dma_p);
+               ctx->p = NULL;
+       }
+-- 
+2.35.1
+
diff --git a/queue-5.15/crypto-qat-use-pre-allocated-buffers-in-datapath.patch b/queue-5.15/crypto-qat-use-pre-allocated-buffers-in-datapath.patch
new file mode 100644 (file)
index 0000000..7bac764
--- /dev/null
@@ -0,0 +1,207 @@
+From ff874c620d2dd9bf3de09a38974e33988757a202 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 May 2022 14:34:08 +0100
+Subject: crypto: qat - use pre-allocated buffers in datapath
+
+From: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+
+[ Upstream commit e0831e7af4e03f2715de102e18e9179ec0a81562 ]
+
+In order to do DMAs, the QAT device requires that the scatterlist
+structures are mapped and translated into a format that the firmware can
+understand. This is defined as the composition of a scatter gather list
+(SGL) descriptor header, the struct qat_alg_buf_list, plus a variable
+number of flat buffer descriptors, the struct qat_alg_buf.
+
+The allocation and mapping of these data structures is done each time a
+request is received from the skcipher and aead APIs.
+In an OOM situation, this behaviour might lead to a dead-lock if an
+allocation fails.
+
+Based on the conversation in [1], increase the size of the aead and
+skcipher request contexts to include an SGL descriptor that can handle
+a maximum of 4 flat buffers.
+If requests exceed 4 entries buffers, memory is allocated dynamically.
+
+[1] https://lore.kernel.org/linux-crypto/20200722072932.GA27544@gondor.apana.org.au/
+
+Cc: stable@vger.kernel.org
+Fixes: d370cec32194 ("crypto: qat - Intel(R) QAT crypto interface")
+Reported-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+Reviewed-by: Marco Chiappero <marco.chiappero@intel.com>
+Reviewed-by: Wojciech Ziemba <wojciech.ziemba@intel.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/crypto/qat/qat_common/qat_algs.c   | 64 +++++++++++++---------
+ drivers/crypto/qat/qat_common/qat_crypto.h | 24 ++++++++
+ 2 files changed, 61 insertions(+), 27 deletions(-)
+
+diff --git a/drivers/crypto/qat/qat_common/qat_algs.c b/drivers/crypto/qat/qat_common/qat_algs.c
+index f998ed58457c..ec635fe44c1f 100644
+--- a/drivers/crypto/qat/qat_common/qat_algs.c
++++ b/drivers/crypto/qat/qat_common/qat_algs.c
+@@ -46,19 +46,6 @@
+ static DEFINE_MUTEX(algs_lock);
+ static unsigned int active_devs;
+-struct qat_alg_buf {
+-      u32 len;
+-      u32 resrvd;
+-      u64 addr;
+-} __packed;
+-
+-struct qat_alg_buf_list {
+-      u64 resrvd;
+-      u32 num_bufs;
+-      u32 num_mapped_bufs;
+-      struct qat_alg_buf bufers[];
+-} __packed __aligned(64);
+-
+ /* Common content descriptor */
+ struct qat_alg_cd {
+       union {
+@@ -693,7 +680,10 @@ static void qat_alg_free_bufl(struct qat_crypto_instance *inst,
+                                bl->bufers[i].len, DMA_BIDIRECTIONAL);
+       dma_unmap_single(dev, blp, sz, DMA_TO_DEVICE);
+-      kfree(bl);
++
++      if (!qat_req->buf.sgl_src_valid)
++              kfree(bl);
++
+       if (blp != blpout) {
+               /* If out of place operation dma unmap only data */
+               int bufless = blout->num_bufs - blout->num_mapped_bufs;
+@@ -704,7 +694,9 @@ static void qat_alg_free_bufl(struct qat_crypto_instance *inst,
+                                        DMA_BIDIRECTIONAL);
+               }
+               dma_unmap_single(dev, blpout, sz_out, DMA_TO_DEVICE);
+-              kfree(blout);
++
++              if (!qat_req->buf.sgl_dst_valid)
++                      kfree(blout);
+       }
+ }
+@@ -721,15 +713,24 @@ static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst,
+       dma_addr_t blp = DMA_MAPPING_ERROR;
+       dma_addr_t bloutp = DMA_MAPPING_ERROR;
+       struct scatterlist *sg;
+-      size_t sz_out, sz = struct_size(bufl, bufers, n + 1);
++      size_t sz_out, sz = struct_size(bufl, bufers, n);
++      int node = dev_to_node(&GET_DEV(inst->accel_dev));
+       if (unlikely(!n))
+               return -EINVAL;
+-      bufl = kzalloc_node(sz, GFP_ATOMIC,
+-                          dev_to_node(&GET_DEV(inst->accel_dev)));
+-      if (unlikely(!bufl))
+-              return -ENOMEM;
++      qat_req->buf.sgl_src_valid = false;
++      qat_req->buf.sgl_dst_valid = false;
++
++      if (n > QAT_MAX_BUFF_DESC) {
++              bufl = kzalloc_node(sz, GFP_ATOMIC, node);
++              if (unlikely(!bufl))
++                      return -ENOMEM;
++      } else {
++              bufl = &qat_req->buf.sgl_src.sgl_hdr;
++              memset(bufl, 0, sizeof(struct qat_alg_buf_list));
++              qat_req->buf.sgl_src_valid = true;
++      }
+       for_each_sg(sgl, sg, n, i)
+               bufl->bufers[i].addr = DMA_MAPPING_ERROR;
+@@ -760,12 +761,18 @@ static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst,
+               struct qat_alg_buf *bufers;
+               n = sg_nents(sglout);
+-              sz_out = struct_size(buflout, bufers, n + 1);
++              sz_out = struct_size(buflout, bufers, n);
+               sg_nctr = 0;
+-              buflout = kzalloc_node(sz_out, GFP_ATOMIC,
+-                                     dev_to_node(&GET_DEV(inst->accel_dev)));
+-              if (unlikely(!buflout))
+-                      goto err_in;
++
++              if (n > QAT_MAX_BUFF_DESC) {
++                      buflout = kzalloc_node(sz_out, GFP_ATOMIC, node);
++                      if (unlikely(!buflout))
++                              goto err_in;
++              } else {
++                      buflout = &qat_req->buf.sgl_dst.sgl_hdr;
++                      memset(buflout, 0, sizeof(struct qat_alg_buf_list));
++                      qat_req->buf.sgl_dst_valid = true;
++              }
+               bufers = buflout->bufers;
+               for_each_sg(sglout, sg, n, i)
+@@ -810,7 +817,9 @@ static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst,
+                       dma_unmap_single(dev, buflout->bufers[i].addr,
+                                        buflout->bufers[i].len,
+                                        DMA_BIDIRECTIONAL);
+-      kfree(buflout);
++
++      if (!qat_req->buf.sgl_dst_valid)
++              kfree(buflout);
+ err_in:
+       if (!dma_mapping_error(dev, blp))
+@@ -823,7 +832,8 @@ static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst,
+                                        bufl->bufers[i].len,
+                                        DMA_BIDIRECTIONAL);
+-      kfree(bufl);
++      if (!qat_req->buf.sgl_src_valid)
++              kfree(bufl);
+       dev_err(dev, "Failed to map buf for dma\n");
+       return -ENOMEM;
+diff --git a/drivers/crypto/qat/qat_common/qat_crypto.h b/drivers/crypto/qat/qat_common/qat_crypto.h
+index b6a4c95ae003..0928f159ea99 100644
+--- a/drivers/crypto/qat/qat_common/qat_crypto.h
++++ b/drivers/crypto/qat/qat_common/qat_crypto.h
+@@ -21,6 +21,26 @@ struct qat_crypto_instance {
+       atomic_t refctr;
+ };
++#define QAT_MAX_BUFF_DESC     4
++
++struct qat_alg_buf {
++      u32 len;
++      u32 resrvd;
++      u64 addr;
++} __packed;
++
++struct qat_alg_buf_list {
++      u64 resrvd;
++      u32 num_bufs;
++      u32 num_mapped_bufs;
++      struct qat_alg_buf bufers[];
++} __packed;
++
++struct qat_alg_fixed_buf_list {
++      struct qat_alg_buf_list sgl_hdr;
++      struct qat_alg_buf descriptors[QAT_MAX_BUFF_DESC];
++} __packed __aligned(64);
++
+ struct qat_crypto_request_buffs {
+       struct qat_alg_buf_list *bl;
+       dma_addr_t blp;
+@@ -28,6 +48,10 @@ struct qat_crypto_request_buffs {
+       dma_addr_t bloutp;
+       size_t sz;
+       size_t sz_out;
++      bool sgl_src_valid;
++      bool sgl_dst_valid;
++      struct qat_alg_fixed_buf_list sgl_src;
++      struct qat_alg_fixed_buf_list sgl_dst;
+ };
+ struct qat_crypto_request;
+-- 
+2.35.1
+
diff --git a/queue-5.15/dlm-fix-pending-remove-if-msg-allocation-fails.patch b/queue-5.15/dlm-fix-pending-remove-if-msg-allocation-fails.patch
new file mode 100644 (file)
index 0000000..16a77f7
--- /dev/null
@@ -0,0 +1,47 @@
+From 95c49d163f77537d678276bbfd2c145e8d3c0e1a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Apr 2022 13:34:16 -0400
+Subject: dlm: fix pending remove if msg allocation fails
+
+From: Alexander Aring <aahringo@redhat.com>
+
+[ Upstream commit ba58995909b5098ca4003af65b0ccd5a8d13dd25 ]
+
+This patch unsets ls_remove_len and ls_remove_name if a message
+allocation of a remove messages fails. In this case we never send a
+remove message out but set the per ls ls_remove_len ls_remove_name
+variable for a pending remove. Unset those variable should indicate
+possible waiters in wait_pending_remove() that no pending remove is
+going on at this moment.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Alexander Aring <aahringo@redhat.com>
+Signed-off-by: David Teigland <teigland@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/dlm/lock.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c
+index bb9e85e8819c..9f93496d2cc9 100644
+--- a/fs/dlm/lock.c
++++ b/fs/dlm/lock.c
+@@ -4065,13 +4065,14 @@ static void send_repeat_remove(struct dlm_ls *ls, char *ms_name, int len)
+       rv = _create_message(ls, sizeof(struct dlm_message) + len,
+                            dir_nodeid, DLM_MSG_REMOVE, &ms, &mh);
+       if (rv)
+-              return;
++              goto out;
+       memcpy(ms->m_extra, name, len);
+       ms->m_hash = hash;
+       send_message(mh, ms);
++out:
+       spin_lock(&ls->ls_remove_spin);
+       ls->ls_remove_len = 0;
+       memset(ls->ls_remove_name, 0, DLM_RESNAME_MAXLEN);
+-- 
+2.35.1
+
diff --git a/queue-5.15/exfat-fix-referencing-wrong-parent-directory-informa.patch b/queue-5.15/exfat-fix-referencing-wrong-parent-directory-informa.patch
new file mode 100644 (file)
index 0000000..e23c13c
--- /dev/null
@@ -0,0 +1,104 @@
+From 6d860fc831dd23c2f8025bce767755709d1dff57 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Apr 2022 11:58:06 +0900
+Subject: exfat: fix referencing wrong parent directory information after
+ renaming
+
+From: Yuezhang Mo <Yuezhang.Mo@sony.com>
+
+[ Upstream commit d8dad2588addd1d861ce19e7df3b702330f0c7e3 ]
+
+During renaming, the parent directory information maybe
+updated. But the file/directory still references to the
+old parent directory information.
+
+This bug will cause 2 problems.
+
+(1) The renamed file can not be written.
+
+    [10768.175172] exFAT-fs (sda1): error, failed to bmap (inode : 7afd50e4 iblock : 0, err : -5)
+    [10768.184285] exFAT-fs (sda1): Filesystem has been set read-only
+    ash: write error: Input/output error
+
+(2) Some dentries of the renamed file/directory are not set
+    to deleted after removing the file/directory.
+
+exfat_update_parent_info() is a workaround for the wrong parent
+directory information being used after renaming. Now that bug is
+fixed, this is no longer needed, so remove it.
+
+Fixes: 5f2aa075070c ("exfat: add inode operations")
+Cc: stable@vger.kernel.org # v5.7+
+Signed-off-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
+Reviewed-by: Andy Wu <Andy.Wu@sony.com>
+Reviewed-by: Aoyama Wataru <wataru.aoyama@sony.com>
+Reviewed-by: Daniel Palmer <daniel.palmer@sony.com>
+Reviewed-by: Sungjong Seo <sj1557.seo@samsung.com>
+Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/exfat/namei.c | 27 +--------------------------
+ 1 file changed, 1 insertion(+), 26 deletions(-)
+
+diff --git a/fs/exfat/namei.c b/fs/exfat/namei.c
+index 9d8ada781250..939737ba520d 100644
+--- a/fs/exfat/namei.c
++++ b/fs/exfat/namei.c
+@@ -1069,6 +1069,7 @@ static int exfat_rename_file(struct inode *inode, struct exfat_chain *p_dir,
+               exfat_remove_entries(inode, p_dir, oldentry, 0,
+                       num_old_entries);
++              ei->dir = *p_dir;
+               ei->entry = newentry;
+       } else {
+               if (exfat_get_entry_type(epold) == TYPE_FILE) {
+@@ -1159,28 +1160,6 @@ static int exfat_move_file(struct inode *inode, struct exfat_chain *p_olddir,
+       return 0;
+ }
+-static void exfat_update_parent_info(struct exfat_inode_info *ei,
+-              struct inode *parent_inode)
+-{
+-      struct exfat_sb_info *sbi = EXFAT_SB(parent_inode->i_sb);
+-      struct exfat_inode_info *parent_ei = EXFAT_I(parent_inode);
+-      loff_t parent_isize = i_size_read(parent_inode);
+-
+-      /*
+-       * the problem that struct exfat_inode_info caches wrong parent info.
+-       *
+-       * because of flag-mismatch of ei->dir,
+-       * there is abnormal traversing cluster chain.
+-       */
+-      if (unlikely(parent_ei->flags != ei->dir.flags ||
+-                   parent_isize != EXFAT_CLU_TO_B(ei->dir.size, sbi) ||
+-                   parent_ei->start_clu != ei->dir.dir)) {
+-              exfat_chain_set(&ei->dir, parent_ei->start_clu,
+-                      EXFAT_B_TO_CLU_ROUND_UP(parent_isize, sbi),
+-                      parent_ei->flags);
+-      }
+-}
+-
+ /* rename or move a old file into a new file */
+ static int __exfat_rename(struct inode *old_parent_inode,
+               struct exfat_inode_info *ei, struct inode *new_parent_inode,
+@@ -1211,8 +1190,6 @@ static int __exfat_rename(struct inode *old_parent_inode,
+               return -ENOENT;
+       }
+-      exfat_update_parent_info(ei, old_parent_inode);
+-
+       exfat_chain_dup(&olddir, &ei->dir);
+       dentry = ei->entry;
+@@ -1233,8 +1210,6 @@ static int __exfat_rename(struct inode *old_parent_inode,
+                       goto out;
+               }
+-              exfat_update_parent_info(new_ei, new_parent_inode);
+-
+               p_dir = &(new_ei->dir);
+               new_entry = new_ei->entry;
+               ep = exfat_get_dentry(sb, p_dir, new_entry, &new_bh, NULL);
+-- 
+2.35.1
+
diff --git a/queue-5.15/iwlwifi-fw-uefi-add-missing-include-guards.patch b/queue-5.15/iwlwifi-fw-uefi-add-missing-include-guards.patch
new file mode 100644 (file)
index 0000000..fb79235
--- /dev/null
@@ -0,0 +1,45 @@
+From 239baa4cd3eda4d636427c9978b24f26c8a07b64 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 24 Oct 2021 18:20:26 +0300
+Subject: iwlwifi: fw: uefi: add missing include guards
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit 91000fdf82195b66350b4f88413c2e8b5f94d994 ]
+
+We still don't use #pragma once in the kernel, but even if
+we did it'd be missing. Add the missing include guards.
+
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Fixes: 84c3c9952afb ("iwlwifi: move UEFI code to a separate file")
+Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
+Link: https://lore.kernel.org/r/iwlwifi.20211024181719.7fc9988ed49b.I87e300fab664047581e51fb9b02744c75320d08c@changeid
+Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/intel/iwlwifi/fw/uefi.h | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h
+index 45d0b36d79b5..d552c656ac9f 100644
+--- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h
++++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h
+@@ -2,7 +2,8 @@
+ /*
+  * Copyright(c) 2021 Intel Corporation
+  */
+-
++#ifndef __iwl_fw_uefi__
++#define __iwl_fw_uefi__
+ #define IWL_UEFI_OEM_PNVM_NAME                L"UefiCnvWlanOemSignedPnvm"
+ #define IWL_UEFI_REDUCED_POWER_NAME   L"UefiCnvWlanReducedPower"
+@@ -40,3 +41,5 @@ void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len)
+       return ERR_PTR(-EOPNOTSUPP);
+ }
+ #endif /* CONFIG_EFI */
++
++#endif /* __iwl_fw_uefi__ */
+-- 
+2.35.1
+
diff --git a/queue-5.15/kvm-x86-use-__try_cmpxchg_user-to-emulate-atomic-acc.patch b/queue-5.15/kvm-x86-use-__try_cmpxchg_user-to-emulate-atomic-acc.patch
new file mode 100644 (file)
index 0000000..617517a
--- /dev/null
@@ -0,0 +1,108 @@
+From 51f20d6e54986ad0ccb68306cba496699b465007 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 2 Feb 2022 00:49:44 +0000
+Subject: KVM: x86: Use __try_cmpxchg_user() to emulate atomic accesses
+
+From: Sean Christopherson <seanjc@google.com>
+
+[ Upstream commit 1c2361f667f3648855ceae25f1332c18413fdb9f ]
+
+Use the recently introduce __try_cmpxchg_user() to emulate atomic guest
+accesses via the associated userspace address instead of mapping the
+backing pfn into kernel address space.  Using kvm_vcpu_map() is unsafe as
+it does not coordinate with KVM's mmu_notifier to ensure the hva=>pfn
+translation isn't changed/unmapped in the memremap() path, i.e. when
+there's no struct page and thus no elevated refcount.
+
+Fixes: 42e35f8072c3 ("KVM/X86: Use kvm_vcpu_map in emulator_cmpxchg_emulated")
+Cc: stable@vger.kernel.org
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Message-Id: <20220202004945.2540433-5-seanjc@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/x86.c | 35 ++++++++++++++---------------------
+ 1 file changed, 14 insertions(+), 21 deletions(-)
+
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index 4525d0b25a43..f9802ceed60a 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -6894,15 +6894,8 @@ static int emulator_write_emulated(struct x86_emulate_ctxt *ctxt,
+                                  exception, &write_emultor);
+ }
+-#define CMPXCHG_TYPE(t, ptr, old, new) \
+-      (cmpxchg((t *)(ptr), *(t *)(old), *(t *)(new)) == *(t *)(old))
+-
+-#ifdef CONFIG_X86_64
+-#  define CMPXCHG64(ptr, old, new) CMPXCHG_TYPE(u64, ptr, old, new)
+-#else
+-#  define CMPXCHG64(ptr, old, new) \
+-      (cmpxchg64((u64 *)(ptr), *(u64 *)(old), *(u64 *)(new)) == *(u64 *)(old))
+-#endif
++#define emulator_try_cmpxchg_user(t, ptr, old, new) \
++      (__try_cmpxchg_user((t __user *)(ptr), (t *)(old), *(t *)(new), efault ## t))
+ static int emulator_cmpxchg_emulated(struct x86_emulate_ctxt *ctxt,
+                                    unsigned long addr,
+@@ -6911,12 +6904,11 @@ static int emulator_cmpxchg_emulated(struct x86_emulate_ctxt *ctxt,
+                                    unsigned int bytes,
+                                    struct x86_exception *exception)
+ {
+-      struct kvm_host_map map;
+       struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
+       u64 page_line_mask;
++      unsigned long hva;
+       gpa_t gpa;
+-      char *kaddr;
+-      bool exchanged;
++      int r;
+       /* guests cmpxchg8b have to be emulated atomically */
+       if (bytes > 8 || (bytes & (bytes - 1)))
+@@ -6940,31 +6932,32 @@ static int emulator_cmpxchg_emulated(struct x86_emulate_ctxt *ctxt,
+       if (((gpa + bytes - 1) & page_line_mask) != (gpa & page_line_mask))
+               goto emul_write;
+-      if (kvm_vcpu_map(vcpu, gpa_to_gfn(gpa), &map))
++      hva = kvm_vcpu_gfn_to_hva(vcpu, gpa_to_gfn(gpa));
++      if (kvm_is_error_hva(addr))
+               goto emul_write;
+-      kaddr = map.hva + offset_in_page(gpa);
++      hva += offset_in_page(gpa);
+       switch (bytes) {
+       case 1:
+-              exchanged = CMPXCHG_TYPE(u8, kaddr, old, new);
++              r = emulator_try_cmpxchg_user(u8, hva, old, new);
+               break;
+       case 2:
+-              exchanged = CMPXCHG_TYPE(u16, kaddr, old, new);
++              r = emulator_try_cmpxchg_user(u16, hva, old, new);
+               break;
+       case 4:
+-              exchanged = CMPXCHG_TYPE(u32, kaddr, old, new);
++              r = emulator_try_cmpxchg_user(u32, hva, old, new);
+               break;
+       case 8:
+-              exchanged = CMPXCHG64(kaddr, old, new);
++              r = emulator_try_cmpxchg_user(u64, hva, old, new);
+               break;
+       default:
+               BUG();
+       }
+-      kvm_vcpu_unmap(vcpu, &map, true);
+-
+-      if (!exchanged)
++      if (r < 0)
++              goto emul_write;
++      if (r)
+               return X86EMUL_CMPXCHG_FAILED;
+       kvm_page_track_write(vcpu, gpa, new, bytes);
+-- 
+2.35.1
+
diff --git a/queue-5.15/mt76-fix-use-after-free-by-removing-a-non-rcu-wcid-p.patch b/queue-5.15/mt76-fix-use-after-free-by-removing-a-non-rcu-wcid-p.patch
new file mode 100644 (file)
index 0000000..eccff20
--- /dev/null
@@ -0,0 +1,269 @@
+From afddbf32fbd8d90ed32596deb1d0060dd59bb455 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 25 Mar 2022 22:01:43 +0100
+Subject: mt76: fix use-after-free by removing a non-RCU wcid pointer
+
+From: Felix Fietkau <nbd@nbd.name>
+
+[ Upstream commit 51fb1278aa57ae0fc54adaa786e1965362bed4fb ]
+
+Fixes an issue caught by KASAN about use-after-free in mt76_txq_schedule
+by protecting mtxq->wcid with rcu_lock between mt76_txq_schedule and
+sta_info_[alloc, free].
+
+[18853.876689] ==================================================================
+[18853.876751] BUG: KASAN: use-after-free in mt76_txq_schedule+0x204/0xaf8 [mt76]
+[18853.876773] Read of size 8 at addr ffffffaf989a2138 by task mt76-tx phy0/883
+[18853.876786]
+[18853.876810] CPU: 5 PID: 883 Comm: mt76-tx phy0 Not tainted 5.10.100-fix-510-56778d365941-kasan #5 0b01fbbcf41a530f52043508fec2e31a4215
+
+[18853.876840] Call trace:
+[18853.876861]  dump_backtrace+0x0/0x3ec
+[18853.876878]  show_stack+0x20/0x2c
+[18853.876899]  dump_stack+0x11c/0x1ac
+[18853.876918]  print_address_description+0x74/0x514
+[18853.876934]  kasan_report+0x134/0x174
+[18853.876948]  __asan_report_load8_noabort+0x44/0x50
+[18853.876976]  mt76_txq_schedule+0x204/0xaf8 [mt76 074e03e4640e97fe7405ee1fab547b81c4fa45d2]
+[18853.877002]  mt76_txq_schedule_all+0x2c/0x48 [mt76 074e03e4640e97fe7405ee1fab547b81c4fa45d2]
+[18853.877030]  mt7921_tx_worker+0xa0/0x1cc [mt7921_common f0875ebac9d7b4754e1010549e7db50fbd90a047]
+[18853.877054]  __mt76_worker_fn+0x190/0x22c [mt76 074e03e4640e97fe7405ee1fab547b81c4fa45d2]
+[18853.877071]  kthread+0x2f8/0x3b8
+[18853.877087]  ret_from_fork+0x10/0x30
+[18853.877098]
+[18853.877112] Allocated by task 941:
+[18853.877131]  kasan_save_stack+0x38/0x68
+[18853.877147]  __kasan_kmalloc+0xd4/0xfc
+[18853.877163]  kasan_kmalloc+0x10/0x1c
+[18853.877177]  __kmalloc+0x264/0x3c4
+[18853.877294]  sta_info_alloc+0x460/0xf88 [mac80211]
+[18853.877410]  ieee80211_prep_connection+0x204/0x1ee0 [mac80211]
+[18853.877523]  ieee80211_mgd_auth+0x6c4/0xa4c [mac80211]
+[18853.877635]  ieee80211_auth+0x20/0x2c [mac80211]
+[18853.877733]  rdev_auth+0x7c/0x438 [cfg80211]
+[18853.877826]  cfg80211_mlme_auth+0x26c/0x390 [cfg80211]
+[18853.877919]  nl80211_authenticate+0x6d4/0x904 [cfg80211]
+[18853.877938]  genl_rcv_msg+0x748/0x93c
+[18853.877954]  netlink_rcv_skb+0x160/0x2a8
+[18853.877969]  genl_rcv+0x3c/0x54
+[18853.877985]  netlink_unicast_kernel+0x104/0x1ec
+[18853.877999]  netlink_unicast+0x178/0x268
+[18853.878015]  netlink_sendmsg+0x3cc/0x5f0
+[18853.878030]  sock_sendmsg+0xb4/0xd8
+[18853.878043]  ____sys_sendmsg+0x2f8/0x53c
+[18853.878058]  ___sys_sendmsg+0xe8/0x150
+[18853.878071]  __sys_sendmsg+0xc4/0x1f4
+[18853.878087]  __arm64_compat_sys_sendmsg+0x88/0x9c
+[18853.878101]  el0_svc_common+0x1b4/0x390
+[18853.878115]  do_el0_svc_compat+0x8c/0xdc
+[18853.878131]  el0_svc_compat+0x10/0x1c
+[18853.878146]  el0_sync_compat_handler+0xa8/0xcc
+[18853.878161]  el0_sync_compat+0x188/0x1c0
+[18853.878171]
+[18853.878183] Freed by task 10927:
+[18853.878200]  kasan_save_stack+0x38/0x68
+[18853.878215]  kasan_set_track+0x28/0x3c
+[18853.878228]  kasan_set_free_info+0x24/0x48
+[18853.878244]  __kasan_slab_free+0x11c/0x154
+[18853.878259]  kasan_slab_free+0x14/0x24
+[18853.878273]  slab_free_freelist_hook+0xac/0x1b0
+[18853.878287]  kfree+0x104/0x390
+[18853.878402]  sta_info_free+0x198/0x210 [mac80211]
+[18853.878515]  __sta_info_destroy_part2+0x230/0x2d4 [mac80211]
+[18853.878628]  __sta_info_flush+0x300/0x37c [mac80211]
+[18853.878740]  ieee80211_set_disassoc+0x2cc/0xa7c [mac80211]
+[18853.878851]  ieee80211_mgd_deauth+0x4a4/0x10a0 [mac80211]
+[18853.878962]  ieee80211_deauth+0x20/0x2c [mac80211]
+[18853.879057]  rdev_deauth+0x7c/0x438 [cfg80211]
+[18853.879150]  cfg80211_mlme_deauth+0x274/0x414 [cfg80211]
+[18853.879243]  cfg80211_mlme_down+0xe4/0x118 [cfg80211]
+[18853.879335]  cfg80211_disconnect+0x218/0x2d8 [cfg80211]
+[18853.879427]  __cfg80211_leave+0x17c/0x240 [cfg80211]
+[18853.879519]  cfg80211_leave+0x3c/0x58 [cfg80211]
+[18853.879611]  wiphy_suspend+0xdc/0x200 [cfg80211]
+[18853.879628]  dpm_run_callback+0x58/0x408
+[18853.879642]  __device_suspend+0x4cc/0x864
+[18853.879658]  async_suspend+0x34/0xf4
+[18853.879673]  async_run_entry_fn+0xe0/0x37c
+[18853.879689]  process_one_work+0x508/0xb98
+[18853.879702]  worker_thread+0x7f4/0xcd4
+[18853.879717]  kthread+0x2f8/0x3b8
+[18853.879731]  ret_from_fork+0x10/0x30
+[18853.879741]
+[18853.879757] The buggy address belongs to the object at ffffffaf989a2000
+[18853.879757]  which belongs to the cache kmalloc-8k of size 8192
+[18853.879774] The buggy address is located 312 bytes inside of
+[18853.879774]  8192-byte region [ffffffaf989a2000, ffffffaf989a4000)
+[18853.879787] The buggy address belongs to the page:
+[18853.879807] page:000000004bda2a59 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x1d89a0
+[18853.879823] head:000000004bda2a59 order:3 compound_mapcount:0 compound_pincount:0
+[18853.879839] flags: 0x8000000000010200(slab|head)
+[18853.879857] raw: 8000000000010200 ffffffffbc89e208 ffffffffb7fb5208 ffffffaec000cc80
+[18853.879873] raw: 0000000000000000 0000000000010001 00000001ffffffff 0000000000000000
+[18853.879885] page dumped because: kasan: bad access detected
+[18853.879896]
+[18853.879907] Memory state around the buggy address:
+[18853.879922]  ffffffaf989a2000: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+[18853.879935]  ffffffaf989a2080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+[18853.879948] >ffffffaf989a2100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+[18853.879961]                                         ^
+[18853.879973]  ffffffaf989a2180: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+[18853.879986]  ffffffaf989a2200: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+[18853.879998] ==================================================================
+
+Cc: stable@vger.kernel.org
+Reported-by: Sean Wang <sean.wang@mediatek.com>
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/mediatek/mt76/mac80211.c     | 2 +-
+ drivers/net/wireless/mediatek/mt76/mt76.h         | 2 +-
+ drivers/net/wireless/mediatek/mt76/mt7603/main.c  | 2 +-
+ drivers/net/wireless/mediatek/mt76/mt7615/main.c  | 2 +-
+ drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 4 +++-
+ drivers/net/wireless/mediatek/mt76/mt7915/main.c  | 2 +-
+ drivers/net/wireless/mediatek/mt76/mt7921/main.c  | 2 +-
+ drivers/net/wireless/mediatek/mt76/tx.c           | 9 ++++-----
+ 8 files changed, 13 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c
+index d03aedc3286b..029599d68ca7 100644
+--- a/drivers/net/wireless/mediatek/mt76/mac80211.c
++++ b/drivers/net/wireless/mediatek/mt76/mac80211.c
+@@ -1100,7 +1100,7 @@ mt76_sta_add(struct mt76_dev *dev, struct ieee80211_vif *vif,
+                       continue;
+               mtxq = (struct mt76_txq *)sta->txq[i]->drv_priv;
+-              mtxq->wcid = wcid;
++              mtxq->wcid = wcid->idx;
+       }
+       ewma_signal_init(&wcid->rssi);
+diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
+index 6e4d69715927..d1f00706d41e 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt76.h
++++ b/drivers/net/wireless/mediatek/mt76/mt76.h
+@@ -263,7 +263,7 @@ struct mt76_wcid {
+ };
+ struct mt76_txq {
+-      struct mt76_wcid *wcid;
++      u16 wcid;
+       u16 agg_ssn;
+       bool send_bar;
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c
+index 7f52a4a11cea..0b7b87b4cc21 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c
+@@ -74,7 +74,7 @@ mt7603_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+       mt7603_wtbl_init(dev, idx, mvif->idx, bc_addr);
+       mtxq = (struct mt76_txq *)vif->txq->drv_priv;
+-      mtxq->wcid = &mvif->sta.wcid;
++      mtxq->wcid = idx;
+       rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid);
+ out:
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
+index 60a41d082961..7c52a4d85cea 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
+@@ -235,7 +235,7 @@ static int mt7615_add_interface(struct ieee80211_hw *hw,
+       rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid);
+       if (vif->txq) {
+               mtxq = (struct mt76_txq *)vif->txq->drv_priv;
+-              mtxq->wcid = &mvif->sta.wcid;
++              mtxq->wcid = idx;
+       }
+       ret = mt7615_mcu_add_dev_info(phy, vif, true);
+diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
+index ccdbab341271..db7a4ffcad55 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
++++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
+@@ -288,7 +288,8 @@ mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif,
+       mvif->group_wcid.idx = MT_VIF_WCID(idx);
+       mvif->group_wcid.hw_key_idx = -1;
+       mtxq = (struct mt76_txq *)vif->txq->drv_priv;
+-      mtxq->wcid = &mvif->group_wcid;
++      rcu_assign_pointer(dev->mt76.wcid[MT_VIF_WCID(idx)], &mvif->group_wcid);
++      mtxq->wcid = MT_VIF_WCID(idx);
+ }
+ int
+@@ -341,6 +342,7 @@ void mt76x02_remove_interface(struct ieee80211_hw *hw,
+       struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv;
+       dev->mt76.vif_mask &= ~BIT(mvif->idx);
++      rcu_assign_pointer(dev->mt76.wcid[mvif->group_wcid.idx], NULL);
+ }
+ EXPORT_SYMBOL_GPL(mt76x02_remove_interface);
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
+index c25f8da590dd..6aca470e2401 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
+@@ -243,7 +243,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
+       rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid);
+       if (vif->txq) {
+               mtxq = (struct mt76_txq *)vif->txq->drv_priv;
+-              mtxq->wcid = &mvif->sta.wcid;
++              mtxq->wcid = idx;
+       }
+       if (vif->type != NL80211_IFTYPE_AP &&
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
+index 13a7ae3d8351..6cb65391427f 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
+@@ -283,7 +283,7 @@ static int mt7921_add_interface(struct ieee80211_hw *hw,
+       rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid);
+       if (vif->txq) {
+               mtxq = (struct mt76_txq *)vif->txq->drv_priv;
+-              mtxq->wcid = &mvif->sta.wcid;
++              mtxq->wcid = idx;
+       }
+ out:
+diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c
+index f0f7a913eaab..dce6f6b5f071 100644
+--- a/drivers/net/wireless/mediatek/mt76/tx.c
++++ b/drivers/net/wireless/mediatek/mt76/tx.c
+@@ -406,12 +406,11 @@ mt76_txq_stopped(struct mt76_queue *q)
+ static int
+ mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_queue *q,
+-                  struct mt76_txq *mtxq)
++                  struct mt76_txq *mtxq, struct mt76_wcid *wcid)
+ {
+       struct mt76_dev *dev = phy->dev;
+       struct ieee80211_txq *txq = mtxq_to_txq(mtxq);
+       enum mt76_txq_id qid = mt76_txq_get_qid(txq);
+-      struct mt76_wcid *wcid = mtxq->wcid;
+       struct ieee80211_tx_info *info;
+       struct sk_buff *skb;
+       int n_frames = 1;
+@@ -491,8 +490,8 @@ mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid)
+                       break;
+               mtxq = (struct mt76_txq *)txq->drv_priv;
+-              wcid = mtxq->wcid;
+-              if (wcid && test_bit(MT_WCID_FLAG_PS, &wcid->flags))
++              wcid = rcu_dereference(dev->wcid[mtxq->wcid]);
++              if (!wcid || test_bit(MT_WCID_FLAG_PS, &wcid->flags))
+                       continue;
+               spin_lock_bh(&q->lock);
+@@ -511,7 +510,7 @@ mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid)
+               }
+               if (!mt76_txq_stopped(q))
+-                      n_frames = mt76_txq_send_burst(phy, q, mtxq);
++                      n_frames = mt76_txq_send_burst(phy, q, mtxq, wcid);
+               spin_unlock_bh(&q->lock);
+-- 
+2.35.1
+
index 756d57442f14fda9a020c5c2891fbf8091d5ef5b..abbce8748aaf7dc7108f77e3c008d23ce5483e3e 100644 (file)
@@ -136,3 +136,41 @@ mm-mempolicy-fix-uninit-value-in-mpol_rebind_policy.patch
 bpf-make-sure-mac_header-was-set-before-using-it.patch
 sched-deadline-fix-bug_on-condition-for-deboosted-tasks.patch
 x86-bugs-warn-when-ibrs-mitigation-is-selected-on-enhanced-ibrs-parts.patch
+dlm-fix-pending-remove-if-msg-allocation-fails.patch
+x86-uaccess-implement-macros-for-cmpxchg-on-user-add.patch
+x86-uaccess-implement-macros-for-cmpxchg-on-user-add.patch-32473
+x86-extable-tidy-up-redundant-handler-functions.patch
+x86-extable-get-rid-of-redundant-macros.patch
+x86-mce-deduplicate-exception-handling.patch
+x86-extable-rework-the-exception-table-mechanics.patch
+x86-extable-provide-ex_type_default_mce_safe-and-ex_.patch
+bitfield.h-fix-type-of-reg-too-small-for-mask-test.patch
+x86-entry_32-remove-.fixup-usage.patch
+x86-extable-extend-extable-functionality.patch
+x86-msr-remove-.fixup-usage.patch
+x86-futex-remove-.fixup-usage.patch
+kvm-x86-use-__try_cmpxchg_user-to-emulate-atomic-acc.patch
+xhci-dbc-refactor-xhci_dbc_init.patch
+xhci-dbc-create-and-remove-dbc-structure-in-dbgtty-d.patch
+xhci-dbc-rename-xhci_dbc_init-and-xhci_dbc_exit.patch
+xhci-set-hcd-flag-to-defer-primary-roothub-registrat.patch
+mt76-fix-use-after-free-by-removing-a-non-rcu-wcid-p.patch
+iwlwifi-fw-uefi-add-missing-include-guards.patch
+crypto-qat-set-to-zero-dh-parameters-before-free.patch
+crypto-qat-use-pre-allocated-buffers-in-datapath.patch
+crypto-qat-refactor-submission-logic.patch
+crypto-qat-add-backlog-mechanism.patch
+crypto-qat-fix-memory-leak-in-rsa.patch
+crypto-qat-remove-dma_free_coherent-for-rsa.patch
+crypto-qat-remove-dma_free_coherent-for-dh.patch
+crypto-qat-add-param-check-for-rsa.patch
+crypto-qat-add-param-check-for-dh.patch
+crypto-qat-re-enable-registration-of-algorithms.patch
+exfat-fix-referencing-wrong-parent-directory-informa.patch
+tracing-have-event-format-check-not-flag-p-on-__get_.patch
+tracing-place-trace_pid_list-logic-into-abstract-fun.patch
+tracing-fix-return-value-of-trace_pid_write.patch
+um-virtio_uml-allow-probing-from-devicetree.patch
+um-virtio_uml-fix-broken-device-handling-in-time-tra.patch
+x86-uaccess-implement-macros-for-cmpxchg-on-user-add.patch-12415
+x86-extable-provide-ex_type_default_mce_safe-and-ex_.patch-2687
diff --git a/queue-5.15/tracing-fix-return-value-of-trace_pid_write.patch b/queue-5.15/tracing-fix-return-value-of-trace_pid_write.patch
new file mode 100644 (file)
index 0000000..5875877
--- /dev/null
@@ -0,0 +1,84 @@
+From 3aea4627fccb657fb44380302e116c6f9a0a9f0f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 May 2022 14:05:46 +0900
+Subject: tracing: Fix return value of trace_pid_write()
+
+From: Wonhyuk Yang <vvghjk1234@gmail.com>
+
+[ Upstream commit b27f266f74fbda4ee36c2b2b04d15992860cf23b ]
+
+Setting set_event_pid with trailing whitespace lead to endless write
+system calls like below.
+
+    $ strace echo "123 " > /sys/kernel/debug/tracing/set_event_pid
+    execve("/usr/bin/echo", ["echo", "123 "], ...) = 0
+    ...
+    write(1, "123 \n", 5)                   = 4
+    write(1, "\n", 1)                       = 0
+    write(1, "\n", 1)                       = 0
+    write(1, "\n", 1)                       = 0
+    write(1, "\n", 1)                       = 0
+    write(1, "\n", 1)                       = 0
+    ....
+
+This is because, the result of trace_get_user's are not returned when it
+read at least one pid. To fix it, update read variable even if
+parser->idx == 0.
+
+The result of applied patch is below.
+
+    $ strace echo "123 " > /sys/kernel/debug/tracing/set_event_pid
+    execve("/usr/bin/echo", ["echo", "123 "], ...) = 0
+    ...
+    write(1, "123 \n", 5)                   = 5
+    close(1)                                = 0
+
+Link: https://lkml.kernel.org/r/20220503050546.288911-1-vvghjk1234@gmail.com
+
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Baik Song An <bsahn@etri.re.kr>
+Cc: Hong Yeon Kim <kimhy@etri.re.kr>
+Cc: Taeung Song <taeung@reallinux.co.kr>
+Cc: linuxgeek@linuxgeek.io
+Cc: stable@vger.kernel.org
+Fixes: 4909010788640 ("tracing: Add set_event_pid directory for future use")
+Signed-off-by: Wonhyuk Yang <vvghjk1234@gmail.com>
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/trace/trace.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
+index abbe8489faae..d93f9c59f50e 100644
+--- a/kernel/trace/trace.c
++++ b/kernel/trace/trace.c
+@@ -711,13 +711,16 @@ int trace_pid_write(struct trace_pid_list *filtered_pids,
+               pos = 0;
+               ret = trace_get_user(&parser, ubuf, cnt, &pos);
+-              if (ret < 0 || !trace_parser_loaded(&parser))
++              if (ret < 0)
+                       break;
+               read += ret;
+               ubuf += ret;
+               cnt -= ret;
++              if (!trace_parser_loaded(&parser))
++                      break;
++
+               ret = -EINVAL;
+               if (kstrtoul(parser.buffer, 0, &val))
+                       break;
+@@ -743,7 +746,6 @@ int trace_pid_write(struct trace_pid_list *filtered_pids,
+       if (!nr_pids) {
+               /* Cleared the list of pids */
+               trace_pid_list_free(pid_list);
+-              read = ret;
+               pid_list = NULL;
+       }
+-- 
+2.35.1
+
diff --git a/queue-5.15/tracing-have-event-format-check-not-flag-p-on-__get_.patch b/queue-5.15/tracing-have-event-format-check-not-flag-p-on-__get_.patch
new file mode 100644 (file)
index 0000000..9ebbadf
--- /dev/null
@@ -0,0 +1,49 @@
+From a6dadf3a29532dbfd9443af5baeb80e80b78596c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 7 Apr 2022 14:56:32 -0400
+Subject: tracing: Have event format check not flag %p* on
+ __get_dynamic_array()
+
+From: Steven Rostedt (Google) <rostedt@goodmis.org>
+
+[ Upstream commit 499f12168aebd6da8fa32c9b7d6203ca9b5eb88d ]
+
+The print fmt check against trace events to make sure that the format does
+not use pointers that may be freed from the time of the trace to the time
+the event is read, gives a false positive on %pISpc when reading data that
+was saved in __get_dynamic_array() when it is perfectly fine to do so, as
+the data being read is on the ring buffer.
+
+Link: https://lore.kernel.org/all/20220407144524.2a592ed6@canb.auug.org.au/
+
+Cc: stable@vger.kernel.org
+Fixes: 5013f454a352c ("tracing: Add check of trace event print fmts for dereferencing pointers")
+Reported-by: Stephen Rothwell <sfr@canb.auug.org.au>
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/trace/trace_events.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
+index c072e8b9849c..ea3fbfa87fdd 100644
+--- a/kernel/trace/trace_events.c
++++ b/kernel/trace/trace_events.c
+@@ -407,7 +407,14 @@ static void test_event_printk(struct trace_event_call *call)
+                               a = strchr(fmt + i, '&');
+                               if ((a && (a < r)) || test_field(r, call))
+                                       dereference_flags &= ~(1ULL << arg);
++                      } else if ((r = strstr(fmt + i, "__get_dynamic_array(")) &&
++                                 (!c || r < c)) {
++                              dereference_flags &= ~(1ULL << arg);
++                      } else if ((r = strstr(fmt + i, "__get_sockaddr(")) &&
++                                 (!c || r < c)) {
++                              dereference_flags &= ~(1ULL << arg);
+                       }
++
+               next_arg:
+                       i--;
+                       arg++;
+-- 
+2.35.1
+
diff --git a/queue-5.15/tracing-place-trace_pid_list-logic-into-abstract-fun.patch b/queue-5.15/tracing-place-trace_pid_list-logic-into-abstract-fun.patch
new file mode 100644 (file)
index 0000000..fabcb94
--- /dev/null
@@ -0,0 +1,497 @@
+From 292cd5bf28c45bc83801b70bb1a221f020fe395f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Sep 2021 21:03:49 -0400
+Subject: tracing: Place trace_pid_list logic into abstract functions
+
+From: Steven Rostedt (VMware) <rostedt@goodmis.org>
+
+[ Upstream commit 6954e415264eeb5ee6be0d22d789ad12c995ee64 ]
+
+Instead of having the logic that does trace_pid_list open coded, wrap it in
+abstract functions. This will allow a rewrite of the logic that implements
+the trace_pid_list without affecting the users.
+
+Note, this causes a change in behavior. Every time a pid is written into
+the set_*_pid file, it creates a new list and uses RCU to update it. If
+pid_max is lowered, but there was a pid currently in the list that was
+higher than pid_max, those pids will now be removed on updating the list.
+The old behavior kept that from happening.
+
+The rewrite of the pid_list logic will no longer depend on pid_max,
+and will return the old behavior.
+
+Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/trace/Makefile       |   1 +
+ kernel/trace/ftrace.c       |   6 +-
+ kernel/trace/pid_list.c     | 160 ++++++++++++++++++++++++++++++++++++
+ kernel/trace/pid_list.h     |  13 +++
+ kernel/trace/trace.c        |  78 ++++++------------
+ kernel/trace/trace.h        |  14 +++-
+ kernel/trace/trace_events.c |   6 +-
+ 7 files changed, 217 insertions(+), 61 deletions(-)
+ create mode 100644 kernel/trace/pid_list.c
+ create mode 100644 kernel/trace/pid_list.h
+
+diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile
+index 6de5d4d63165..bedc5caceec7 100644
+--- a/kernel/trace/Makefile
++++ b/kernel/trace/Makefile
+@@ -47,6 +47,7 @@ obj-$(CONFIG_TRACING) += trace_output.o
+ obj-$(CONFIG_TRACING) += trace_seq.o
+ obj-$(CONFIG_TRACING) += trace_stat.o
+ obj-$(CONFIG_TRACING) += trace_printk.o
++obj-$(CONFIG_TRACING) +=      pid_list.o
+ obj-$(CONFIG_TRACING_MAP) += tracing_map.o
+ obj-$(CONFIG_PREEMPTIRQ_DELAY_TEST) += preemptirq_delay_test.o
+ obj-$(CONFIG_SYNTH_EVENT_GEN_TEST) += synth_event_gen_test.o
+diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
+index 53a1af21d25c..e215a9c96971 100644
+--- a/kernel/trace/ftrace.c
++++ b/kernel/trace/ftrace.c
+@@ -7184,10 +7184,10 @@ static void clear_ftrace_pids(struct trace_array *tr, int type)
+       synchronize_rcu();
+       if ((type & TRACE_PIDS) && pid_list)
+-              trace_free_pid_list(pid_list);
++              trace_pid_list_free(pid_list);
+       if ((type & TRACE_NO_PIDS) && no_pid_list)
+-              trace_free_pid_list(no_pid_list);
++              trace_pid_list_free(no_pid_list);
+ }
+ void ftrace_clear_pids(struct trace_array *tr)
+@@ -7428,7 +7428,7 @@ pid_write(struct file *filp, const char __user *ubuf,
+       if (filtered_pids) {
+               synchronize_rcu();
+-              trace_free_pid_list(filtered_pids);
++              trace_pid_list_free(filtered_pids);
+       } else if (pid_list && !other_pids) {
+               /* Register a probe to set whether to ignore the tracing of a task */
+               register_trace_sched_switch(ftrace_filter_pid_sched_switch_probe, tr);
+diff --git a/kernel/trace/pid_list.c b/kernel/trace/pid_list.c
+new file mode 100644
+index 000000000000..4483ef70b562
+--- /dev/null
++++ b/kernel/trace/pid_list.c
+@@ -0,0 +1,160 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (C) 2021 VMware Inc, Steven Rostedt <rostedt@goodmis.org>
++ */
++#include <linux/vmalloc.h>
++#include <linux/slab.h>
++#include "trace.h"
++
++/**
++ * trace_pid_list_is_set - test if the pid is set in the list
++ * @pid_list: The pid list to test
++ * @pid: The pid to to see if set in the list.
++ *
++ * Tests if @pid is is set in the @pid_list. This is usually called
++ * from the scheduler when a task is scheduled. Its pid is checked
++ * if it should be traced or not.
++ *
++ * Return true if the pid is in the list, false otherwise.
++ */
++bool trace_pid_list_is_set(struct trace_pid_list *pid_list, unsigned int pid)
++{
++      /*
++       * If pid_max changed after filtered_pids was created, we
++       * by default ignore all pids greater than the previous pid_max.
++       */
++      if (pid >= pid_list->pid_max)
++              return false;
++
++      return test_bit(pid, pid_list->pids);
++}
++
++/**
++ * trace_pid_list_set - add a pid to the list
++ * @pid_list: The pid list to add the @pid to.
++ * @pid: The pid to add.
++ *
++ * Adds @pid to @pid_list. This is usually done explicitly by a user
++ * adding a task to be traced, or indirectly by the fork function
++ * when children should be traced and a task's pid is in the list.
++ *
++ * Return 0 on success, negative otherwise.
++ */
++int trace_pid_list_set(struct trace_pid_list *pid_list, unsigned int pid)
++{
++      /* Sorry, but we don't support pid_max changing after setting */
++      if (pid >= pid_list->pid_max)
++              return -EINVAL;
++
++      set_bit(pid, pid_list->pids);
++
++      return 0;
++}
++
++/**
++ * trace_pid_list_clear - remove a pid from the list
++ * @pid_list: The pid list to remove the @pid from.
++ * @pid: The pid to remove.
++ *
++ * Removes @pid from @pid_list. This is usually done explicitly by a user
++ * removing tasks from tracing, or indirectly by the exit function
++ * when a task that is set to be traced exits.
++ *
++ * Return 0 on success, negative otherwise.
++ */
++int trace_pid_list_clear(struct trace_pid_list *pid_list, unsigned int pid)
++{
++      /* Sorry, but we don't support pid_max changing after setting */
++      if (pid >= pid_list->pid_max)
++              return -EINVAL;
++
++      clear_bit(pid, pid_list->pids);
++
++      return 0;
++}
++
++/**
++ * trace_pid_list_next - return the next pid in the list
++ * @pid_list: The pid list to examine.
++ * @pid: The pid to start from
++ * @next: The pointer to place the pid that is set starting from @pid.
++ *
++ * Looks for the next consecutive pid that is in @pid_list starting
++ * at the pid specified by @pid. If one is set (including @pid), then
++ * that pid is placed into @next.
++ *
++ * Return 0 when a pid is found, -1 if there are no more pids included.
++ */
++int trace_pid_list_next(struct trace_pid_list *pid_list, unsigned int pid,
++                      unsigned int *next)
++{
++      pid = find_next_bit(pid_list->pids, pid_list->pid_max, pid);
++
++      if (pid < pid_list->pid_max) {
++              *next = pid;
++              return 0;
++      }
++      return -1;
++}
++
++/**
++ * trace_pid_list_first - return the first pid in the list
++ * @pid_list: The pid list to examine.
++ * @pid: The pointer to place the pid first found pid that is set.
++ *
++ * Looks for the first pid that is set in @pid_list, and places it
++ * into @pid if found.
++ *
++ * Return 0 when a pid is found, -1 if there are no pids set.
++ */
++int trace_pid_list_first(struct trace_pid_list *pid_list, unsigned int *pid)
++{
++      unsigned int first;
++
++      first = find_first_bit(pid_list->pids, pid_list->pid_max);
++
++      if (first < pid_list->pid_max) {
++              *pid = first;
++              return 0;
++      }
++      return -1;
++}
++
++/**
++ * trace_pid_list_alloc - create a new pid_list
++ *
++ * Allocates a new pid_list to store pids into.
++ *
++ * Returns the pid_list on success, NULL otherwise.
++ */
++struct trace_pid_list *trace_pid_list_alloc(void)
++{
++      struct trace_pid_list *pid_list;
++
++      pid_list = kmalloc(sizeof(*pid_list), GFP_KERNEL);
++      if (!pid_list)
++              return NULL;
++
++      pid_list->pid_max = READ_ONCE(pid_max);
++
++      pid_list->pids = vzalloc((pid_list->pid_max + 7) >> 3);
++      if (!pid_list->pids) {
++              kfree(pid_list);
++              return NULL;
++      }
++      return pid_list;
++}
++
++/**
++ * trace_pid_list_free - Frees an allocated pid_list.
++ *
++ * Frees the memory for a pid_list that was allocated.
++ */
++void trace_pid_list_free(struct trace_pid_list *pid_list)
++{
++      if (!pid_list)
++              return;
++
++      vfree(pid_list->pids);
++      kfree(pid_list);
++}
+diff --git a/kernel/trace/pid_list.h b/kernel/trace/pid_list.h
+new file mode 100644
+index 000000000000..80d0ecfe1536
+--- /dev/null
++++ b/kernel/trace/pid_list.h
+@@ -0,0 +1,13 @@
++// SPDX-License-Identifier: GPL-2.0
++
++/* Do not include this file directly. */
++
++#ifndef _TRACE_INTERNAL_PID_LIST_H
++#define _TRACE_INTERNAL_PID_LIST_H
++
++struct trace_pid_list {
++      int                     pid_max;
++      unsigned long           *pids;
++};
++
++#endif /* _TRACE_INTERNAL_PID_LIST_H */
+diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
+index f752f2574630..abbe8489faae 100644
+--- a/kernel/trace/trace.c
++++ b/kernel/trace/trace.c
+@@ -516,12 +516,6 @@ int call_filter_check_discard(struct trace_event_call *call, void *rec,
+       return 0;
+ }
+-void trace_free_pid_list(struct trace_pid_list *pid_list)
+-{
+-      vfree(pid_list->pids);
+-      kfree(pid_list);
+-}
+-
+ /**
+  * trace_find_filtered_pid - check if a pid exists in a filtered_pid list
+  * @filtered_pids: The list of pids to check
+@@ -532,14 +526,7 @@ void trace_free_pid_list(struct trace_pid_list *pid_list)
+ bool
+ trace_find_filtered_pid(struct trace_pid_list *filtered_pids, pid_t search_pid)
+ {
+-      /*
+-       * If pid_max changed after filtered_pids was created, we
+-       * by default ignore all pids greater than the previous pid_max.
+-       */
+-      if (search_pid >= filtered_pids->pid_max)
+-              return false;
+-
+-      return test_bit(search_pid, filtered_pids->pids);
++      return trace_pid_list_is_set(filtered_pids, search_pid);
+ }
+ /**
+@@ -596,15 +583,11 @@ void trace_filter_add_remove_task(struct trace_pid_list *pid_list,
+                       return;
+       }
+-      /* Sorry, but we don't support pid_max changing after setting */
+-      if (task->pid >= pid_list->pid_max)
+-              return;
+-
+       /* "self" is set for forks, and NULL for exits */
+       if (self)
+-              set_bit(task->pid, pid_list->pids);
++              trace_pid_list_set(pid_list, task->pid);
+       else
+-              clear_bit(task->pid, pid_list->pids);
++              trace_pid_list_clear(pid_list, task->pid);
+ }
+ /**
+@@ -621,18 +604,19 @@ void trace_filter_add_remove_task(struct trace_pid_list *pid_list,
+  */
+ void *trace_pid_next(struct trace_pid_list *pid_list, void *v, loff_t *pos)
+ {
+-      unsigned long pid = (unsigned long)v;
++      long pid = (unsigned long)v;
++      unsigned int next;
+       (*pos)++;
+       /* pid already is +1 of the actual previous bit */
+-      pid = find_next_bit(pid_list->pids, pid_list->pid_max, pid);
++      if (trace_pid_list_next(pid_list, pid, &next) < 0)
++              return NULL;
+-      /* Return pid + 1 to allow zero to be represented */
+-      if (pid < pid_list->pid_max)
+-              return (void *)(pid + 1);
++      pid = next;
+-      return NULL;
++      /* Return pid + 1 to allow zero to be represented */
++      return (void *)(pid + 1);
+ }
+ /**
+@@ -649,12 +633,14 @@ void *trace_pid_next(struct trace_pid_list *pid_list, void *v, loff_t *pos)
+ void *trace_pid_start(struct trace_pid_list *pid_list, loff_t *pos)
+ {
+       unsigned long pid;
++      unsigned int first;
+       loff_t l = 0;
+-      pid = find_first_bit(pid_list->pids, pid_list->pid_max);
+-      if (pid >= pid_list->pid_max)
++      if (trace_pid_list_first(pid_list, &first) < 0)
+               return NULL;
++      pid = first;
++
+       /* Return pid + 1 so that zero can be the exit value */
+       for (pid++; pid && l < *pos;
+            pid = (unsigned long)trace_pid_next(pid_list, (void *)pid, &l))
+@@ -690,7 +676,7 @@ int trace_pid_write(struct trace_pid_list *filtered_pids,
+       unsigned long val;
+       int nr_pids = 0;
+       ssize_t read = 0;
+-      ssize_t ret = 0;
++      ssize_t ret;
+       loff_t pos;
+       pid_t pid;
+@@ -703,34 +689,23 @@ int trace_pid_write(struct trace_pid_list *filtered_pids,
+        * the user. If the operation fails, then the current list is
+        * not modified.
+        */
+-      pid_list = kmalloc(sizeof(*pid_list), GFP_KERNEL);
++      pid_list = trace_pid_list_alloc();
+       if (!pid_list) {
+               trace_parser_put(&parser);
+               return -ENOMEM;
+       }
+-      pid_list->pid_max = READ_ONCE(pid_max);
+-
+-      /* Only truncating will shrink pid_max */
+-      if (filtered_pids && filtered_pids->pid_max > pid_list->pid_max)
+-              pid_list->pid_max = filtered_pids->pid_max;
+-
+-      pid_list->pids = vzalloc((pid_list->pid_max + 7) >> 3);
+-      if (!pid_list->pids) {
+-              trace_parser_put(&parser);
+-              kfree(pid_list);
+-              return -ENOMEM;
+-      }
+-
+       if (filtered_pids) {
+               /* copy the current bits to the new max */
+-              for_each_set_bit(pid, filtered_pids->pids,
+-                               filtered_pids->pid_max) {
+-                      set_bit(pid, pid_list->pids);
++              ret = trace_pid_list_first(filtered_pids, &pid);
++              while (!ret) {
++                      trace_pid_list_set(pid_list, pid);
++                      ret = trace_pid_list_next(filtered_pids, pid + 1, &pid);
+                       nr_pids++;
+               }
+       }
++      ret = 0;
+       while (cnt > 0) {
+               pos = 0;
+@@ -746,12 +721,13 @@ int trace_pid_write(struct trace_pid_list *filtered_pids,
+               ret = -EINVAL;
+               if (kstrtoul(parser.buffer, 0, &val))
+                       break;
+-              if (val >= pid_list->pid_max)
+-                      break;
+               pid = (pid_t)val;
+-              set_bit(pid, pid_list->pids);
++              if (trace_pid_list_set(pid_list, pid) < 0) {
++                      ret = -1;
++                      break;
++              }
+               nr_pids++;
+               trace_parser_clear(&parser);
+@@ -760,13 +736,13 @@ int trace_pid_write(struct trace_pid_list *filtered_pids,
+       trace_parser_put(&parser);
+       if (ret < 0) {
+-              trace_free_pid_list(pid_list);
++              trace_pid_list_free(pid_list);
+               return ret;
+       }
+       if (!nr_pids) {
+               /* Cleared the list of pids */
+-              trace_free_pid_list(pid_list);
++              trace_pid_list_free(pid_list);
+               read = ret;
+               pid_list = NULL;
+       }
+diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
+index 421374c304fc..d6763366a320 100644
+--- a/kernel/trace/trace.h
++++ b/kernel/trace/trace.h
+@@ -22,6 +22,8 @@
+ #include <linux/ctype.h>
+ #include <linux/once_lite.h>
++#include "pid_list.h"
++
+ #ifdef CONFIG_FTRACE_SYSCALLS
+ #include <asm/unistd.h>               /* For NR_SYSCALLS           */
+ #include <asm/syscall.h>      /* some archs define it here */
+@@ -191,10 +193,14 @@ struct trace_options {
+       struct trace_option_dentry      *topts;
+ };
+-struct trace_pid_list {
+-      int                             pid_max;
+-      unsigned long                   *pids;
+-};
++struct trace_pid_list *trace_pid_list_alloc(void);
++void trace_pid_list_free(struct trace_pid_list *pid_list);
++bool trace_pid_list_is_set(struct trace_pid_list *pid_list, unsigned int pid);
++int trace_pid_list_set(struct trace_pid_list *pid_list, unsigned int pid);
++int trace_pid_list_clear(struct trace_pid_list *pid_list, unsigned int pid);
++int trace_pid_list_first(struct trace_pid_list *pid_list, unsigned int *pid);
++int trace_pid_list_next(struct trace_pid_list *pid_list, unsigned int pid,
++                      unsigned int *next);
+ enum {
+       TRACE_PIDS              = BIT(0),
+diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
+index ea3fbfa87fdd..c4f654efb77a 100644
+--- a/kernel/trace/trace_events.c
++++ b/kernel/trace/trace_events.c
+@@ -900,10 +900,10 @@ static void __ftrace_clear_event_pids(struct trace_array *tr, int type)
+       tracepoint_synchronize_unregister();
+       if ((type & TRACE_PIDS) && pid_list)
+-              trace_free_pid_list(pid_list);
++              trace_pid_list_free(pid_list);
+       if ((type & TRACE_NO_PIDS) && no_pid_list)
+-              trace_free_pid_list(no_pid_list);
++              trace_pid_list_free(no_pid_list);
+ }
+ static void ftrace_clear_event_pids(struct trace_array *tr, int type)
+@@ -1982,7 +1982,7 @@ event_pid_write(struct file *filp, const char __user *ubuf,
+       if (filtered_pids) {
+               tracepoint_synchronize_unregister();
+-              trace_free_pid_list(filtered_pids);
++              trace_pid_list_free(filtered_pids);
+       } else if (pid_list && !other_pids) {
+               register_pid_events(tr);
+       }
+-- 
+2.35.1
+
diff --git a/queue-5.15/um-virtio_uml-allow-probing-from-devicetree.patch b/queue-5.15/um-virtio_uml-allow-probing-from-devicetree.patch
new file mode 100644 (file)
index 0000000..411ae6b
--- /dev/null
@@ -0,0 +1,135 @@
+From d1e3f5bf6241fc4a6f315763eb5608f2f656da4e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Dec 2021 10:04:46 +0100
+Subject: um: virtio_uml: Allow probing from devicetree
+
+From: Vincent Whitchurch <vincent.whitchurch@axis.com>
+
+[ Upstream commit db0dd9cee82270e032123169ceff659eced5115d ]
+
+Allow the virtio_uml device to be probed from the devicetree so that
+sub-devices can be specified using the standard virtio bindings, for
+example:
+
+  virtio@1 {
+    compatible = "virtio,uml";
+    socket-path = "i2c.sock";
+    virtio-device-id = <0x22>;
+
+    i2c-controller {
+      compatible = "virtio,device22";
+      #address-cells = <0x01>;
+      #size-cells = <0x00>;
+
+      light-sensor@01 {
+        compatible = "ti,opt3001";
+        reg = <0x01>;
+      };
+    };
+  };
+
+Signed-off-by: Vincent Whitchurch <vincent.whitchurch@axis.com>
+Signed-off-by: Richard Weinberger <richard@nod.at>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/um/drivers/virtio_uml.c | 50 +++++++++++++++++++++++++++++++++---
+ 1 file changed, 47 insertions(+), 3 deletions(-)
+
+diff --git a/arch/um/drivers/virtio_uml.c b/arch/um/drivers/virtio_uml.c
+index 7755cb4ff9fc..ba562d68dc04 100644
+--- a/arch/um/drivers/virtio_uml.c
++++ b/arch/um/drivers/virtio_uml.c
+@@ -21,6 +21,7 @@
+  * Based on Virtio MMIO driver by Pawel Moll, copyright 2011-2014, ARM Ltd.
+  */
+ #include <linux/module.h>
++#include <linux/of.h>
+ #include <linux/platform_device.h>
+ #include <linux/slab.h>
+ #include <linux/virtio.h>
+@@ -49,6 +50,7 @@ struct virtio_uml_platform_data {
+ struct virtio_uml_device {
+       struct virtio_device vdev;
+       struct platform_device *pdev;
++      struct virtio_uml_platform_data *pdata;
+       spinlock_t sock_lock;
+       int sock, req_fd, irq;
+@@ -149,7 +151,7 @@ static int vhost_user_recv(struct virtio_uml_device *vu_dev,
+       if (rc == -ECONNRESET && vu_dev->registered) {
+               struct virtio_uml_platform_data *pdata;
+-              pdata = vu_dev->pdev->dev.platform_data;
++              pdata = vu_dev->pdata;
+               virtio_break_device(&vu_dev->vdev);
+               schedule_work(&pdata->conn_broken_wk);
+@@ -1115,21 +1117,63 @@ void virtio_uml_set_no_vq_suspend(struct virtio_device *vdev,
+                no_vq_suspend ? "dis" : "en");
+ }
++static void vu_of_conn_broken(struct work_struct *wk)
++{
++      /*
++       * We can't remove the device from the devicetree so the only thing we
++       * can do is warn.
++       */
++      WARN_ON(1);
++}
++
+ /* Platform device */
++static struct virtio_uml_platform_data *
++virtio_uml_create_pdata(struct platform_device *pdev)
++{
++      struct device_node *np = pdev->dev.of_node;
++      struct virtio_uml_platform_data *pdata;
++      int ret;
++
++      if (!np)
++              return ERR_PTR(-EINVAL);
++
++      pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
++      if (!pdata)
++              return ERR_PTR(-ENOMEM);
++
++      INIT_WORK(&pdata->conn_broken_wk, vu_of_conn_broken);
++      pdata->pdev = pdev;
++
++      ret = of_property_read_string(np, "socket-path", &pdata->socket_path);
++      if (ret)
++              return ERR_PTR(ret);
++
++      ret = of_property_read_u32(np, "virtio-device-id",
++                                 &pdata->virtio_device_id);
++      if (ret)
++              return ERR_PTR(ret);
++
++      return pdata;
++}
++
+ static int virtio_uml_probe(struct platform_device *pdev)
+ {
+       struct virtio_uml_platform_data *pdata = pdev->dev.platform_data;
+       struct virtio_uml_device *vu_dev;
+       int rc;
+-      if (!pdata)
+-              return -EINVAL;
++      if (!pdata) {
++              pdata = virtio_uml_create_pdata(pdev);
++              if (IS_ERR(pdata))
++                      return PTR_ERR(pdata);
++      }
+       vu_dev = kzalloc(sizeof(*vu_dev), GFP_KERNEL);
+       if (!vu_dev)
+               return -ENOMEM;
++      vu_dev->pdata = pdata;
+       vu_dev->vdev.dev.parent = &pdev->dev;
+       vu_dev->vdev.dev.release = virtio_uml_release_dev;
+       vu_dev->vdev.config = &virtio_uml_config_ops;
+-- 
+2.35.1
+
diff --git a/queue-5.15/um-virtio_uml-fix-broken-device-handling-in-time-tra.patch b/queue-5.15/um-virtio_uml-fix-broken-device-handling-in-time-tra.patch
new file mode 100644 (file)
index 0000000..c6ce918
--- /dev/null
@@ -0,0 +1,122 @@
+From 553ad0ac9df5625106875386382e05797b7df23a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 17 May 2022 22:52:50 +0200
+Subject: um: virtio_uml: Fix broken device handling in time-travel
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit af9fb41ed315ce95f659f0b10b4d59a71975381d ]
+
+If a device implementation crashes, virtio_uml will mark it
+as dead by calling virtio_break_device() and scheduling the
+work that will remove it.
+
+This still seems like the right thing to do, but it's done
+directly while reading the message, and if time-travel is
+used, this is in the time-travel handler, outside of the
+normal Linux machinery. Therefore, we cannot acquire locks
+or do normal "linux-y" things because e.g. lockdep will be
+confused about the context.
+
+Move handling this situation out of the read function and
+into the actual IRQ handler and response handling instead,
+so that in the case of time-travel we don't call it in the
+wrong context.
+
+Chances are the system will still crash immediately, since
+the device implementation crashing may also cause the time-
+travel controller to go down, but at least all of that now
+happens without strange warnings from lockdep.
+
+Fixes: c8177aba37ca ("um: time-travel: rework interrupt handling in ext mode")
+Cc: stable@vger.kernel.org
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Richard Weinberger <richard@nod.at>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/um/drivers/virtio_uml.c | 33 +++++++++++++++++++++++----------
+ 1 file changed, 23 insertions(+), 10 deletions(-)
+
+diff --git a/arch/um/drivers/virtio_uml.c b/arch/um/drivers/virtio_uml.c
+index ba562d68dc04..82ff3785bf69 100644
+--- a/arch/um/drivers/virtio_uml.c
++++ b/arch/um/drivers/virtio_uml.c
+@@ -63,6 +63,7 @@ struct virtio_uml_device {
+       u8 config_changed_irq:1;
+       uint64_t vq_irq_vq_map;
++      int recv_rc;
+ };
+ struct virtio_uml_vq_info {
+@@ -148,14 +149,6 @@ static int vhost_user_recv(struct virtio_uml_device *vu_dev,
+       rc = vhost_user_recv_header(fd, msg);
+-      if (rc == -ECONNRESET && vu_dev->registered) {
+-              struct virtio_uml_platform_data *pdata;
+-
+-              pdata = vu_dev->pdata;
+-
+-              virtio_break_device(&vu_dev->vdev);
+-              schedule_work(&pdata->conn_broken_wk);
+-      }
+       if (rc)
+               return rc;
+       size = msg->header.size;
+@@ -164,6 +157,21 @@ static int vhost_user_recv(struct virtio_uml_device *vu_dev,
+       return full_read(fd, &msg->payload, size, false);
+ }
++static void vhost_user_check_reset(struct virtio_uml_device *vu_dev,
++                                 int rc)
++{
++      struct virtio_uml_platform_data *pdata = vu_dev->pdata;
++
++      if (rc != -ECONNRESET)
++              return;
++
++      if (!vu_dev->registered)
++              return;
++
++      virtio_break_device(&vu_dev->vdev);
++      schedule_work(&pdata->conn_broken_wk);
++}
++
+ static int vhost_user_recv_resp(struct virtio_uml_device *vu_dev,
+                               struct vhost_user_msg *msg,
+                               size_t max_payload_size)
+@@ -171,8 +179,10 @@ static int vhost_user_recv_resp(struct virtio_uml_device *vu_dev,
+       int rc = vhost_user_recv(vu_dev, vu_dev->sock, msg,
+                                max_payload_size, true);
+-      if (rc)
++      if (rc) {
++              vhost_user_check_reset(vu_dev, rc);
+               return rc;
++      }
+       if (msg->header.flags != (VHOST_USER_FLAG_REPLY | VHOST_USER_VERSION))
+               return -EPROTO;
+@@ -369,6 +379,7 @@ static irqreturn_t vu_req_read_message(struct virtio_uml_device *vu_dev,
+                                sizeof(msg.msg.payload) +
+                                sizeof(msg.extra_payload));
++      vu_dev->recv_rc = rc;
+       if (rc)
+               return IRQ_NONE;
+@@ -412,7 +423,9 @@ static irqreturn_t vu_req_interrupt(int irq, void *data)
+       if (!um_irq_timetravel_handler_used())
+               ret = vu_req_read_message(vu_dev, NULL);
+-      if (vu_dev->vq_irq_vq_map) {
++      if (vu_dev->recv_rc) {
++              vhost_user_check_reset(vu_dev, vu_dev->recv_rc);
++      } else if (vu_dev->vq_irq_vq_map) {
+               struct virtqueue *vq;
+               virtio_device_for_each_vq((&vu_dev->vdev), vq) {
+-- 
+2.35.1
+
diff --git a/queue-5.15/x86-entry_32-remove-.fixup-usage.patch b/queue-5.15/x86-entry_32-remove-.fixup-usage.patch
new file mode 100644 (file)
index 0000000..5559eb1
--- /dev/null
@@ -0,0 +1,130 @@
+From 682a415a9bab479fe5e3f45a1062a5eb495a9c34 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 10 Nov 2021 11:01:08 +0100
+Subject: x86/entry_32: Remove .fixup usage
+
+From: Peter Zijlstra <peterz@infradead.org>
+
+[ Upstream commit aa93e2ad7464ffb90155a5ffdde963816f86d5dc ]
+
+Where possible, push the .fixup into code, at the tail of functions.
+
+This is hard for macros since they're used in multiple functions,
+therefore introduce a new extable handler to pop zeros.
+
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Reviewed-by: Josh Poimboeuf <jpoimboe@redhat.com>
+Link: https://lore.kernel.org/r/20211110101325.245184699@infradead.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/entry/entry_32.S                  | 28 +++++++---------------
+ arch/x86/include/asm/extable_fixup_types.h |  2 ++
+ arch/x86/mm/extable.c                      | 14 +++++++++++
+ 3 files changed, 24 insertions(+), 20 deletions(-)
+
+diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S
+index 5bd3baf36d87..2cba70f9753b 100644
+--- a/arch/x86/entry/entry_32.S
++++ b/arch/x86/entry/entry_32.S
+@@ -270,17 +270,9 @@
+ 3:    popl    %fs
+       addl    $(4 + \pop), %esp       /* pop the unused "gs" slot */
+       IRET_FRAME
+-.pushsection .fixup, "ax"
+-4:    movl    $0, (%esp)
+-      jmp     1b
+-5:    movl    $0, (%esp)
+-      jmp     2b
+-6:    movl    $0, (%esp)
+-      jmp     3b
+-.popsection
+-      _ASM_EXTABLE(1b, 4b)
+-      _ASM_EXTABLE(2b, 5b)
+-      _ASM_EXTABLE(3b, 6b)
++      _ASM_EXTABLE_TYPE(1b, 1b, EX_TYPE_POP_ZERO)
++      _ASM_EXTABLE_TYPE(2b, 2b, EX_TYPE_POP_ZERO)
++      _ASM_EXTABLE_TYPE(3b, 3b, EX_TYPE_POP_ZERO)
+ .endm
+ .macro RESTORE_ALL_NMI cr3_reg:req pop=0
+@@ -923,10 +915,8 @@ SYM_FUNC_START(entry_SYSENTER_32)
+       sti
+       sysexit
+-.pushsection .fixup, "ax"
+-2:    movl    $0, PT_FS(%esp)
+-      jmp     1b
+-.popsection
++2:    movl    $0, PT_FS(%esp)
++      jmp     1b
+       _ASM_EXTABLE(1b, 2b)
+ .Lsysenter_fix_flags:
+@@ -994,8 +984,7 @@ restore_all_switch_stack:
+        */
+       iret
+-.section .fixup, "ax"
+-SYM_CODE_START(asm_iret_error)
++.Lasm_iret_error:
+       pushl   $0                              # no error code
+       pushl   $iret_error
+@@ -1012,9 +1001,8 @@ SYM_CODE_START(asm_iret_error)
+ #endif
+       jmp     handle_exception
+-SYM_CODE_END(asm_iret_error)
+-.previous
+-      _ASM_EXTABLE(.Lirq_return, asm_iret_error)
++
++      _ASM_EXTABLE(.Lirq_return, .Lasm_iret_error)
+ SYM_FUNC_END(entry_INT80_32)
+ .macro FIXUP_ESPFIX_STACK
+diff --git a/arch/x86/include/asm/extable_fixup_types.h b/arch/x86/include/asm/extable_fixup_types.h
+index 409524d5d2eb..4d709a2768bb 100644
+--- a/arch/x86/include/asm/extable_fixup_types.h
++++ b/arch/x86/include/asm/extable_fixup_types.h
+@@ -19,4 +19,6 @@
+ #define       EX_TYPE_DEFAULT_MCE_SAFE        12
+ #define       EX_TYPE_FAULT_MCE_SAFE          13
++#define       EX_TYPE_POP_ZERO                14
++
+ #endif
+diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c
+index f37e290e6d0a..f59a4d017070 100644
+--- a/arch/x86/mm/extable.c
++++ b/arch/x86/mm/extable.c
+@@ -99,6 +99,18 @@ static bool ex_handler_clear_fs(const struct exception_table_entry *fixup,
+       return ex_handler_default(fixup, regs);
+ }
++static bool ex_handler_pop_zero(const struct exception_table_entry *fixup,
++                              struct pt_regs *regs)
++{
++      /*
++       * Typically used for when "pop %seg" traps, in which case we'll clear
++       * the stack slot and re-try the instruction, which will then succeed
++       * to pop zero.
++       */
++      *((unsigned long *)regs->sp) = 0;
++      return ex_handler_default(fixup, regs);
++}
++
+ int ex_get_fixup_type(unsigned long ip)
+ {
+       const struct exception_table_entry *e = search_exception_tables(ip);
+@@ -156,6 +168,8 @@ int fixup_exception(struct pt_regs *regs, int trapnr, unsigned long error_code,
+       case EX_TYPE_WRMSR_IN_MCE:
+               ex_handler_msr_mce(regs, true);
+               break;
++      case EX_TYPE_POP_ZERO:
++              return ex_handler_pop_zero(e, regs);
+       }
+       BUG();
+ }
+-- 
+2.35.1
+
diff --git a/queue-5.15/x86-extable-extend-extable-functionality.patch b/queue-5.15/x86-extable-extend-extable-functionality.patch
new file mode 100644 (file)
index 0000000..ba1f69f
--- /dev/null
@@ -0,0 +1,383 @@
+From 008147ae0631666dbe799b2f4ca7dbf37d98d280 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 10 Nov 2021 11:01:09 +0100
+Subject: x86/extable: Extend extable functionality
+
+From: Peter Zijlstra <peterz@infradead.org>
+
+[ Upstream commit 4b5305decc8436bfe363d1c1773e8fa1c828b14d ]
+
+In order to remove further .fixup usage, extend the extable
+infrastructure to take additional information from the extable entry
+sites.
+
+Specifically add _ASM_EXTABLE_TYPE_REG() and EX_TYPE_IMM_REG that
+extend the existing _ASM_EXTABLE_TYPE() by taking an additional
+register argument and encoding that and an s16 immediate into the
+existing s32 type field. This limits the actual types to the first
+byte, 255 seem plenty.
+
+Also add a few flags into the type word, specifically CLEAR_AX and
+CLEAR_DX which clear the return and extended return register.
+
+Notes:
+ - due to the % in our register names it's hard to make it more
+   generally usable as arm64 did.
+ - the s16 is far larger than used in these patches, future extentions
+   can easily shrink this to get more bits.
+ - without the bitfield fix this will not compile, because: 0xFF > -1
+   and we can't even extract the TYPE field.
+
+[nathanchance: Build fix for clang-lto builds:
+ https://lkml.kernel.org/r/20211210234953.3420108-1-nathan@kernel.org
+]
+
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Reviewed-by: Josh Poimboeuf <jpoimboe@redhat.com>
+Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
+Tested-by: Nick Desaulniers <ndesaulniers@google.com>
+Link: https://lore.kernel.org/r/20211110101325.303890153@infradead.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/include/asm/asm.h                 | 37 ++++++++++++
+ arch/x86/include/asm/extable.h             |  6 +-
+ arch/x86/include/asm/extable_fixup_types.h | 24 ++++++++
+ arch/x86/include/asm/insn-eval.h           |  2 +
+ arch/x86/lib/insn-eval.c                   | 66 ++++++++++++++--------
+ arch/x86/mm/extable.c                      | 40 +++++++++++--
+ arch/x86/net/bpf_jit_comp.c                |  2 +-
+ 7 files changed, 145 insertions(+), 32 deletions(-)
+
+diff --git a/arch/x86/include/asm/asm.h b/arch/x86/include/asm/asm.h
+index 6aadb9a620ee..8cbdfd77a390 100644
+--- a/arch/x86/include/asm/asm.h
++++ b/arch/x86/include/asm/asm.h
+@@ -147,6 +147,33 @@
+ #else /* ! __ASSEMBLY__ */
++# define DEFINE_EXTABLE_TYPE_REG \
++      ".macro extable_type_reg type:req reg:req\n"                                            \
++      ".set found, 0\n"                                                                       \
++      ".set regnr, 0\n"                                                                       \
++      ".irp rs,rax,rcx,rdx,rbx,rsp,rbp,rsi,rdi,r8,r9,r10,r11,r12,r13,r14,r15\n"               \
++      ".ifc \\reg, %%\\rs\n"                                                                  \
++      ".set found, found+1\n"                                                                 \
++      ".long \\type + (regnr << 8)\n"                                                         \
++      ".endif\n"                                                                              \
++      ".set regnr, regnr+1\n"                                                                 \
++      ".endr\n"                                                                               \
++      ".set regnr, 0\n"                                                                       \
++      ".irp rs,eax,ecx,edx,ebx,esp,ebp,esi,edi,r8d,r9d,r10d,r11d,r12d,r13d,r14d,r15d\n"       \
++      ".ifc \\reg, %%\\rs\n"                                                                  \
++      ".set found, found+1\n"                                                                 \
++      ".long \\type + (regnr << 8)\n"                                                         \
++      ".endif\n"                                                                              \
++      ".set regnr, regnr+1\n"                                                                 \
++      ".endr\n"                                                                               \
++      ".if (found != 1)\n"                                                                    \
++      ".error \"extable_type_reg: bad register argument\"\n"                                  \
++      ".endif\n"                                                                              \
++      ".endm\n"
++
++# define UNDEFINE_EXTABLE_TYPE_REG \
++      ".purgem extable_type_reg\n"
++
+ # define _ASM_EXTABLE_TYPE(from, to, type)                    \
+       " .pushsection \"__ex_table\",\"a\"\n"                  \
+       " .balign 4\n"                                          \
+@@ -155,6 +182,16 @@
+       " .long " __stringify(type) " \n"                       \
+       " .popsection\n"
++# define _ASM_EXTABLE_TYPE_REG(from, to, type, reg)                           \
++      " .pushsection \"__ex_table\",\"a\"\n"                                  \
++      " .balign 4\n"                                                          \
++      " .long (" #from ") - .\n"                                              \
++      " .long (" #to ") - .\n"                                                \
++      DEFINE_EXTABLE_TYPE_REG                                                 \
++      "extable_type_reg reg=" __stringify(reg) ", type=" __stringify(type) " \n"\
++      UNDEFINE_EXTABLE_TYPE_REG                                               \
++      " .popsection\n"
++
+ /* For C file, we already have NOKPROBE_SYMBOL macro */
+ /*
+diff --git a/arch/x86/include/asm/extable.h b/arch/x86/include/asm/extable.h
+index 93f400eb728f..155c991ba95e 100644
+--- a/arch/x86/include/asm/extable.h
++++ b/arch/x86/include/asm/extable.h
+@@ -21,7 +21,7 @@
+  */
+ struct exception_table_entry {
+-      int insn, fixup, type;
++      int insn, fixup, data;
+ };
+ struct pt_regs;
+@@ -31,8 +31,8 @@ struct pt_regs;
+       do {                                                    \
+               (a)->fixup = (b)->fixup + (delta);              \
+               (b)->fixup = (tmp).fixup - (delta);             \
+-              (a)->type = (b)->type;                          \
+-              (b)->type = (tmp).type;                         \
++              (a)->data = (b)->data;                          \
++              (b)->data = (tmp).data;                         \
+       } while (0)
+ extern int fixup_exception(struct pt_regs *regs, int trapnr,
+diff --git a/arch/x86/include/asm/extable_fixup_types.h b/arch/x86/include/asm/extable_fixup_types.h
+index 4d709a2768bb..944f8329022a 100644
+--- a/arch/x86/include/asm/extable_fixup_types.h
++++ b/arch/x86/include/asm/extable_fixup_types.h
+@@ -2,6 +2,29 @@
+ #ifndef _ASM_X86_EXTABLE_FIXUP_TYPES_H
+ #define _ASM_X86_EXTABLE_FIXUP_TYPES_H
++/*
++ * Our IMM is signed, as such it must live at the top end of the word. Also,
++ * since C99 hex constants are of ambigious type, force cast the mask to 'int'
++ * so that FIELD_GET() will DTRT and sign extend the value when it extracts it.
++ */
++#define EX_DATA_TYPE_MASK             ((int)0x000000FF)
++#define EX_DATA_REG_MASK              ((int)0x00000F00)
++#define EX_DATA_FLAG_MASK             ((int)0x0000F000)
++#define EX_DATA_IMM_MASK              ((int)0xFFFF0000)
++
++#define EX_DATA_REG_SHIFT             8
++#define EX_DATA_FLAG_SHIFT            12
++#define EX_DATA_IMM_SHIFT             16
++
++#define EX_DATA_FLAG(flag)            ((flag) << EX_DATA_FLAG_SHIFT)
++#define EX_DATA_IMM(imm)              ((imm) << EX_DATA_IMM_SHIFT)
++
++/* flags */
++#define EX_FLAG_CLEAR_AX              EX_DATA_FLAG(1)
++#define EX_FLAG_CLEAR_DX              EX_DATA_FLAG(2)
++#define EX_FLAG_CLEAR_AX_DX           EX_DATA_FLAG(3)
++
++/* types */
+ #define       EX_TYPE_NONE                     0
+ #define       EX_TYPE_DEFAULT                  1
+ #define       EX_TYPE_FAULT                    2
+@@ -20,5 +43,6 @@
+ #define       EX_TYPE_FAULT_MCE_SAFE          13
+ #define       EX_TYPE_POP_ZERO                14
++#define       EX_TYPE_IMM_REG                 15 /* reg := (long)imm */
+ #endif
+diff --git a/arch/x86/include/asm/insn-eval.h b/arch/x86/include/asm/insn-eval.h
+index 4ec3613551e3..3df123f437c9 100644
+--- a/arch/x86/include/asm/insn-eval.h
++++ b/arch/x86/include/asm/insn-eval.h
+@@ -15,6 +15,8 @@
+ #define INSN_CODE_SEG_OPND_SZ(params) (params & 0xf)
+ #define INSN_CODE_SEG_PARAMS(oper_sz, addr_sz) (oper_sz | (addr_sz << 4))
++int pt_regs_offset(struct pt_regs *regs, int regno);
++
+ bool insn_has_rep_prefix(struct insn *insn);
+ void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs);
+ int insn_get_modrm_rm_off(struct insn *insn, struct pt_regs *regs);
+diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c
+index eb3ccffb9b9d..7760d228041b 100644
+--- a/arch/x86/lib/insn-eval.c
++++ b/arch/x86/lib/insn-eval.c
+@@ -412,32 +412,39 @@ static short get_segment_selector(struct pt_regs *regs, int seg_reg_idx)
+ #endif /* CONFIG_X86_64 */
+ }
+-static int get_reg_offset(struct insn *insn, struct pt_regs *regs,
+-                        enum reg_type type)
++static const int pt_regoff[] = {
++      offsetof(struct pt_regs, ax),
++      offsetof(struct pt_regs, cx),
++      offsetof(struct pt_regs, dx),
++      offsetof(struct pt_regs, bx),
++      offsetof(struct pt_regs, sp),
++      offsetof(struct pt_regs, bp),
++      offsetof(struct pt_regs, si),
++      offsetof(struct pt_regs, di),
++#ifdef CONFIG_X86_64
++      offsetof(struct pt_regs, r8),
++      offsetof(struct pt_regs, r9),
++      offsetof(struct pt_regs, r10),
++      offsetof(struct pt_regs, r11),
++      offsetof(struct pt_regs, r12),
++      offsetof(struct pt_regs, r13),
++      offsetof(struct pt_regs, r14),
++      offsetof(struct pt_regs, r15),
++#endif
++};
++
++int pt_regs_offset(struct pt_regs *regs, int regno)
+ {
++      if ((unsigned)regno < ARRAY_SIZE(pt_regoff))
++              return pt_regoff[regno];
++      return -EDOM;
++}
++
++static int get_regno(struct insn *insn, enum reg_type type)
++{
++      int nr_registers = ARRAY_SIZE(pt_regoff);
+       int regno = 0;
+-      static const int regoff[] = {
+-              offsetof(struct pt_regs, ax),
+-              offsetof(struct pt_regs, cx),
+-              offsetof(struct pt_regs, dx),
+-              offsetof(struct pt_regs, bx),
+-              offsetof(struct pt_regs, sp),
+-              offsetof(struct pt_regs, bp),
+-              offsetof(struct pt_regs, si),
+-              offsetof(struct pt_regs, di),
+-#ifdef CONFIG_X86_64
+-              offsetof(struct pt_regs, r8),
+-              offsetof(struct pt_regs, r9),
+-              offsetof(struct pt_regs, r10),
+-              offsetof(struct pt_regs, r11),
+-              offsetof(struct pt_regs, r12),
+-              offsetof(struct pt_regs, r13),
+-              offsetof(struct pt_regs, r14),
+-              offsetof(struct pt_regs, r15),
+-#endif
+-      };
+-      int nr_registers = ARRAY_SIZE(regoff);
+       /*
+        * Don't possibly decode a 32-bit instructions as
+        * reading a 64-bit-only register.
+@@ -505,7 +512,18 @@ static int get_reg_offset(struct insn *insn, struct pt_regs *regs,
+               WARN_ONCE(1, "decoded an instruction with an invalid register");
+               return -EINVAL;
+       }
+-      return regoff[regno];
++      return regno;
++}
++
++static int get_reg_offset(struct insn *insn, struct pt_regs *regs,
++                        enum reg_type type)
++{
++      int regno = get_regno(insn, type);
++
++      if (regno < 0)
++              return regno;
++
++      return pt_regs_offset(regs, regno);
+ }
+ /**
+diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c
+index f59a4d017070..251732113624 100644
+--- a/arch/x86/mm/extable.c
++++ b/arch/x86/mm/extable.c
+@@ -2,12 +2,25 @@
+ #include <linux/extable.h>
+ #include <linux/uaccess.h>
+ #include <linux/sched/debug.h>
++#include <linux/bitfield.h>
+ #include <xen/xen.h>
+ #include <asm/fpu/internal.h>
+ #include <asm/sev.h>
+ #include <asm/traps.h>
+ #include <asm/kdebug.h>
++#include <asm/insn-eval.h>
++
++static inline unsigned long *pt_regs_nr(struct pt_regs *regs, int nr)
++{
++      int reg_offset = pt_regs_offset(regs, nr);
++      static unsigned long __dummy;
++
++      if (WARN_ON_ONCE(reg_offset < 0))
++              return &__dummy;
++
++      return (unsigned long *)((unsigned long)regs + reg_offset);
++}
+ static inline unsigned long
+ ex_fixup_addr(const struct exception_table_entry *x)
+@@ -15,10 +28,15 @@ ex_fixup_addr(const struct exception_table_entry *x)
+       return (unsigned long)&x->fixup + x->fixup;
+ }
+-static bool ex_handler_default(const struct exception_table_entry *fixup,
++static bool ex_handler_default(const struct exception_table_entry *e,
+                              struct pt_regs *regs)
+ {
+-      regs->ip = ex_fixup_addr(fixup);
++      if (e->data & EX_FLAG_CLEAR_AX)
++              regs->ax = 0;
++      if (e->data & EX_FLAG_CLEAR_DX)
++              regs->dx = 0;
++
++      regs->ip = ex_fixup_addr(e);
+       return true;
+ }
+@@ -111,17 +129,25 @@ static bool ex_handler_pop_zero(const struct exception_table_entry *fixup,
+       return ex_handler_default(fixup, regs);
+ }
++static bool ex_handler_imm_reg(const struct exception_table_entry *fixup,
++                             struct pt_regs *regs, int reg, int imm)
++{
++      *pt_regs_nr(regs, reg) = (long)imm;
++      return ex_handler_default(fixup, regs);
++}
++
+ int ex_get_fixup_type(unsigned long ip)
+ {
+       const struct exception_table_entry *e = search_exception_tables(ip);
+-      return e ? e->type : EX_TYPE_NONE;
++      return e ? FIELD_GET(EX_DATA_TYPE_MASK, e->data) : EX_TYPE_NONE;
+ }
+ int fixup_exception(struct pt_regs *regs, int trapnr, unsigned long error_code,
+                   unsigned long fault_addr)
+ {
+       const struct exception_table_entry *e;
++      int type, reg, imm;
+ #ifdef CONFIG_PNPBIOS
+       if (unlikely(SEGMENT_IS_PNP_CODE(regs->cs))) {
+@@ -141,7 +167,11 @@ int fixup_exception(struct pt_regs *regs, int trapnr, unsigned long error_code,
+       if (!e)
+               return 0;
+-      switch (e->type) {
++      type = FIELD_GET(EX_DATA_TYPE_MASK, e->data);
++      reg  = FIELD_GET(EX_DATA_REG_MASK,  e->data);
++      imm  = FIELD_GET(EX_DATA_IMM_MASK,  e->data);
++
++      switch (type) {
+       case EX_TYPE_DEFAULT:
+       case EX_TYPE_DEFAULT_MCE_SAFE:
+               return ex_handler_default(e, regs);
+@@ -170,6 +200,8 @@ int fixup_exception(struct pt_regs *regs, int trapnr, unsigned long error_code,
+               break;
+       case EX_TYPE_POP_ZERO:
+               return ex_handler_pop_zero(e, regs);
++      case EX_TYPE_IMM_REG:
++              return ex_handler_imm_reg(e, regs, reg, imm);
+       }
+       BUG();
+ }
+diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
+index 4f3a60037150..dccaab2113f9 100644
+--- a/arch/x86/net/bpf_jit_comp.c
++++ b/arch/x86/net/bpf_jit_comp.c
+@@ -1342,7 +1342,7 @@ st:                      if (is_imm8(insn->off))
+                               }
+                               ex->insn = delta;
+-                              ex->type = EX_TYPE_BPF;
++                              ex->data = EX_TYPE_BPF;
+                               if (dst_reg > BPF_REG_9) {
+                                       pr_err("verifier error\n");
+-- 
+2.35.1
+
diff --git a/queue-5.15/x86-extable-get-rid-of-redundant-macros.patch b/queue-5.15/x86-extable-get-rid-of-redundant-macros.patch
new file mode 100644 (file)
index 0000000..9bdc922
--- /dev/null
@@ -0,0 +1,84 @@
+From 7aa07863a71fb723dd25779d2457479386d7e4e3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 Sep 2021 15:29:13 +0200
+Subject: x86/extable: Get rid of redundant macros
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+[ Upstream commit 32fd8b59f91fcd3bf9459aa72d90345735cc2588 ]
+
+No point in defining the identical macros twice depending on C or assembly
+mode. They are still identical.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Link: https://lkml.kernel.org/r/20210908132525.023659534@linutronix.de
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/include/asm/asm.h | 36 ++++++++++++------------------------
+ 1 file changed, 12 insertions(+), 24 deletions(-)
+
+diff --git a/arch/x86/include/asm/asm.h b/arch/x86/include/asm/asm.h
+index 3ad3da9a7d97..719955e658a2 100644
+--- a/arch/x86/include/asm/asm.h
++++ b/arch/x86/include/asm/asm.h
+@@ -132,18 +132,6 @@
+       .long (handler) - . ;                                   \
+       .popsection
+-# define _ASM_EXTABLE(from, to)                                       \
+-      _ASM_EXTABLE_HANDLE(from, to, ex_handler_default)
+-
+-# define _ASM_EXTABLE_UA(from, to)                            \
+-      _ASM_EXTABLE_HANDLE(from, to, ex_handler_uaccess)
+-
+-# define _ASM_EXTABLE_CPY(from, to)                           \
+-      _ASM_EXTABLE_HANDLE(from, to, ex_handler_copy)
+-
+-# define _ASM_EXTABLE_FAULT(from, to)                         \
+-      _ASM_EXTABLE_HANDLE(from, to, ex_handler_fault)
+-
+ # ifdef CONFIG_KPROBES
+ #  define _ASM_NOKPROBE(entry)                                        \
+       .pushsection "_kprobe_blacklist","aw" ;                 \
+@@ -164,18 +152,6 @@
+       " .long (" _EXPAND_EXTABLE_HANDLE(handler) ") - .\n"    \
+       " .popsection\n"
+-# define _ASM_EXTABLE(from, to)                                       \
+-      _ASM_EXTABLE_HANDLE(from, to, ex_handler_default)
+-
+-# define _ASM_EXTABLE_UA(from, to)                            \
+-      _ASM_EXTABLE_HANDLE(from, to, ex_handler_uaccess)
+-
+-# define _ASM_EXTABLE_CPY(from, to)                           \
+-      _ASM_EXTABLE_HANDLE(from, to, ex_handler_copy)
+-
+-# define _ASM_EXTABLE_FAULT(from, to)                         \
+-      _ASM_EXTABLE_HANDLE(from, to, ex_handler_fault)
+-
+ /* For C file, we already have NOKPROBE_SYMBOL macro */
+ /*
+@@ -188,6 +164,18 @@ register unsigned long current_stack_pointer asm(_ASM_SP);
+ #define ASM_CALL_CONSTRAINT "+r" (current_stack_pointer)
+ #endif /* __ASSEMBLY__ */
++#define _ASM_EXTABLE(from, to)                                        \
++      _ASM_EXTABLE_HANDLE(from, to, ex_handler_default)
++
++#define _ASM_EXTABLE_UA(from, to)                             \
++      _ASM_EXTABLE_HANDLE(from, to, ex_handler_uaccess)
++
++#define _ASM_EXTABLE_CPY(from, to)                            \
++      _ASM_EXTABLE_HANDLE(from, to, ex_handler_copy)
++
++#define _ASM_EXTABLE_FAULT(from, to)                          \
++      _ASM_EXTABLE_HANDLE(from, to, ex_handler_fault)
++
+ #endif /* __KERNEL__ */
+ #endif /* _ASM_X86_ASM_H */
+-- 
+2.35.1
+
diff --git a/queue-5.15/x86-extable-provide-ex_type_default_mce_safe-and-ex_.patch b/queue-5.15/x86-extable-provide-ex_type_default_mce_safe-and-ex_.patch
new file mode 100644 (file)
index 0000000..252a2b4
--- /dev/null
@@ -0,0 +1,69 @@
+From a8cb7913e1c09d3ca5ff12f408d26b1a5fb57fb0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 Sep 2021 15:29:19 +0200
+Subject: x86/extable: Provide EX_TYPE_DEFAULT_MCE_SAFE and
+ EX_TYPE_FAULT_MCE_SAFE
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+[ Upstream commit 2cadf5248b9316d3c8af876e795d61c55476f6e9 ]
+
+Provide exception fixup types which can be used to identify fixups which
+allow in kernel #MC recovery and make them invoke the existing handlers.
+
+These will be used at places where #MC recovery is handled correctly by the
+caller.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Link: https://lkml.kernel.org/r/20210908132525.269689153@linutronix.de
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/include/asm/extable_fixup_types.h | 3 +++
+ arch/x86/kernel/cpu/mce/severity.c         | 2 ++
+ arch/x86/mm/extable.c                      | 2 ++
+ 3 files changed, 7 insertions(+)
+
+diff --git a/arch/x86/include/asm/extable_fixup_types.h b/arch/x86/include/asm/extable_fixup_types.h
+index 0adc117618e6..409524d5d2eb 100644
+--- a/arch/x86/include/asm/extable_fixup_types.h
++++ b/arch/x86/include/asm/extable_fixup_types.h
+@@ -16,4 +16,7 @@
+ #define       EX_TYPE_WRMSR_IN_MCE            10
+ #define       EX_TYPE_RDMSR_IN_MCE            11
++#define       EX_TYPE_DEFAULT_MCE_SAFE        12
++#define       EX_TYPE_FAULT_MCE_SAFE          13
++
+ #endif
+diff --git a/arch/x86/kernel/cpu/mce/severity.c b/arch/x86/kernel/cpu/mce/severity.c
+index 74fe763bffda..d9b77a74f8d2 100644
+--- a/arch/x86/kernel/cpu/mce/severity.c
++++ b/arch/x86/kernel/cpu/mce/severity.c
+@@ -278,6 +278,8 @@ static int error_context(struct mce *m, struct pt_regs *regs)
+               m->kflags |= MCE_IN_KERNEL_COPYIN;
+               fallthrough;
+       case EX_TYPE_FAULT:
++      case EX_TYPE_FAULT_MCE_SAFE:
++      case EX_TYPE_DEFAULT_MCE_SAFE:
+               m->kflags |= MCE_IN_KERNEL_RECOV;
+               return IN_KERNEL_RECOV;
+       default:
+diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c
+index 5db46df409b5..f37e290e6d0a 100644
+--- a/arch/x86/mm/extable.c
++++ b/arch/x86/mm/extable.c
+@@ -131,8 +131,10 @@ int fixup_exception(struct pt_regs *regs, int trapnr, unsigned long error_code,
+       switch (e->type) {
+       case EX_TYPE_DEFAULT:
++      case EX_TYPE_DEFAULT_MCE_SAFE:
+               return ex_handler_default(e, regs);
+       case EX_TYPE_FAULT:
++      case EX_TYPE_FAULT_MCE_SAFE:
+               return ex_handler_fault(e, regs, trapnr);
+       case EX_TYPE_UACCESS:
+               return ex_handler_uaccess(e, regs, trapnr);
+-- 
+2.35.1
+
diff --git a/queue-5.15/x86-extable-provide-ex_type_default_mce_safe-and-ex_.patch-2687 b/queue-5.15/x86-extable-provide-ex_type_default_mce_safe-and-ex_.patch-2687
new file mode 100644 (file)
index 0000000..5e90a22
--- /dev/null
@@ -0,0 +1,39 @@
+From 53d65cb5022c6e46747335a85b4b638a26a9ca0d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 Sep 2021 15:29:19 +0200
+Subject: x86/extable: Provide EX_TYPE_DEFAULT_MCE_SAFE and
+ EX_TYPE_FAULT_MCE_SAFE
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+[ Upstream commit 2cadf5248b9316d3c8af876e795d61c55476f6e9 ]
+
+Provide exception fixup types which can be used to identify fixups which
+allow in kernel #MC recovery and make them invoke the existing handlers.
+
+These will be used at places where #MC recovery is handled correctly by the
+caller.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Link: https://lkml.kernel.org/r/20210908132525.269689153@linutronix.de
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/include/asm/extable_fixup_types.h | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/arch/x86/include/asm/extable_fixup_types.h b/arch/x86/include/asm/extable_fixup_types.h
+index 7469038de100..82c263f74971 100644
+--- a/arch/x86/include/asm/extable_fixup_types.h
++++ b/arch/x86/include/asm/extable_fixup_types.h
+@@ -46,4 +46,7 @@
+ #define       EX_TYPE_IMM_REG                 17 /* reg := (long)imm */
+ #define       EX_TYPE_EFAULT_REG              (EX_TYPE_IMM_REG | EX_DATA_IMM(-EFAULT))
++#define       EX_TYPE_DEFAULT_MCE_SAFE        12
++#define       EX_TYPE_FAULT_MCE_SAFE          13
++
+ #endif
+-- 
+2.35.1
+
diff --git a/queue-5.15/x86-extable-rework-the-exception-table-mechanics.patch b/queue-5.15/x86-extable-rework-the-exception-table-mechanics.patch
new file mode 100644 (file)
index 0000000..daf5dbc
--- /dev/null
@@ -0,0 +1,665 @@
+From fb7315cf41170c88c38982a20db3e321ea9b9663 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 Sep 2021 15:29:18 +0200
+Subject: x86/extable: Rework the exception table mechanics
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+[ Upstream commit 46d28947d9876fc0f8f93d3c69813ef6e9852595 ]
+
+The exception table entries contain the instruction address, the fixup
+address and the handler address. All addresses are relative. Storing the
+handler address has a few downsides:
+
+ 1) Most handlers need to be exported
+
+ 2) Handlers can be defined everywhere and there is no overview about the
+    handler types
+
+ 3) MCE needs to check the handler type to decide whether an in kernel #MC
+    can be recovered. The functionality of the handler itself is not in any
+    way special, but for these checks there need to be separate functions
+    which in the worst case have to be exported.
+
+    Some of these 'recoverable' exception fixups are pretty obscure and
+    just reuse some other handler to spare code. That obfuscates e.g. the
+    #MC safe copy functions. Cleaning that up would require more handlers
+    and exports
+
+Rework the exception fixup mechanics by storing a fixup type number instead
+of the handler address and invoke the proper handler for each fixup
+type. Also teach the extable sort to leave the type field alone.
+
+This makes most handlers static except for special cases like the MCE
+MSR fixup and the BPF fixup. This allows to add more types for cleaning up
+the obscure places without adding more handler code and exports.
+
+There is a marginal code size reduction for a production config and it
+removes _eight_ exported symbols.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Acked-by: Alexei Starovoitov <ast@kernel.org>
+Link: https://lkml.kernel.org/r/20210908132525.211958725@linutronix.de
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/include/asm/asm.h                 |  22 ++--
+ arch/x86/include/asm/extable.h             |  44 +++++---
+ arch/x86/include/asm/extable_fixup_types.h |  19 ++++
+ arch/x86/include/asm/fpu/internal.h        |   4 +-
+ arch/x86/include/asm/msr.h                 |   4 +-
+ arch/x86/include/asm/segment.h             |   2 +-
+ arch/x86/kernel/cpu/mce/core.c             |  24 +---
+ arch/x86/kernel/cpu/mce/internal.h         |  10 --
+ arch/x86/kernel/cpu/mce/severity.c         |  21 ++--
+ arch/x86/mm/extable.c                      | 123 +++++++++------------
+ arch/x86/net/bpf_jit_comp.c                |  11 +-
+ scripts/sorttable.c                        |   4 +-
+ 12 files changed, 133 insertions(+), 155 deletions(-)
+ create mode 100644 arch/x86/include/asm/extable_fixup_types.h
+
+diff --git a/arch/x86/include/asm/asm.h b/arch/x86/include/asm/asm.h
+index 719955e658a2..6aadb9a620ee 100644
+--- a/arch/x86/include/asm/asm.h
++++ b/arch/x86/include/asm/asm.h
+@@ -122,14 +122,17 @@
+ #ifdef __KERNEL__
++# include <asm/extable_fixup_types.h>
++
+ /* Exception table entry */
+ #ifdef __ASSEMBLY__
+-# define _ASM_EXTABLE_HANDLE(from, to, handler)                       \
++
++# define _ASM_EXTABLE_TYPE(from, to, type)                    \
+       .pushsection "__ex_table","a" ;                         \
+       .balign 4 ;                                             \
+       .long (from) - . ;                                      \
+       .long (to) - . ;                                        \
+-      .long (handler) - . ;                                   \
++      .long type ;                                            \
+       .popsection
+ # ifdef CONFIG_KPROBES
+@@ -143,13 +146,13 @@
+ # endif
+ #else /* ! __ASSEMBLY__ */
+-# define _EXPAND_EXTABLE_HANDLE(x) #x
+-# define _ASM_EXTABLE_HANDLE(from, to, handler)                       \
++
++# define _ASM_EXTABLE_TYPE(from, to, type)                    \
+       " .pushsection \"__ex_table\",\"a\"\n"                  \
+       " .balign 4\n"                                          \
+       " .long (" #from ") - .\n"                              \
+       " .long (" #to ") - .\n"                                \
+-      " .long (" _EXPAND_EXTABLE_HANDLE(handler) ") - .\n"    \
++      " .long " __stringify(type) " \n"                       \
+       " .popsection\n"
+ /* For C file, we already have NOKPROBE_SYMBOL macro */
+@@ -165,17 +168,16 @@ register unsigned long current_stack_pointer asm(_ASM_SP);
+ #endif /* __ASSEMBLY__ */
+ #define _ASM_EXTABLE(from, to)                                        \
+-      _ASM_EXTABLE_HANDLE(from, to, ex_handler_default)
++      _ASM_EXTABLE_TYPE(from, to, EX_TYPE_DEFAULT)
+ #define _ASM_EXTABLE_UA(from, to)                             \
+-      _ASM_EXTABLE_HANDLE(from, to, ex_handler_uaccess)
++      _ASM_EXTABLE_TYPE(from, to, EX_TYPE_UACCESS)
+ #define _ASM_EXTABLE_CPY(from, to)                            \
+-      _ASM_EXTABLE_HANDLE(from, to, ex_handler_copy)
++      _ASM_EXTABLE_TYPE(from, to, EX_TYPE_COPY)
+ #define _ASM_EXTABLE_FAULT(from, to)                          \
+-      _ASM_EXTABLE_HANDLE(from, to, ex_handler_fault)
++      _ASM_EXTABLE_TYPE(from, to, EX_TYPE_FAULT)
+ #endif /* __KERNEL__ */
+-
+ #endif /* _ASM_X86_ASM_H */
+diff --git a/arch/x86/include/asm/extable.h b/arch/x86/include/asm/extable.h
+index 1f0cbc52937c..93f400eb728f 100644
+--- a/arch/x86/include/asm/extable.h
++++ b/arch/x86/include/asm/extable.h
+@@ -1,12 +1,18 @@
+ /* SPDX-License-Identifier: GPL-2.0 */
+ #ifndef _ASM_X86_EXTABLE_H
+ #define _ASM_X86_EXTABLE_H
++
++#include <asm/extable_fixup_types.h>
++
+ /*
+- * The exception table consists of triples of addresses relative to the
+- * exception table entry itself. The first address is of an instruction
+- * that is allowed to fault, the second is the target at which the program
+- * should continue. The third is a handler function to deal with the fault
+- * caused by the instruction in the first field.
++ * The exception table consists of two addresses relative to the
++ * exception table entry itself and a type selector field.
++ *
++ * The first address is of an instruction that is allowed to fault, the
++ * second is the target at which the program should continue.
++ *
++ * The type entry is used by fixup_exception() to select the handler to
++ * deal with the fault caused by the instruction in the first field.
+  *
+  * All the routines below use bits of fixup code that are out of line
+  * with the main instruction path.  This means when everything is well,
+@@ -15,7 +21,7 @@
+  */
+ struct exception_table_entry {
+-      int insn, fixup, handler;
++      int insn, fixup, type;
+ };
+ struct pt_regs;
+@@ -25,21 +31,27 @@ struct pt_regs;
+       do {                                                    \
+               (a)->fixup = (b)->fixup + (delta);              \
+               (b)->fixup = (tmp).fixup - (delta);             \
+-              (a)->handler = (b)->handler + (delta);          \
+-              (b)->handler = (tmp).handler - (delta);         \
++              (a)->type = (b)->type;                          \
++              (b)->type = (tmp).type;                         \
+       } while (0)
+-enum handler_type {
+-      EX_HANDLER_NONE,
+-      EX_HANDLER_FAULT,
+-      EX_HANDLER_UACCESS,
+-      EX_HANDLER_OTHER
+-};
+-
+ extern int fixup_exception(struct pt_regs *regs, int trapnr,
+                          unsigned long error_code, unsigned long fault_addr);
+ extern int fixup_bug(struct pt_regs *regs, int trapnr);
+-extern enum handler_type ex_get_fault_handler_type(unsigned long ip);
++extern int ex_get_fixup_type(unsigned long ip);
+ extern void early_fixup_exception(struct pt_regs *regs, int trapnr);
++#ifdef CONFIG_X86_MCE
++extern void ex_handler_msr_mce(struct pt_regs *regs, bool wrmsr);
++#else
++static inline void ex_handler_msr_mce(struct pt_regs *regs, bool wrmsr) { }
++#endif
++
++#if defined(CONFIG_BPF_JIT) && defined(CONFIG_X86_64)
++bool ex_handler_bpf(const struct exception_table_entry *x, struct pt_regs *regs);
++#else
++static inline bool ex_handler_bpf(const struct exception_table_entry *x,
++                                struct pt_regs *regs) { return false; }
++#endif
++
+ #endif
+diff --git a/arch/x86/include/asm/extable_fixup_types.h b/arch/x86/include/asm/extable_fixup_types.h
+new file mode 100644
+index 000000000000..0adc117618e6
+--- /dev/null
++++ b/arch/x86/include/asm/extable_fixup_types.h
+@@ -0,0 +1,19 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++#ifndef _ASM_X86_EXTABLE_FIXUP_TYPES_H
++#define _ASM_X86_EXTABLE_FIXUP_TYPES_H
++
++#define       EX_TYPE_NONE                     0
++#define       EX_TYPE_DEFAULT                  1
++#define       EX_TYPE_FAULT                    2
++#define       EX_TYPE_UACCESS                  3
++#define       EX_TYPE_COPY                     4
++#define       EX_TYPE_CLEAR_FS                 5
++#define       EX_TYPE_FPU_RESTORE              6
++#define       EX_TYPE_WRMSR                    7
++#define       EX_TYPE_RDMSR                    8
++#define       EX_TYPE_BPF                      9
++
++#define       EX_TYPE_WRMSR_IN_MCE            10
++#define       EX_TYPE_RDMSR_IN_MCE            11
++
++#endif
+diff --git a/arch/x86/include/asm/fpu/internal.h b/arch/x86/include/asm/fpu/internal.h
+index 5a18694a89b2..ce6fc4f8d1d1 100644
+--- a/arch/x86/include/asm/fpu/internal.h
++++ b/arch/x86/include/asm/fpu/internal.h
+@@ -126,7 +126,7 @@ extern void save_fpregs_to_fpstate(struct fpu *fpu);
+ #define kernel_insn(insn, output, input...)                           \
+       asm volatile("1:" #insn "\n\t"                                  \
+                    "2:\n"                                             \
+-                   _ASM_EXTABLE_HANDLE(1b, 2b, ex_handler_fprestore)  \
++                   _ASM_EXTABLE_TYPE(1b, 2b, EX_TYPE_FPU_RESTORE)     \
+                    : output : input)
+ static inline int fnsave_to_user_sigframe(struct fregs_state __user *fx)
+@@ -253,7 +253,7 @@ static inline void fxsave(struct fxregs_state *fx)
+                                XRSTORS, X86_FEATURE_XSAVES)           \
+                    "\n"                                               \
+                    "3:\n"                                             \
+-                   _ASM_EXTABLE_HANDLE(661b, 3b, ex_handler_fprestore)\
++                   _ASM_EXTABLE_TYPE(661b, 3b, EX_TYPE_FPU_RESTORE)   \
+                    :                                                  \
+                    : "D" (st), "m" (*st), "a" (lmask), "d" (hmask)    \
+                    : "memory")
+diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h
+index a3f87f1015d3..6b52182e178a 100644
+--- a/arch/x86/include/asm/msr.h
++++ b/arch/x86/include/asm/msr.h
+@@ -92,7 +92,7 @@ static __always_inline unsigned long long __rdmsr(unsigned int msr)
+       asm volatile("1: rdmsr\n"
+                    "2:\n"
+-                   _ASM_EXTABLE_HANDLE(1b, 2b, ex_handler_rdmsr_unsafe)
++                   _ASM_EXTABLE_TYPE(1b, 2b, EX_TYPE_RDMSR)
+                    : EAX_EDX_RET(val, low, high) : "c" (msr));
+       return EAX_EDX_VAL(val, low, high);
+@@ -102,7 +102,7 @@ static __always_inline void __wrmsr(unsigned int msr, u32 low, u32 high)
+ {
+       asm volatile("1: wrmsr\n"
+                    "2:\n"
+-                   _ASM_EXTABLE_HANDLE(1b, 2b, ex_handler_wrmsr_unsafe)
++                   _ASM_EXTABLE_TYPE(1b, 2b, EX_TYPE_WRMSR)
+                    : : "c" (msr), "a"(low), "d" (high) : "memory");
+ }
+diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h
+index 72044026eb3c..8dd8e8ec9fa5 100644
+--- a/arch/x86/include/asm/segment.h
++++ b/arch/x86/include/asm/segment.h
+@@ -339,7 +339,7 @@ static inline void __loadsegment_fs(unsigned short value)
+                    "1:        movw %0, %%fs                   \n"
+                    "2:                                        \n"
+-                   _ASM_EXTABLE_HANDLE(1b, 2b, ex_handler_clear_fs)
++                   _ASM_EXTABLE_TYPE(1b, 2b, EX_TYPE_CLEAR_FS)
+                    : : "rm" (value) : "memory");
+ }
+diff --git a/arch/x86/kernel/cpu/mce/core.c b/arch/x86/kernel/cpu/mce/core.c
+index d8da3acf1ffd..773037e5fd76 100644
+--- a/arch/x86/kernel/cpu/mce/core.c
++++ b/arch/x86/kernel/cpu/mce/core.c
+@@ -382,7 +382,7 @@ static int msr_to_offset(u32 msr)
+       return -1;
+ }
+-static void ex_handler_msr_mce(struct pt_regs *regs, bool wrmsr)
++void ex_handler_msr_mce(struct pt_regs *regs, bool wrmsr)
+ {
+       if (wrmsr) {
+               pr_emerg("MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x) at rIP: 0x%lx (%pS)\n",
+@@ -401,15 +401,6 @@ static void ex_handler_msr_mce(struct pt_regs *regs, bool wrmsr)
+               cpu_relax();
+ }
+-__visible bool ex_handler_rdmsr_fault(const struct exception_table_entry *fixup,
+-                                    struct pt_regs *regs, int trapnr,
+-                                    unsigned long error_code,
+-                                    unsigned long fault_addr)
+-{
+-      ex_handler_msr_mce(regs, false);
+-      return true;
+-}
+-
+ /* MSR access wrappers used for error injection */
+ static noinstr u64 mce_rdmsrl(u32 msr)
+ {
+@@ -439,22 +430,13 @@ static noinstr u64 mce_rdmsrl(u32 msr)
+        */
+       asm volatile("1: rdmsr\n"
+                    "2:\n"
+-                   _ASM_EXTABLE_HANDLE(1b, 2b, ex_handler_rdmsr_fault)
++                   _ASM_EXTABLE_TYPE(1b, 2b, EX_TYPE_RDMSR_IN_MCE)
+                    : EAX_EDX_RET(val, low, high) : "c" (msr));
+       return EAX_EDX_VAL(val, low, high);
+ }
+-__visible bool ex_handler_wrmsr_fault(const struct exception_table_entry *fixup,
+-                                    struct pt_regs *regs, int trapnr,
+-                                    unsigned long error_code,
+-                                    unsigned long fault_addr)
+-{
+-      ex_handler_msr_mce(regs, true);
+-      return true;
+-}
+-
+ static noinstr void mce_wrmsrl(u32 msr, u64 v)
+ {
+       u32 low, high;
+@@ -479,7 +461,7 @@ static noinstr void mce_wrmsrl(u32 msr, u64 v)
+       /* See comment in mce_rdmsrl() */
+       asm volatile("1: wrmsr\n"
+                    "2:\n"
+-                   _ASM_EXTABLE_HANDLE(1b, 2b, ex_handler_wrmsr_fault)
++                   _ASM_EXTABLE_TYPE(1b, 2b, EX_TYPE_WRMSR_IN_MCE)
+                    : : "c" (msr), "a"(low), "d" (high) : "memory");
+ }
+diff --git a/arch/x86/kernel/cpu/mce/internal.h b/arch/x86/kernel/cpu/mce/internal.h
+index 88dcc79cfb07..80dc94313bcf 100644
+--- a/arch/x86/kernel/cpu/mce/internal.h
++++ b/arch/x86/kernel/cpu/mce/internal.h
+@@ -186,14 +186,4 @@ extern bool amd_filter_mce(struct mce *m);
+ static inline bool amd_filter_mce(struct mce *m)                      { return false; };
+ #endif
+-__visible bool ex_handler_rdmsr_fault(const struct exception_table_entry *fixup,
+-                                    struct pt_regs *regs, int trapnr,
+-                                    unsigned long error_code,
+-                                    unsigned long fault_addr);
+-
+-__visible bool ex_handler_wrmsr_fault(const struct exception_table_entry *fixup,
+-                                    struct pt_regs *regs, int trapnr,
+-                                    unsigned long error_code,
+-                                    unsigned long fault_addr);
+-
+ #endif /* __X86_MCE_INTERNAL_H__ */
+diff --git a/arch/x86/kernel/cpu/mce/severity.c b/arch/x86/kernel/cpu/mce/severity.c
+index 17e631443116..74fe763bffda 100644
+--- a/arch/x86/kernel/cpu/mce/severity.c
++++ b/arch/x86/kernel/cpu/mce/severity.c
+@@ -265,25 +265,24 @@ static bool is_copy_from_user(struct pt_regs *regs)
+  */
+ static int error_context(struct mce *m, struct pt_regs *regs)
+ {
+-      enum handler_type t;
+-
+       if ((m->cs & 3) == 3)
+               return IN_USER;
+       if (!mc_recoverable(m->mcgstatus))
+               return IN_KERNEL;
+-      t = ex_get_fault_handler_type(m->ip);
+-      if (t == EX_HANDLER_FAULT) {
+-              m->kflags |= MCE_IN_KERNEL_RECOV;
+-              return IN_KERNEL_RECOV;
+-      }
+-      if (t == EX_HANDLER_UACCESS && regs && is_copy_from_user(regs)) {
+-              m->kflags |= MCE_IN_KERNEL_RECOV;
++      switch (ex_get_fixup_type(m->ip)) {
++      case EX_TYPE_UACCESS:
++      case EX_TYPE_COPY:
++              if (!regs || !is_copy_from_user(regs))
++                      return IN_KERNEL;
+               m->kflags |= MCE_IN_KERNEL_COPYIN;
++              fallthrough;
++      case EX_TYPE_FAULT:
++              m->kflags |= MCE_IN_KERNEL_RECOV;
+               return IN_KERNEL_RECOV;
++      default:
++              return IN_KERNEL;
+       }
+-
+-      return IN_KERNEL;
+ }
+ static int mce_severity_amd_smca(struct mce *m, enum context err_ctx)
+diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c
+index d9a1046f3a98..5db46df409b5 100644
+--- a/arch/x86/mm/extable.c
++++ b/arch/x86/mm/extable.c
+@@ -9,40 +9,25 @@
+ #include <asm/traps.h>
+ #include <asm/kdebug.h>
+-typedef bool (*ex_handler_t)(const struct exception_table_entry *,
+-                          struct pt_regs *, int, unsigned long,
+-                          unsigned long);
+-
+ static inline unsigned long
+ ex_fixup_addr(const struct exception_table_entry *x)
+ {
+       return (unsigned long)&x->fixup + x->fixup;
+ }
+-static inline ex_handler_t
+-ex_fixup_handler(const struct exception_table_entry *x)
+-{
+-      return (ex_handler_t)((unsigned long)&x->handler + x->handler);
+-}
+-__visible bool ex_handler_default(const struct exception_table_entry *fixup,
+-                                struct pt_regs *regs, int trapnr,
+-                                unsigned long error_code,
+-                                unsigned long fault_addr)
++static bool ex_handler_default(const struct exception_table_entry *fixup,
++                             struct pt_regs *regs)
+ {
+       regs->ip = ex_fixup_addr(fixup);
+       return true;
+ }
+-EXPORT_SYMBOL(ex_handler_default);
+-__visible bool ex_handler_fault(const struct exception_table_entry *fixup,
+-                              struct pt_regs *regs, int trapnr,
+-                              unsigned long error_code,
+-                              unsigned long fault_addr)
++static bool ex_handler_fault(const struct exception_table_entry *fixup,
++                           struct pt_regs *regs, int trapnr)
+ {
+       regs->ax = trapnr;
+-      return ex_handler_default(fixup, regs, trapnr, error_code, fault_addr);
++      return ex_handler_default(fixup, regs);
+ }
+-EXPORT_SYMBOL_GPL(ex_handler_fault);
+ /*
+  * Handler for when we fail to restore a task's FPU state.  We should never get
+@@ -54,10 +39,8 @@ EXPORT_SYMBOL_GPL(ex_handler_fault);
+  * of vulnerability by restoring from the initial state (essentially, zeroing
+  * out all the FPU registers) if we can't restore from the task's FPU state.
+  */
+-__visible bool ex_handler_fprestore(const struct exception_table_entry *fixup,
+-                                  struct pt_regs *regs, int trapnr,
+-                                  unsigned long error_code,
+-                                  unsigned long fault_addr)
++static bool ex_handler_fprestore(const struct exception_table_entry *fixup,
++                               struct pt_regs *regs)
+ {
+       regs->ip = ex_fixup_addr(fixup);
+@@ -67,32 +50,23 @@ __visible bool ex_handler_fprestore(const struct exception_table_entry *fixup,
+       __restore_fpregs_from_fpstate(&init_fpstate, xfeatures_mask_fpstate());
+       return true;
+ }
+-EXPORT_SYMBOL_GPL(ex_handler_fprestore);
+-__visible bool ex_handler_uaccess(const struct exception_table_entry *fixup,
+-                                struct pt_regs *regs, int trapnr,
+-                                unsigned long error_code,
+-                                unsigned long fault_addr)
++static bool ex_handler_uaccess(const struct exception_table_entry *fixup,
++                             struct pt_regs *regs, int trapnr)
+ {
+       WARN_ONCE(trapnr == X86_TRAP_GP, "General protection fault in user access. Non-canonical address?");
+-      return ex_handler_default(fixup, regs, trapnr, error_code, fault_addr);
++      return ex_handler_default(fixup, regs);
+ }
+-EXPORT_SYMBOL(ex_handler_uaccess);
+-__visible bool ex_handler_copy(const struct exception_table_entry *fixup,
+-                             struct pt_regs *regs, int trapnr,
+-                             unsigned long error_code,
+-                             unsigned long fault_addr)
++static bool ex_handler_copy(const struct exception_table_entry *fixup,
++                          struct pt_regs *regs, int trapnr)
+ {
+       WARN_ONCE(trapnr == X86_TRAP_GP, "General protection fault in user access. Non-canonical address?");
+-      return ex_handler_fault(fixup, regs, trapnr, error_code, fault_addr);
++      return ex_handler_fault(fixup, regs, trapnr);
+ }
+-EXPORT_SYMBOL(ex_handler_copy);
+-__visible bool ex_handler_rdmsr_unsafe(const struct exception_table_entry *fixup,
+-                                     struct pt_regs *regs, int trapnr,
+-                                     unsigned long error_code,
+-                                     unsigned long fault_addr)
++static bool ex_handler_rdmsr_unsafe(const struct exception_table_entry *fixup,
++                                  struct pt_regs *regs)
+ {
+       if (pr_warn_once("unchecked MSR access error: RDMSR from 0x%x at rIP: 0x%lx (%pS)\n",
+                        (unsigned int)regs->cx, regs->ip, (void *)regs->ip))
+@@ -101,14 +75,11 @@ __visible bool ex_handler_rdmsr_unsafe(const struct exception_table_entry *fixup
+       /* Pretend that the read succeeded and returned 0. */
+       regs->ax = 0;
+       regs->dx = 0;
+-      return ex_handler_default(fixup, regs, trapnr, error_code, fault_addr);
++      return ex_handler_default(fixup, regs);
+ }
+-EXPORT_SYMBOL(ex_handler_rdmsr_unsafe);
+-__visible bool ex_handler_wrmsr_unsafe(const struct exception_table_entry *fixup,
+-                                     struct pt_regs *regs, int trapnr,
+-                                     unsigned long error_code,
+-                                     unsigned long fault_addr)
++static bool ex_handler_wrmsr_unsafe(const struct exception_table_entry *fixup,
++                                  struct pt_regs *regs)
+ {
+       if (pr_warn_once("unchecked MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x) at rIP: 0x%lx (%pS)\n",
+                        (unsigned int)regs->cx, (unsigned int)regs->dx,
+@@ -116,44 +87,29 @@ __visible bool ex_handler_wrmsr_unsafe(const struct exception_table_entry *fixup
+               show_stack_regs(regs);
+       /* Pretend that the write succeeded. */
+-      return ex_handler_default(fixup, regs, trapnr, error_code, fault_addr);
++      return ex_handler_default(fixup, regs);
+ }
+-EXPORT_SYMBOL(ex_handler_wrmsr_unsafe);
+-__visible bool ex_handler_clear_fs(const struct exception_table_entry *fixup,
+-                                 struct pt_regs *regs, int trapnr,
+-                                 unsigned long error_code,
+-                                 unsigned long fault_addr)
++static bool ex_handler_clear_fs(const struct exception_table_entry *fixup,
++                              struct pt_regs *regs)
+ {
+       if (static_cpu_has(X86_BUG_NULL_SEG))
+               asm volatile ("mov %0, %%fs" : : "rm" (__USER_DS));
+       asm volatile ("mov %0, %%fs" : : "rm" (0));
+-      return ex_handler_default(fixup, regs, trapnr, error_code, fault_addr);
++      return ex_handler_default(fixup, regs);
+ }
+-EXPORT_SYMBOL(ex_handler_clear_fs);
+-enum handler_type ex_get_fault_handler_type(unsigned long ip)
++int ex_get_fixup_type(unsigned long ip)
+ {
+-      const struct exception_table_entry *e;
+-      ex_handler_t handler;
++      const struct exception_table_entry *e = search_exception_tables(ip);
+-      e = search_exception_tables(ip);
+-      if (!e)
+-              return EX_HANDLER_NONE;
+-      handler = ex_fixup_handler(e);
+-      if (handler == ex_handler_fault)
+-              return EX_HANDLER_FAULT;
+-      else if (handler == ex_handler_uaccess || handler == ex_handler_copy)
+-              return EX_HANDLER_UACCESS;
+-      else
+-              return EX_HANDLER_OTHER;
++      return e ? e->type : EX_TYPE_NONE;
+ }
+ int fixup_exception(struct pt_regs *regs, int trapnr, unsigned long error_code,
+                   unsigned long fault_addr)
+ {
+       const struct exception_table_entry *e;
+-      ex_handler_t handler;
+ #ifdef CONFIG_PNPBIOS
+       if (unlikely(SEGMENT_IS_PNP_CODE(regs->cs))) {
+@@ -173,8 +129,33 @@ int fixup_exception(struct pt_regs *regs, int trapnr, unsigned long error_code,
+       if (!e)
+               return 0;
+-      handler = ex_fixup_handler(e);
+-      return handler(e, regs, trapnr, error_code, fault_addr);
++      switch (e->type) {
++      case EX_TYPE_DEFAULT:
++              return ex_handler_default(e, regs);
++      case EX_TYPE_FAULT:
++              return ex_handler_fault(e, regs, trapnr);
++      case EX_TYPE_UACCESS:
++              return ex_handler_uaccess(e, regs, trapnr);
++      case EX_TYPE_COPY:
++              return ex_handler_copy(e, regs, trapnr);
++      case EX_TYPE_CLEAR_FS:
++              return ex_handler_clear_fs(e, regs);
++      case EX_TYPE_FPU_RESTORE:
++              return ex_handler_fprestore(e, regs);
++      case EX_TYPE_RDMSR:
++              return ex_handler_rdmsr_unsafe(e, regs);
++      case EX_TYPE_WRMSR:
++              return ex_handler_wrmsr_unsafe(e, regs);
++      case EX_TYPE_BPF:
++              return ex_handler_bpf(e, regs);
++      case EX_TYPE_RDMSR_IN_MCE:
++              ex_handler_msr_mce(regs, false);
++              break;
++      case EX_TYPE_WRMSR_IN_MCE:
++              ex_handler_msr_mce(regs, true);
++              break;
++      }
++      BUG();
+ }
+ extern unsigned int early_recursion_flag;
+diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
+index 131f7ceb54dc..4f3a60037150 100644
+--- a/arch/x86/net/bpf_jit_comp.c
++++ b/arch/x86/net/bpf_jit_comp.c
+@@ -832,9 +832,7 @@ static int emit_atomic(u8 **pprog, u8 atomic_op,
+       return 0;
+ }
+-static bool ex_handler_bpf(const struct exception_table_entry *x,
+-                         struct pt_regs *regs, int trapnr,
+-                         unsigned long error_code, unsigned long fault_addr)
++bool ex_handler_bpf(const struct exception_table_entry *x, struct pt_regs *regs)
+ {
+       u32 reg = x->fixup >> 8;
+@@ -1344,12 +1342,7 @@ st:                     if (is_imm8(insn->off))
+                               }
+                               ex->insn = delta;
+-                              delta = (u8 *)ex_handler_bpf - (u8 *)&ex->handler;
+-                              if (!is_simm32(delta)) {
+-                                      pr_err("extable->handler doesn't fit into 32-bit\n");
+-                                      return -EFAULT;
+-                              }
+-                              ex->handler = delta;
++                              ex->type = EX_TYPE_BPF;
+                               if (dst_reg > BPF_REG_9) {
+                                       pr_err("verifier error\n");
+diff --git a/scripts/sorttable.c b/scripts/sorttable.c
+index 6ee4fa882919..278bb53b325c 100644
+--- a/scripts/sorttable.c
++++ b/scripts/sorttable.c
+@@ -240,7 +240,7 @@ static void x86_sort_relative_table(char *extab_image, int image_size)
+               w(r(loc) + i, loc);
+               w(r(loc + 1) + i + 4, loc + 1);
+-              w(r(loc + 2) + i + 8, loc + 2);
++              /* Don't touch the fixup type */
+               i += sizeof(uint32_t) * 3;
+       }
+@@ -253,7 +253,7 @@ static void x86_sort_relative_table(char *extab_image, int image_size)
+               w(r(loc) - i, loc);
+               w(r(loc + 1) - (i + 4), loc + 1);
+-              w(r(loc + 2) - (i + 8), loc + 2);
++              /* Don't touch the fixup type */
+               i += sizeof(uint32_t) * 3;
+       }
+-- 
+2.35.1
+
diff --git a/queue-5.15/x86-extable-tidy-up-redundant-handler-functions.patch b/queue-5.15/x86-extable-tidy-up-redundant-handler-functions.patch
new file mode 100644 (file)
index 0000000..b3a3f25
--- /dev/null
@@ -0,0 +1,80 @@
+From 19962250ce126724b25c19141bb7ae2ab9fc6946 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 Sep 2021 15:29:12 +0200
+Subject: x86/extable: Tidy up redundant handler functions
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+[ Upstream commit 326b567f82df0c4c8f50092b9af9a3014616fb3c ]
+
+No need to have the same code all over the place.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Link: https://lkml.kernel.org/r/20210908132524.963232825@linutronix.de
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/mm/extable.c | 16 +++++-----------
+ 1 file changed, 5 insertions(+), 11 deletions(-)
+
+diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c
+index e1664e9f969c..d9a1046f3a98 100644
+--- a/arch/x86/mm/extable.c
++++ b/arch/x86/mm/extable.c
+@@ -39,9 +39,8 @@ __visible bool ex_handler_fault(const struct exception_table_entry *fixup,
+                               unsigned long error_code,
+                               unsigned long fault_addr)
+ {
+-      regs->ip = ex_fixup_addr(fixup);
+       regs->ax = trapnr;
+-      return true;
++      return ex_handler_default(fixup, regs, trapnr, error_code, fault_addr);
+ }
+ EXPORT_SYMBOL_GPL(ex_handler_fault);
+@@ -76,8 +75,7 @@ __visible bool ex_handler_uaccess(const struct exception_table_entry *fixup,
+                                 unsigned long fault_addr)
+ {
+       WARN_ONCE(trapnr == X86_TRAP_GP, "General protection fault in user access. Non-canonical address?");
+-      regs->ip = ex_fixup_addr(fixup);
+-      return true;
++      return ex_handler_default(fixup, regs, trapnr, error_code, fault_addr);
+ }
+ EXPORT_SYMBOL(ex_handler_uaccess);
+@@ -87,9 +85,7 @@ __visible bool ex_handler_copy(const struct exception_table_entry *fixup,
+                              unsigned long fault_addr)
+ {
+       WARN_ONCE(trapnr == X86_TRAP_GP, "General protection fault in user access. Non-canonical address?");
+-      regs->ip = ex_fixup_addr(fixup);
+-      regs->ax = trapnr;
+-      return true;
++      return ex_handler_fault(fixup, regs, trapnr, error_code, fault_addr);
+ }
+ EXPORT_SYMBOL(ex_handler_copy);
+@@ -103,10 +99,9 @@ __visible bool ex_handler_rdmsr_unsafe(const struct exception_table_entry *fixup
+               show_stack_regs(regs);
+       /* Pretend that the read succeeded and returned 0. */
+-      regs->ip = ex_fixup_addr(fixup);
+       regs->ax = 0;
+       regs->dx = 0;
+-      return true;
++      return ex_handler_default(fixup, regs, trapnr, error_code, fault_addr);
+ }
+ EXPORT_SYMBOL(ex_handler_rdmsr_unsafe);
+@@ -121,8 +116,7 @@ __visible bool ex_handler_wrmsr_unsafe(const struct exception_table_entry *fixup
+               show_stack_regs(regs);
+       /* Pretend that the write succeeded. */
+-      regs->ip = ex_fixup_addr(fixup);
+-      return true;
++      return ex_handler_default(fixup, regs, trapnr, error_code, fault_addr);
+ }
+ EXPORT_SYMBOL(ex_handler_wrmsr_unsafe);
+-- 
+2.35.1
+
diff --git a/queue-5.15/x86-futex-remove-.fixup-usage.patch b/queue-5.15/x86-futex-remove-.fixup-usage.patch
new file mode 100644 (file)
index 0000000..f0405b6
--- /dev/null
@@ -0,0 +1,95 @@
+From ba85de34586b23fe8324d35656f8644f1854a8ae Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 10 Nov 2021 11:01:11 +0100
+Subject: x86/futex: Remove .fixup usage
+
+From: Peter Zijlstra <peterz@infradead.org>
+
+[ Upstream commit 4c132d1d844a53fc4e4b5c34e36ef10d6124b783 ]
+
+Use the new EX_TYPE_IMM_REG to store -EFAULT into the designated 'ret'
+register, this removes the need for anonymous .fixup code.
+
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Reviewed-by: Josh Poimboeuf <jpoimboe@redhat.com>
+Link: https://lore.kernel.org/r/20211110101325.426016322@infradead.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/include/asm/extable_fixup_types.h |  2 ++
+ arch/x86/include/asm/futex.h               | 28 +++++++---------------
+ 2 files changed, 10 insertions(+), 20 deletions(-)
+
+diff --git a/arch/x86/include/asm/extable_fixup_types.h b/arch/x86/include/asm/extable_fixup_types.h
+index 9d597fe1017d..7469038de100 100644
+--- a/arch/x86/include/asm/extable_fixup_types.h
++++ b/arch/x86/include/asm/extable_fixup_types.h
+@@ -42,6 +42,8 @@
+ #define       EX_TYPE_DEFAULT_MCE_SAFE        14
+ #define       EX_TYPE_FAULT_MCE_SAFE          15
+ #define       EX_TYPE_POP_ZERO                16
++
+ #define       EX_TYPE_IMM_REG                 17 /* reg := (long)imm */
++#define       EX_TYPE_EFAULT_REG              (EX_TYPE_IMM_REG | EX_DATA_IMM(-EFAULT))
+ #endif
+diff --git a/arch/x86/include/asm/futex.h b/arch/x86/include/asm/futex.h
+index f9c00110a69a..99d345b686fa 100644
+--- a/arch/x86/include/asm/futex.h
++++ b/arch/x86/include/asm/futex.h
+@@ -17,13 +17,9 @@ do {                                                                \
+       int oldval = 0, ret;                                    \
+       asm volatile("1:\t" insn "\n"                           \
+                    "2:\n"                                     \
+-                   "\t.section .fixup,\"ax\"\n"               \
+-                   "3:\tmov\t%3, %1\n"                        \
+-                   "\tjmp\t2b\n"                              \
+-                   "\t.previous\n"                            \
+-                   _ASM_EXTABLE_UA(1b, 3b)                    \
++                   _ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_EFAULT_REG, %1) \
+                    : "=r" (oldval), "=r" (ret), "+m" (*uaddr) \
+-                   : "i" (-EFAULT), "0" (oparg), "1" (0));    \
++                   : "0" (oparg), "1" (0));   \
+       if (ret)                                                \
+               goto label;                                     \
+       *oval = oldval;                                         \
+@@ -39,15 +35,11 @@ do {                                                               \
+                    "3:\t" LOCK_PREFIX "cmpxchgl %3, %2\n"     \
+                    "\tjnz\t2b\n"                              \
+                    "4:\n"                                     \
+-                   "\t.section .fixup,\"ax\"\n"               \
+-                   "5:\tmov\t%5, %1\n"                        \
+-                   "\tjmp\t4b\n"                              \
+-                   "\t.previous\n"                            \
+-                   _ASM_EXTABLE_UA(1b, 5b)                    \
+-                   _ASM_EXTABLE_UA(3b, 5b)                    \
++                   _ASM_EXTABLE_TYPE_REG(1b, 4b, EX_TYPE_EFAULT_REG, %1) \
++                   _ASM_EXTABLE_TYPE_REG(3b, 4b, EX_TYPE_EFAULT_REG, %1) \
+                    : "=&a" (oldval), "=&r" (ret),             \
+                      "+m" (*uaddr), "=&r" (tem)               \
+-                   : "r" (oparg), "i" (-EFAULT), "1" (0));    \
++                   : "r" (oparg), "1" (0));                   \
+       if (ret)                                                \
+               goto label;                                     \
+       *oval = oldval;                                         \
+@@ -95,15 +87,11 @@ static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+       if (!user_access_begin(uaddr, sizeof(u32)))
+               return -EFAULT;
+       asm volatile("\n"
+-              "1:\t" LOCK_PREFIX "cmpxchgl %4, %2\n"
++              "1:\t" LOCK_PREFIX "cmpxchgl %3, %2\n"
+               "2:\n"
+-              "\t.section .fixup, \"ax\"\n"
+-              "3:\tmov     %3, %0\n"
+-              "\tjmp     2b\n"
+-              "\t.previous\n"
+-              _ASM_EXTABLE_UA(1b, 3b)
++              _ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_EFAULT_REG, %0) \
+               : "+r" (ret), "=a" (oldval), "+m" (*uaddr)
+-              : "i" (-EFAULT), "r" (newval), "1" (oldval)
++              : "r" (newval), "1" (oldval)
+               : "memory"
+       );
+       user_access_end();
+-- 
+2.35.1
+
diff --git a/queue-5.15/x86-mce-deduplicate-exception-handling.patch b/queue-5.15/x86-mce-deduplicate-exception-handling.patch
new file mode 100644 (file)
index 0000000..84f909a
--- /dev/null
@@ -0,0 +1,83 @@
+From 59c536dddffbccd8cd338206c01c9d46dc99496e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 Sep 2021 15:29:15 +0200
+Subject: x86/mce: Deduplicate exception handling
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+[ Upstream commit e42404afc4ca856c48f1e05752541faa3587c472 ]
+
+Prepare code for further simplification. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Link: https://lkml.kernel.org/r/20210908132525.096452100@linutronix.de
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kernel/cpu/mce/core.c | 34 +++++++++++++++++-----------------
+ 1 file changed, 17 insertions(+), 17 deletions(-)
+
+diff --git a/arch/x86/kernel/cpu/mce/core.c b/arch/x86/kernel/cpu/mce/core.c
+index 848cfb013f58..d8da3acf1ffd 100644
+--- a/arch/x86/kernel/cpu/mce/core.c
++++ b/arch/x86/kernel/cpu/mce/core.c
+@@ -382,13 +382,16 @@ static int msr_to_offset(u32 msr)
+       return -1;
+ }
+-__visible bool ex_handler_rdmsr_fault(const struct exception_table_entry *fixup,
+-                                    struct pt_regs *regs, int trapnr,
+-                                    unsigned long error_code,
+-                                    unsigned long fault_addr)
++static void ex_handler_msr_mce(struct pt_regs *regs, bool wrmsr)
+ {
+-      pr_emerg("MSR access error: RDMSR from 0x%x at rIP: 0x%lx (%pS)\n",
+-               (unsigned int)regs->cx, regs->ip, (void *)regs->ip);
++      if (wrmsr) {
++              pr_emerg("MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x) at rIP: 0x%lx (%pS)\n",
++                       (unsigned int)regs->cx, (unsigned int)regs->dx, (unsigned int)regs->ax,
++                       regs->ip, (void *)regs->ip);
++      } else {
++              pr_emerg("MSR access error: RDMSR from 0x%x at rIP: 0x%lx (%pS)\n",
++                       (unsigned int)regs->cx, regs->ip, (void *)regs->ip);
++      }
+       show_stack_regs(regs);
+@@ -396,7 +399,14 @@ __visible bool ex_handler_rdmsr_fault(const struct exception_table_entry *fixup,
+       while (true)
+               cpu_relax();
++}
++__visible bool ex_handler_rdmsr_fault(const struct exception_table_entry *fixup,
++                                    struct pt_regs *regs, int trapnr,
++                                    unsigned long error_code,
++                                    unsigned long fault_addr)
++{
++      ex_handler_msr_mce(regs, false);
+       return true;
+ }
+@@ -441,17 +451,7 @@ __visible bool ex_handler_wrmsr_fault(const struct exception_table_entry *fixup,
+                                     unsigned long error_code,
+                                     unsigned long fault_addr)
+ {
+-      pr_emerg("MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x) at rIP: 0x%lx (%pS)\n",
+-               (unsigned int)regs->cx, (unsigned int)regs->dx, (unsigned int)regs->ax,
+-                regs->ip, (void *)regs->ip);
+-
+-      show_stack_regs(regs);
+-
+-      panic("MCA architectural violation!\n");
+-
+-      while (true)
+-              cpu_relax();
+-
++      ex_handler_msr_mce(regs, true);
+       return true;
+ }
+-- 
+2.35.1
+
diff --git a/queue-5.15/x86-msr-remove-.fixup-usage.patch b/queue-5.15/x86-msr-remove-.fixup-usage.patch
new file mode 100644 (file)
index 0000000..6d934cd
--- /dev/null
@@ -0,0 +1,185 @@
+From 0d99dcd85c36ae7f26fb7af68f3555028a4926b1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 10 Nov 2021 11:01:10 +0100
+Subject: x86/msr: Remove .fixup usage
+
+From: Peter Zijlstra <peterz@infradead.org>
+
+[ Upstream commit d52a7344bdfa9c3442d3f86fb3501d9343726c76 ]
+
+Rework the MSR accessors to remove .fixup usage. Add two new extable
+types (to the 4 already existing msr ones) using the new register
+infrastructure to record which register should get the error value.
+
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Reviewed-by: Josh Poimboeuf <jpoimboe@redhat.com>
+Link: https://lore.kernel.org/r/20211110101325.364084212@infradead.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/include/asm/extable_fixup_types.h | 23 +++++-----
+ arch/x86/include/asm/msr.h                 | 26 ++++-------
+ arch/x86/mm/extable.c                      | 51 ++++++++++++----------
+ 3 files changed, 47 insertions(+), 53 deletions(-)
+
+diff --git a/arch/x86/include/asm/extable_fixup_types.h b/arch/x86/include/asm/extable_fixup_types.h
+index 944f8329022a..9d597fe1017d 100644
+--- a/arch/x86/include/asm/extable_fixup_types.h
++++ b/arch/x86/include/asm/extable_fixup_types.h
+@@ -32,17 +32,16 @@
+ #define       EX_TYPE_COPY                     4
+ #define       EX_TYPE_CLEAR_FS                 5
+ #define       EX_TYPE_FPU_RESTORE              6
+-#define       EX_TYPE_WRMSR                    7
+-#define       EX_TYPE_RDMSR                    8
+-#define       EX_TYPE_BPF                      9
+-
+-#define       EX_TYPE_WRMSR_IN_MCE            10
+-#define       EX_TYPE_RDMSR_IN_MCE            11
+-
+-#define       EX_TYPE_DEFAULT_MCE_SAFE        12
+-#define       EX_TYPE_FAULT_MCE_SAFE          13
+-
+-#define       EX_TYPE_POP_ZERO                14
+-#define       EX_TYPE_IMM_REG                 15 /* reg := (long)imm */
++#define       EX_TYPE_BPF                      7
++#define       EX_TYPE_WRMSR                    8
++#define       EX_TYPE_RDMSR                    9
++#define       EX_TYPE_WRMSR_SAFE              10 /* reg := -EIO */
++#define       EX_TYPE_RDMSR_SAFE              11 /* reg := -EIO */
++#define       EX_TYPE_WRMSR_IN_MCE            12
++#define       EX_TYPE_RDMSR_IN_MCE            13
++#define       EX_TYPE_DEFAULT_MCE_SAFE        14
++#define       EX_TYPE_FAULT_MCE_SAFE          15
++#define       EX_TYPE_POP_ZERO                16
++#define       EX_TYPE_IMM_REG                 17 /* reg := (long)imm */
+ #endif
+diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h
+index 6b52182e178a..d42e6c6b47b1 100644
+--- a/arch/x86/include/asm/msr.h
++++ b/arch/x86/include/asm/msr.h
+@@ -137,17 +137,11 @@ static inline unsigned long long native_read_msr_safe(unsigned int msr,
+ {
+       DECLARE_ARGS(val, low, high);
+-      asm volatile("2: rdmsr ; xor %[err],%[err]\n"
+-                   "1:\n\t"
+-                   ".section .fixup,\"ax\"\n\t"
+-                   "3: mov %[fault],%[err]\n\t"
+-                   "xorl %%eax, %%eax\n\t"
+-                   "xorl %%edx, %%edx\n\t"
+-                   "jmp 1b\n\t"
+-                   ".previous\n\t"
+-                   _ASM_EXTABLE(2b, 3b)
++      asm volatile("1: rdmsr ; xor %[err],%[err]\n"
++                   "2:\n\t"
++                   _ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_RDMSR_SAFE, %[err])
+                    : [err] "=r" (*err), EAX_EDX_RET(val, low, high)
+-                   : "c" (msr), [fault] "i" (-EIO));
++                   : "c" (msr));
+       if (tracepoint_enabled(read_msr))
+               do_trace_read_msr(msr, EAX_EDX_VAL(val, low, high), *err);
+       return EAX_EDX_VAL(val, low, high);
+@@ -169,15 +163,11 @@ native_write_msr_safe(unsigned int msr, u32 low, u32 high)
+ {
+       int err;
+-      asm volatile("2: wrmsr ; xor %[err],%[err]\n"
+-                   "1:\n\t"
+-                   ".section .fixup,\"ax\"\n\t"
+-                   "3:  mov %[fault],%[err] ; jmp 1b\n\t"
+-                   ".previous\n\t"
+-                   _ASM_EXTABLE(2b, 3b)
++      asm volatile("1: wrmsr ; xor %[err],%[err]\n"
++                   "2:\n\t"
++                   _ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_WRMSR_SAFE, %[err])
+                    : [err] "=a" (err)
+-                   : "c" (msr), "0" (low), "d" (high),
+-                     [fault] "i" (-EIO)
++                   : "c" (msr), "0" (low), "d" (high)
+                    : "memory");
+       if (tracepoint_enabled(write_msr))
+               do_trace_write_msr(msr, ((u64)high << 32 | low), err);
+diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c
+index 251732113624..1c558f8e8c07 100644
+--- a/arch/x86/mm/extable.c
++++ b/arch/x86/mm/extable.c
+@@ -83,28 +83,29 @@ static bool ex_handler_copy(const struct exception_table_entry *fixup,
+       return ex_handler_fault(fixup, regs, trapnr);
+ }
+-static bool ex_handler_rdmsr_unsafe(const struct exception_table_entry *fixup,
+-                                  struct pt_regs *regs)
++static bool ex_handler_msr(const struct exception_table_entry *fixup,
++                         struct pt_regs *regs, bool wrmsr, bool safe, int reg)
+ {
+-      if (pr_warn_once("unchecked MSR access error: RDMSR from 0x%x at rIP: 0x%lx (%pS)\n",
++      if (!safe && wrmsr &&
++          pr_warn_once("unchecked MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x) at rIP: 0x%lx (%pS)\n",
++                       (unsigned int)regs->cx, (unsigned int)regs->dx,
++                       (unsigned int)regs->ax,  regs->ip, (void *)regs->ip))
++              show_stack_regs(regs);
++
++      if (!safe && !wrmsr &&
++          pr_warn_once("unchecked MSR access error: RDMSR from 0x%x at rIP: 0x%lx (%pS)\n",
+                        (unsigned int)regs->cx, regs->ip, (void *)regs->ip))
+               show_stack_regs(regs);
+-      /* Pretend that the read succeeded and returned 0. */
+-      regs->ax = 0;
+-      regs->dx = 0;
+-      return ex_handler_default(fixup, regs);
+-}
++      if (!wrmsr) {
++              /* Pretend that the read succeeded and returned 0. */
++              regs->ax = 0;
++              regs->dx = 0;
++      }
+-static bool ex_handler_wrmsr_unsafe(const struct exception_table_entry *fixup,
+-                                  struct pt_regs *regs)
+-{
+-      if (pr_warn_once("unchecked MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x) at rIP: 0x%lx (%pS)\n",
+-                       (unsigned int)regs->cx, (unsigned int)regs->dx,
+-                       (unsigned int)regs->ax,  regs->ip, (void *)regs->ip))
+-              show_stack_regs(regs);
++      if (safe)
++              *pt_regs_nr(regs, reg) = -EIO;
+-      /* Pretend that the write succeeded. */
+       return ex_handler_default(fixup, regs);
+ }
+@@ -186,18 +187,22 @@ int fixup_exception(struct pt_regs *regs, int trapnr, unsigned long error_code,
+               return ex_handler_clear_fs(e, regs);
+       case EX_TYPE_FPU_RESTORE:
+               return ex_handler_fprestore(e, regs);
+-      case EX_TYPE_RDMSR:
+-              return ex_handler_rdmsr_unsafe(e, regs);
+-      case EX_TYPE_WRMSR:
+-              return ex_handler_wrmsr_unsafe(e, regs);
+       case EX_TYPE_BPF:
+               return ex_handler_bpf(e, regs);
+-      case EX_TYPE_RDMSR_IN_MCE:
+-              ex_handler_msr_mce(regs, false);
+-              break;
++      case EX_TYPE_WRMSR:
++              return ex_handler_msr(e, regs, true, false, reg);
++      case EX_TYPE_RDMSR:
++              return ex_handler_msr(e, regs, false, false, reg);
++      case EX_TYPE_WRMSR_SAFE:
++              return ex_handler_msr(e, regs, true, true, reg);
++      case EX_TYPE_RDMSR_SAFE:
++              return ex_handler_msr(e, regs, false, true, reg);
+       case EX_TYPE_WRMSR_IN_MCE:
+               ex_handler_msr_mce(regs, true);
+               break;
++      case EX_TYPE_RDMSR_IN_MCE:
++              ex_handler_msr_mce(regs, false);
++              break;
+       case EX_TYPE_POP_ZERO:
+               return ex_handler_pop_zero(e, regs);
+       case EX_TYPE_IMM_REG:
+-- 
+2.35.1
+
diff --git a/queue-5.15/x86-uaccess-implement-macros-for-cmpxchg-on-user-add.patch b/queue-5.15/x86-uaccess-implement-macros-for-cmpxchg-on-user-add.patch
new file mode 100644 (file)
index 0000000..6a3ed33
--- /dev/null
@@ -0,0 +1,196 @@
+From ac2daa7af9eb665242ed56b610762a7ca45bcbbc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 2 Feb 2022 00:49:42 +0000
+Subject: x86/uaccess: Implement macros for CMPXCHG on user addresses
+
+From: Peter Zijlstra <peterz@infradead.org>
+
+[ Upstream commit 989b5db215a2f22f89d730b607b071d964780f10 ]
+
+Add support for CMPXCHG loops on userspace addresses.  Provide both an
+"unsafe" version for tight loops that do their own uaccess begin/end, as
+well as a "safe" version for use cases where the CMPXCHG is not buried in
+a loop, e.g. KVM will resume the guest instead of looping when emulation
+of a guest atomic accesses fails the CMPXCHG.
+
+Provide 8-byte versions for 32-bit kernels so that KVM can do CMPXCHG on
+guest PAE PTEs, which are accessed via userspace addresses.
+
+Guard the asm_volatile_goto() variation with CC_HAS_ASM_GOTO_TIED_OUTPUT,
+the "+m" constraint fails on some compilers that otherwise support
+CC_HAS_ASM_GOTO_OUTPUT.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Co-developed-by: Sean Christopherson <seanjc@google.com>
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Message-Id: <20220202004945.2540433-3-seanjc@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/include/asm/uaccess.h | 142 +++++++++++++++++++++++++++++++++
+ 1 file changed, 142 insertions(+)
+
+diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
+index bb1430283c72..2f4c9c168b11 100644
+--- a/arch/x86/include/asm/uaccess.h
++++ b/arch/x86/include/asm/uaccess.h
+@@ -414,6 +414,103 @@ do {                                                                     \
+ #endif // CONFIG_CC_ASM_GOTO_OUTPUT
++#ifdef CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT
++#define __try_cmpxchg_user_asm(itype, ltype, _ptr, _pold, _new, label)        ({ \
++      bool success;                                                   \
++      __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold);              \
++      __typeof__(*(_ptr)) __old = *_old;                              \
++      __typeof__(*(_ptr)) __new = (_new);                             \
++      asm_volatile_goto("\n"                                          \
++                   "1: " LOCK_PREFIX "cmpxchg"itype" %[new], %[ptr]\n"\
++                   _ASM_EXTABLE_UA(1b, %l[label])                     \
++                   : CC_OUT(z) (success),                             \
++                     [ptr] "+m" (*_ptr),                              \
++                     [old] "+a" (__old)                               \
++                   : [new] ltype (__new)                              \
++                   : "memory"                                         \
++                   : label);                                          \
++      if (unlikely(!success))                                         \
++              *_old = __old;                                          \
++      likely(success);                                        })
++
++#ifdef CONFIG_X86_32
++#define __try_cmpxchg64_user_asm(_ptr, _pold, _new, label)    ({      \
++      bool success;                                                   \
++      __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold);              \
++      __typeof__(*(_ptr)) __old = *_old;                              \
++      __typeof__(*(_ptr)) __new = (_new);                             \
++      asm_volatile_goto("\n"                                          \
++                   "1: " LOCK_PREFIX "cmpxchg8b %[ptr]\n"             \
++                   _ASM_EXTABLE_UA(1b, %l[label])                     \
++                   : CC_OUT(z) (success),                             \
++                     "+A" (__old),                                    \
++                     [ptr] "+m" (*_ptr)                               \
++                   : "b" ((u32)__new),                                \
++                     "c" ((u32)((u64)__new >> 32))                    \
++                   : "memory"                                         \
++                   : label);                                          \
++      if (unlikely(!success))                                         \
++              *_old = __old;                                          \
++      likely(success);                                        })
++#endif // CONFIG_X86_32
++#else  // !CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT
++#define __try_cmpxchg_user_asm(itype, ltype, _ptr, _pold, _new, label)        ({ \
++      int __err = 0;                                                  \
++      bool success;                                                   \
++      __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold);              \
++      __typeof__(*(_ptr)) __old = *_old;                              \
++      __typeof__(*(_ptr)) __new = (_new);                             \
++      asm volatile("\n"                                               \
++                   "1: " LOCK_PREFIX "cmpxchg"itype" %[new], %[ptr]\n"\
++                   CC_SET(z)                                          \
++                   "2:\n"                                             \
++                   _ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_EFAULT_REG,  \
++                                         %[errout])                   \
++                   : CC_OUT(z) (success),                             \
++                     [errout] "+r" (__err),                           \
++                     [ptr] "+m" (*_ptr),                              \
++                     [old] "+a" (__old)                               \
++                   : [new] ltype (__new)                              \
++                   : "memory", "cc");                                 \
++      if (unlikely(__err))                                            \
++              goto label;                                             \
++      if (unlikely(!success))                                         \
++              *_old = __old;                                          \
++      likely(success);                                        })
++
++#ifdef CONFIG_X86_32
++/*
++ * Unlike the normal CMPXCHG, hardcode ECX for both success/fail and error.
++ * There are only six GPRs available and four (EAX, EBX, ECX, and EDX) are
++ * hardcoded by CMPXCHG8B, leaving only ESI and EDI.  If the compiler uses
++ * both ESI and EDI for the memory operand, compilation will fail if the error
++ * is an input+output as there will be no register available for input.
++ */
++#define __try_cmpxchg64_user_asm(_ptr, _pold, _new, label)    ({      \
++      int __result;                                                   \
++      __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold);              \
++      __typeof__(*(_ptr)) __old = *_old;                              \
++      __typeof__(*(_ptr)) __new = (_new);                             \
++      asm volatile("\n"                                               \
++                   "1: " LOCK_PREFIX "cmpxchg8b %[ptr]\n"             \
++                   "mov $0, %%ecx\n\t"                                \
++                   "setz %%cl\n"                                      \
++                   "2:\n"                                             \
++                   _ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_EFAULT_REG, %%ecx) \
++                   : [result]"=c" (__result),                         \
++                     "+A" (__old),                                    \
++                     [ptr] "+m" (*_ptr)                               \
++                   : "b" ((u32)__new),                                \
++                     "c" ((u32)((u64)__new >> 32))                    \
++                   : "memory", "cc");                                 \
++      if (unlikely(__result < 0))                                     \
++              goto label;                                             \
++      if (unlikely(!__result))                                        \
++              *_old = __old;                                          \
++      likely(__result);                                       })
++#endif // CONFIG_X86_32
++#endif // CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT
++
+ /* FIXME: this hack is definitely wrong -AK */
+ struct __large_struct { unsigned long buf[100]; };
+ #define __m(x) (*(struct __large_struct __user *)(x))
+@@ -506,6 +603,51 @@ do {                                                                              \
+ } while (0)
+ #endif // CONFIG_CC_HAS_ASM_GOTO_OUTPUT
++extern void __try_cmpxchg_user_wrong_size(void);
++
++#ifndef CONFIG_X86_32
++#define __try_cmpxchg64_user_asm(_ptr, _oldp, _nval, _label)          \
++      __try_cmpxchg_user_asm("q", "r", (_ptr), (_oldp), (_nval), _label)
++#endif
++
++/*
++ * Force the pointer to u<size> to match the size expected by the asm helper.
++ * clang/LLVM compiles all cases and only discards the unused paths after
++ * processing errors, which breaks i386 if the pointer is an 8-byte value.
++ */
++#define unsafe_try_cmpxchg_user(_ptr, _oldp, _nval, _label) ({                        \
++      bool __ret;                                                             \
++      __chk_user_ptr(_ptr);                                                   \
++      switch (sizeof(*(_ptr))) {                                              \
++      case 1: __ret = __try_cmpxchg_user_asm("b", "q",                        \
++                                             (__force u8 *)(_ptr), (_oldp),   \
++                                             (_nval), _label);                \
++              break;                                                          \
++      case 2: __ret = __try_cmpxchg_user_asm("w", "r",                        \
++                                             (__force u16 *)(_ptr), (_oldp),  \
++                                             (_nval), _label);                \
++              break;                                                          \
++      case 4: __ret = __try_cmpxchg_user_asm("l", "r",                        \
++                                             (__force u32 *)(_ptr), (_oldp),  \
++                                             (_nval), _label);                \
++              break;                                                          \
++      case 8: __ret = __try_cmpxchg64_user_asm((__force u64 *)(_ptr), (_oldp),\
++                                               (_nval), _label);              \
++              break;                                                          \
++      default: __try_cmpxchg_user_wrong_size();                               \
++      }                                                                       \
++      __ret;                                          })
++
++/* "Returns" 0 on success, 1 on failure, -EFAULT if the access faults. */
++#define __try_cmpxchg_user(_ptr, _oldp, _nval, _label)        ({              \
++      int __ret = -EFAULT;                                            \
++      __uaccess_begin_nospec();                                       \
++      __ret = !unsafe_try_cmpxchg_user(_ptr, _oldp, _nval, _label);   \
++_label:                                                                       \
++      __uaccess_end();                                                \
++      __ret;                                                          \
++                                                      })
++
+ /*
+  * We want the unsafe accessors to always be inlined and use
+  * the error labels - thus the macro games.
+-- 
+2.35.1
+
diff --git a/queue-5.15/x86-uaccess-implement-macros-for-cmpxchg-on-user-add.patch-12415 b/queue-5.15/x86-uaccess-implement-macros-for-cmpxchg-on-user-add.patch-12415
new file mode 100644 (file)
index 0000000..c87474b
--- /dev/null
@@ -0,0 +1,144 @@
+From 8a0706834a022fcc9d6d7b4b80c9cc8f3342539f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 2 Feb 2022 00:49:42 +0000
+Subject: x86/uaccess: Implement macros for CMPXCHG on user addresses
+
+From: Peter Zijlstra <peterz@infradead.org>
+
+[ Upstream commit 989b5db215a2f22f89d730b607b071d964780f10 ]
+
+Add support for CMPXCHG loops on userspace addresses.  Provide both an
+"unsafe" version for tight loops that do their own uaccess begin/end, as
+well as a "safe" version for use cases where the CMPXCHG is not buried in
+a loop, e.g. KVM will resume the guest instead of looping when emulation
+of a guest atomic accesses fails the CMPXCHG.
+
+Provide 8-byte versions for 32-bit kernels so that KVM can do CMPXCHG on
+guest PAE PTEs, which are accessed via userspace addresses.
+
+Guard the asm_volatile_goto() variation with CC_HAS_ASM_GOTO_TIED_OUTPUT,
+the "+m" constraint fails on some compilers that otherwise support
+CC_HAS_ASM_GOTO_OUTPUT.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Co-developed-by: Sean Christopherson <seanjc@google.com>
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Message-Id: <20220202004945.2540433-3-seanjc@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/include/asm/uaccess.h | 97 ++++++++++++++++++++++++++++++++++
+ 1 file changed, 97 insertions(+)
+
+diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
+index 775f1162da74..9af1a27fa568 100644
+--- a/arch/x86/include/asm/uaccess.h
++++ b/arch/x86/include/asm/uaccess.h
+@@ -608,6 +608,103 @@ do {                                                                     \
+ #endif // CONFIG_X86_32
+ #endif // CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT
++#ifdef CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT
++#define __try_cmpxchg_user_asm(itype, ltype, _ptr, _pold, _new, label)        ({ \
++      bool success;                                                   \
++      __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold);              \
++      __typeof__(*(_ptr)) __old = *_old;                              \
++      __typeof__(*(_ptr)) __new = (_new);                             \
++      asm_volatile_goto("\n"                                          \
++                   "1: " LOCK_PREFIX "cmpxchg"itype" %[new], %[ptr]\n"\
++                   _ASM_EXTABLE_UA(1b, %l[label])                     \
++                   : CC_OUT(z) (success),                             \
++                     [ptr] "+m" (*_ptr),                              \
++                     [old] "+a" (__old)                               \
++                   : [new] ltype (__new)                              \
++                   : "memory"                                         \
++                   : label);                                          \
++      if (unlikely(!success))                                         \
++              *_old = __old;                                          \
++      likely(success);                                        })
++
++#ifdef CONFIG_X86_32
++#define __try_cmpxchg64_user_asm(_ptr, _pold, _new, label)    ({      \
++      bool success;                                                   \
++      __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold);              \
++      __typeof__(*(_ptr)) __old = *_old;                              \
++      __typeof__(*(_ptr)) __new = (_new);                             \
++      asm_volatile_goto("\n"                                          \
++                   "1: " LOCK_PREFIX "cmpxchg8b %[ptr]\n"             \
++                   _ASM_EXTABLE_UA(1b, %l[label])                     \
++                   : CC_OUT(z) (success),                             \
++                     "+A" (__old),                                    \
++                     [ptr] "+m" (*_ptr)                               \
++                   : "b" ((u32)__new),                                \
++                     "c" ((u32)((u64)__new >> 32))                    \
++                   : "memory"                                         \
++                   : label);                                          \
++      if (unlikely(!success))                                         \
++              *_old = __old;                                          \
++      likely(success);                                        })
++#endif // CONFIG_X86_32
++#else  // !CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT
++#define __try_cmpxchg_user_asm(itype, ltype, _ptr, _pold, _new, label)        ({ \
++      int __err = 0;                                                  \
++      bool success;                                                   \
++      __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold);              \
++      __typeof__(*(_ptr)) __old = *_old;                              \
++      __typeof__(*(_ptr)) __new = (_new);                             \
++      asm volatile("\n"                                               \
++                   "1: " LOCK_PREFIX "cmpxchg"itype" %[new], %[ptr]\n"\
++                   CC_SET(z)                                          \
++                   "2:\n"                                             \
++                   _ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_EFAULT_REG,  \
++                                         %[errout])                   \
++                   : CC_OUT(z) (success),                             \
++                     [errout] "+r" (__err),                           \
++                     [ptr] "+m" (*_ptr),                              \
++                     [old] "+a" (__old)                               \
++                   : [new] ltype (__new)                              \
++                   : "memory", "cc");                                 \
++      if (unlikely(__err))                                            \
++              goto label;                                             \
++      if (unlikely(!success))                                         \
++              *_old = __old;                                          \
++      likely(success);                                        })
++
++#ifdef CONFIG_X86_32
++/*
++ * Unlike the normal CMPXCHG, hardcode ECX for both success/fail and error.
++ * There are only six GPRs available and four (EAX, EBX, ECX, and EDX) are
++ * hardcoded by CMPXCHG8B, leaving only ESI and EDI.  If the compiler uses
++ * both ESI and EDI for the memory operand, compilation will fail if the error
++ * is an input+output as there will be no register available for input.
++ */
++#define __try_cmpxchg64_user_asm(_ptr, _pold, _new, label)    ({      \
++      int __result;                                                   \
++      __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold);              \
++      __typeof__(*(_ptr)) __old = *_old;                              \
++      __typeof__(*(_ptr)) __new = (_new);                             \
++      asm volatile("\n"                                               \
++                   "1: " LOCK_PREFIX "cmpxchg8b %[ptr]\n"             \
++                   "mov $0, %%ecx\n\t"                                \
++                   "setz %%cl\n"                                      \
++                   "2:\n"                                             \
++                   _ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_EFAULT_REG, %%ecx) \
++                   : [result]"=c" (__result),                         \
++                     "+A" (__old),                                    \
++                     [ptr] "+m" (*_ptr)                               \
++                   : "b" ((u32)__new),                                \
++                     "c" ((u32)((u64)__new >> 32))                    \
++                   : "memory", "cc");                                 \
++      if (unlikely(__result < 0))                                     \
++              goto label;                                             \
++      if (unlikely(!__result))                                        \
++              *_old = __old;                                          \
++      likely(__result);                                       })
++#endif // CONFIG_X86_32
++#endif // CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT
++
+ /* FIXME: this hack is definitely wrong -AK */
+ struct __large_struct { unsigned long buf[100]; };
+ #define __m(x) (*(struct __large_struct __user *)(x))
+-- 
+2.35.1
+
diff --git a/queue-5.15/x86-uaccess-implement-macros-for-cmpxchg-on-user-add.patch-32473 b/queue-5.15/x86-uaccess-implement-macros-for-cmpxchg-on-user-add.patch-32473
new file mode 100644 (file)
index 0000000..63e8637
--- /dev/null
@@ -0,0 +1,144 @@
+From 9fd1d1b2e1d0f4aadee5632111f011a0a4e2ca5d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 2 Feb 2022 00:49:42 +0000
+Subject: x86/uaccess: Implement macros for CMPXCHG on user addresses
+
+From: Peter Zijlstra <peterz@infradead.org>
+
+[ Upstream commit 989b5db215a2f22f89d730b607b071d964780f10 ]
+
+Add support for CMPXCHG loops on userspace addresses.  Provide both an
+"unsafe" version for tight loops that do their own uaccess begin/end, as
+well as a "safe" version for use cases where the CMPXCHG is not buried in
+a loop, e.g. KVM will resume the guest instead of looping when emulation
+of a guest atomic accesses fails the CMPXCHG.
+
+Provide 8-byte versions for 32-bit kernels so that KVM can do CMPXCHG on
+guest PAE PTEs, which are accessed via userspace addresses.
+
+Guard the asm_volatile_goto() variation with CC_HAS_ASM_GOTO_TIED_OUTPUT,
+the "+m" constraint fails on some compilers that otherwise support
+CC_HAS_ASM_GOTO_OUTPUT.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Co-developed-by: Sean Christopherson <seanjc@google.com>
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Message-Id: <20220202004945.2540433-3-seanjc@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/include/asm/uaccess.h | 97 ++++++++++++++++++++++++++++++++++
+ 1 file changed, 97 insertions(+)
+
+diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
+index 2f4c9c168b11..775f1162da74 100644
+--- a/arch/x86/include/asm/uaccess.h
++++ b/arch/x86/include/asm/uaccess.h
+@@ -511,6 +511,103 @@ do {                                                                     \
+ #endif // CONFIG_X86_32
+ #endif // CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT
++#ifdef CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT
++#define __try_cmpxchg_user_asm(itype, ltype, _ptr, _pold, _new, label)        ({ \
++      bool success;                                                   \
++      __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold);              \
++      __typeof__(*(_ptr)) __old = *_old;                              \
++      __typeof__(*(_ptr)) __new = (_new);                             \
++      asm_volatile_goto("\n"                                          \
++                   "1: " LOCK_PREFIX "cmpxchg"itype" %[new], %[ptr]\n"\
++                   _ASM_EXTABLE_UA(1b, %l[label])                     \
++                   : CC_OUT(z) (success),                             \
++                     [ptr] "+m" (*_ptr),                              \
++                     [old] "+a" (__old)                               \
++                   : [new] ltype (__new)                              \
++                   : "memory"                                         \
++                   : label);                                          \
++      if (unlikely(!success))                                         \
++              *_old = __old;                                          \
++      likely(success);                                        })
++
++#ifdef CONFIG_X86_32
++#define __try_cmpxchg64_user_asm(_ptr, _pold, _new, label)    ({      \
++      bool success;                                                   \
++      __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold);              \
++      __typeof__(*(_ptr)) __old = *_old;                              \
++      __typeof__(*(_ptr)) __new = (_new);                             \
++      asm_volatile_goto("\n"                                          \
++                   "1: " LOCK_PREFIX "cmpxchg8b %[ptr]\n"             \
++                   _ASM_EXTABLE_UA(1b, %l[label])                     \
++                   : CC_OUT(z) (success),                             \
++                     "+A" (__old),                                    \
++                     [ptr] "+m" (*_ptr)                               \
++                   : "b" ((u32)__new),                                \
++                     "c" ((u32)((u64)__new >> 32))                    \
++                   : "memory"                                         \
++                   : label);                                          \
++      if (unlikely(!success))                                         \
++              *_old = __old;                                          \
++      likely(success);                                        })
++#endif // CONFIG_X86_32
++#else  // !CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT
++#define __try_cmpxchg_user_asm(itype, ltype, _ptr, _pold, _new, label)        ({ \
++      int __err = 0;                                                  \
++      bool success;                                                   \
++      __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold);              \
++      __typeof__(*(_ptr)) __old = *_old;                              \
++      __typeof__(*(_ptr)) __new = (_new);                             \
++      asm volatile("\n"                                               \
++                   "1: " LOCK_PREFIX "cmpxchg"itype" %[new], %[ptr]\n"\
++                   CC_SET(z)                                          \
++                   "2:\n"                                             \
++                   _ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_EFAULT_REG,  \
++                                         %[errout])                   \
++                   : CC_OUT(z) (success),                             \
++                     [errout] "+r" (__err),                           \
++                     [ptr] "+m" (*_ptr),                              \
++                     [old] "+a" (__old)                               \
++                   : [new] ltype (__new)                              \
++                   : "memory", "cc");                                 \
++      if (unlikely(__err))                                            \
++              goto label;                                             \
++      if (unlikely(!success))                                         \
++              *_old = __old;                                          \
++      likely(success);                                        })
++
++#ifdef CONFIG_X86_32
++/*
++ * Unlike the normal CMPXCHG, hardcode ECX for both success/fail and error.
++ * There are only six GPRs available and four (EAX, EBX, ECX, and EDX) are
++ * hardcoded by CMPXCHG8B, leaving only ESI and EDI.  If the compiler uses
++ * both ESI and EDI for the memory operand, compilation will fail if the error
++ * is an input+output as there will be no register available for input.
++ */
++#define __try_cmpxchg64_user_asm(_ptr, _pold, _new, label)    ({      \
++      int __result;                                                   \
++      __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold);              \
++      __typeof__(*(_ptr)) __old = *_old;                              \
++      __typeof__(*(_ptr)) __new = (_new);                             \
++      asm volatile("\n"                                               \
++                   "1: " LOCK_PREFIX "cmpxchg8b %[ptr]\n"             \
++                   "mov $0, %%ecx\n\t"                                \
++                   "setz %%cl\n"                                      \
++                   "2:\n"                                             \
++                   _ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_EFAULT_REG, %%ecx) \
++                   : [result]"=c" (__result),                         \
++                     "+A" (__old),                                    \
++                     [ptr] "+m" (*_ptr)                               \
++                   : "b" ((u32)__new),                                \
++                     "c" ((u32)((u64)__new >> 32))                    \
++                   : "memory", "cc");                                 \
++      if (unlikely(__result < 0))                                     \
++              goto label;                                             \
++      if (unlikely(!__result))                                        \
++              *_old = __old;                                          \
++      likely(__result);                                       })
++#endif // CONFIG_X86_32
++#endif // CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT
++
+ /* FIXME: this hack is definitely wrong -AK */
+ struct __large_struct { unsigned long buf[100]; };
+ #define __m(x) (*(struct __large_struct __user *)(x))
+-- 
+2.35.1
+
diff --git a/queue-5.15/xhci-dbc-create-and-remove-dbc-structure-in-dbgtty-d.patch b/queue-5.15/xhci-dbc-create-and-remove-dbc-structure-in-dbgtty-d.patch
new file mode 100644 (file)
index 0000000..459411a
--- /dev/null
@@ -0,0 +1,165 @@
+From e91dffa8b81880565d0c625f19d16c7b5b261b77 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 16 Feb 2022 11:51:46 +0200
+Subject: xhci: dbc: create and remove dbc structure in dbgtty driver.
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+[ Upstream commit 5ce036b98dd3301fc43bb06a6383ef07b6c776bc ]
+
+Turn the dbgtty closer to a device driver by allocating the dbc
+structure in its own xhci_dbc_tty_probe() function, and freeing it
+in xhci_dbc_tty_remove()
+
+Remove xhci_do_dbc_exit() as its no longer needed.
+
+allocate and create the dbc strcuture in xhci_dbc_tty_probe()
+
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://lore.kernel.org/r/20220216095153.1303105-3-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci-dbgcap.c | 26 +++-----------------------
+ drivers/usb/host/xhci-dbgcap.h |  5 ++++-
+ drivers/usb/host/xhci-dbgtty.c | 22 +++++++++++++++-------
+ 3 files changed, 22 insertions(+), 31 deletions(-)
+
+diff --git a/drivers/usb/host/xhci-dbgcap.c b/drivers/usb/host/xhci-dbgcap.c
+index 6a437862b498..f4da5708a40f 100644
+--- a/drivers/usb/host/xhci-dbgcap.c
++++ b/drivers/usb/host/xhci-dbgcap.c
+@@ -914,16 +914,6 @@ static void xhci_dbc_handle_events(struct work_struct *work)
+       mod_delayed_work(system_wq, &dbc->event_work, 1);
+ }
+-static void xhci_do_dbc_exit(struct xhci_hcd *xhci)
+-{
+-      unsigned long           flags;
+-
+-      spin_lock_irqsave(&xhci->lock, flags);
+-      kfree(xhci->dbc);
+-      xhci->dbc = NULL;
+-      spin_unlock_irqrestore(&xhci->lock, flags);
+-}
+-
+ static ssize_t dbc_show(struct device *dev,
+                       struct device_attribute *attr,
+                       char *buf)
+@@ -984,7 +974,7 @@ static ssize_t dbc_store(struct device *dev,
+ static DEVICE_ATTR_RW(dbc);
+ struct xhci_dbc *
+-xhci_alloc_dbc(struct device *dev, void __iomem *base)
++xhci_alloc_dbc(struct device *dev, void __iomem *base, const struct dbc_driver *driver)
+ {
+       struct xhci_dbc         *dbc;
+       int                     ret;
+@@ -995,6 +985,7 @@ xhci_alloc_dbc(struct device *dev, void __iomem *base)
+       dbc->regs = base;
+       dbc->dev = dev;
++      dbc->driver = driver;
+       if (readl(&dbc->regs->control) & DBC_CTRL_DBC_ENABLE)
+               return NULL;
+@@ -1045,18 +1036,8 @@ int xhci_dbc_init(struct xhci_hcd *xhci)
+       if (xhci->dbc)
+               return -EBUSY;
+-      xhci->dbc = xhci_alloc_dbc(dev, base);
+-      if (!xhci->dbc)
+-              return -ENOMEM;
+-
+-      ret = xhci_dbc_tty_probe(xhci);
+-      if (ret)
+-              goto init_err2;
+-
+-      return 0;
++      ret = xhci_dbc_tty_probe(dev, base + dbc_cap_offs, xhci);
+-init_err2:
+-      xhci_do_dbc_exit(xhci);
+       return ret;
+ }
+@@ -1068,7 +1049,6 @@ void xhci_dbc_exit(struct xhci_hcd *xhci)
+               return;
+       xhci_dbc_tty_remove(xhci->dbc);
+-      xhci_dbc_remove(xhci->dbc);
+       spin_lock_irqsave(&xhci->lock, flags);
+       xhci->dbc = NULL;
+       spin_unlock_irqrestore(&xhci->lock, flags);
+diff --git a/drivers/usb/host/xhci-dbgcap.h b/drivers/usb/host/xhci-dbgcap.h
+index c70b78d504eb..5d8c7815491c 100644
+--- a/drivers/usb/host/xhci-dbgcap.h
++++ b/drivers/usb/host/xhci-dbgcap.h
+@@ -196,8 +196,11 @@ static inline struct dbc_ep *get_out_ep(struct xhci_dbc *dbc)
+ #ifdef CONFIG_USB_XHCI_DBGCAP
+ int xhci_dbc_init(struct xhci_hcd *xhci);
+ void xhci_dbc_exit(struct xhci_hcd *xhci);
+-int xhci_dbc_tty_probe(struct xhci_hcd *xhci);
++int xhci_dbc_tty_probe(struct device *dev, void __iomem *res, struct xhci_hcd *xhci);
+ void xhci_dbc_tty_remove(struct xhci_dbc *dbc);
++struct xhci_dbc *xhci_alloc_dbc(struct device *dev, void __iomem *res,
++                               const struct dbc_driver *driver);
++void xhci_dbc_remove(struct xhci_dbc *dbc);
+ struct dbc_request *dbc_alloc_request(struct xhci_dbc *dbc,
+                                     unsigned int direction,
+                                     gfp_t flags);
+diff --git a/drivers/usb/host/xhci-dbgtty.c b/drivers/usb/host/xhci-dbgtty.c
+index eb46e642e87a..18bcc96853ae 100644
+--- a/drivers/usb/host/xhci-dbgtty.c
++++ b/drivers/usb/host/xhci-dbgtty.c
+@@ -468,9 +468,9 @@ static const struct dbc_driver dbc_driver = {
+       .disconnect             = xhci_dbc_tty_unregister_device,
+ };
+-int xhci_dbc_tty_probe(struct xhci_hcd *xhci)
++int xhci_dbc_tty_probe(struct device *dev, void __iomem *base, struct xhci_hcd *xhci)
+ {
+-      struct xhci_dbc         *dbc = xhci->dbc;
++      struct xhci_dbc         *dbc;
+       struct dbc_port         *port;
+       int                     status;
+@@ -485,13 +485,22 @@ int xhci_dbc_tty_probe(struct xhci_hcd *xhci)
+               goto out;
+       }
+-      dbc->driver = &dbc_driver;
+-      dbc->priv = port;
++      dbc_tty_driver->driver_state = port;
++
++      dbc = xhci_alloc_dbc(dev, base, &dbc_driver);
++      if (!dbc) {
++              status = -ENOMEM;
++              goto out2;
++      }
++      dbc->priv = port;
+-      dbc_tty_driver->driver_state = port;
++      /* get rid of xhci once this is a real driver binding to a device */
++      xhci->dbc = dbc;
+       return 0;
++out2:
++      kfree(port);
+ out:
+       /* dbc_tty_exit will be called by module_exit() in the future */
+       dbc_tty_exit();
+@@ -506,8 +515,7 @@ void xhci_dbc_tty_remove(struct xhci_dbc *dbc)
+ {
+       struct dbc_port         *port = dbc_to_port(dbc);
+-      dbc->driver = NULL;
+-      dbc->priv = NULL;
++      xhci_dbc_remove(dbc);
+       kfree(port);
+       /* dbc_tty_exit will be called by  module_exit() in the future */
+-- 
+2.35.1
+
diff --git a/queue-5.15/xhci-dbc-refactor-xhci_dbc_init.patch b/queue-5.15/xhci-dbc-refactor-xhci_dbc_init.patch
new file mode 100644 (file)
index 0000000..e4eeef1
--- /dev/null
@@ -0,0 +1,198 @@
+From 9d851a34f8198d8a3f57265da0c0dc7a31c6fff9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 16 Feb 2022 11:51:45 +0200
+Subject: xhci: dbc: refactor xhci_dbc_init()
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+[ Upstream commit 534675942e901959b5d8dc11ea526c4e48817d8e ]
+
+Refactor xhci_dbc_init(), splitting it into logical
+parts closer to the Linux device model.
+
+- Create the fake dbc device, depends on xhci strucure
+- Allocate a dbc structure, xhci agnostic
+- Call xhci_dbc_tty_probe(), similar to actual probe.
+
+Adjustments to xhci_dbc_exit and xhci_dbc_remove are also needed
+as a result to the xhci_dbc_init() changes
+
+Mostly non-functional changes, except for creating the dbc sysfs
+entry earlier, together with the dbc structure.
+
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://lore.kernel.org/r/20220216095153.1303105-2-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci-dbgcap.c | 124 ++++++++++++++++++---------------
+ 1 file changed, 66 insertions(+), 58 deletions(-)
+
+diff --git a/drivers/usb/host/xhci-dbgcap.c b/drivers/usb/host/xhci-dbgcap.c
+index ccb0156fcebe..6a437862b498 100644
+--- a/drivers/usb/host/xhci-dbgcap.c
++++ b/drivers/usb/host/xhci-dbgcap.c
+@@ -924,49 +924,6 @@ static void xhci_do_dbc_exit(struct xhci_hcd *xhci)
+       spin_unlock_irqrestore(&xhci->lock, flags);
+ }
+-static int xhci_do_dbc_init(struct xhci_hcd *xhci)
+-{
+-      u32                     reg;
+-      struct xhci_dbc         *dbc;
+-      unsigned long           flags;
+-      void __iomem            *base;
+-      int                     dbc_cap_offs;
+-
+-      base = &xhci->cap_regs->hc_capbase;
+-      dbc_cap_offs = xhci_find_next_ext_cap(base, 0, XHCI_EXT_CAPS_DEBUG);
+-      if (!dbc_cap_offs)
+-              return -ENODEV;
+-
+-      dbc = kzalloc(sizeof(*dbc), GFP_KERNEL);
+-      if (!dbc)
+-              return -ENOMEM;
+-
+-      dbc->regs = base + dbc_cap_offs;
+-
+-      /* We will avoid using DbC in xhci driver if it's in use. */
+-      reg = readl(&dbc->regs->control);
+-      if (reg & DBC_CTRL_DBC_ENABLE) {
+-              kfree(dbc);
+-              return -EBUSY;
+-      }
+-
+-      spin_lock_irqsave(&xhci->lock, flags);
+-      if (xhci->dbc) {
+-              spin_unlock_irqrestore(&xhci->lock, flags);
+-              kfree(dbc);
+-              return -EBUSY;
+-      }
+-      xhci->dbc = dbc;
+-      spin_unlock_irqrestore(&xhci->lock, flags);
+-
+-      dbc->xhci = xhci;
+-      dbc->dev = xhci_to_hcd(xhci)->self.sysdev;
+-      INIT_DELAYED_WORK(&dbc->event_work, xhci_dbc_handle_events);
+-      spin_lock_init(&dbc->lock);
+-
+-      return 0;
+-}
+-
+ static ssize_t dbc_show(struct device *dev,
+                       struct device_attribute *attr,
+                       char *buf)
+@@ -1026,44 +983,95 @@ static ssize_t dbc_store(struct device *dev,
+ static DEVICE_ATTR_RW(dbc);
+-int xhci_dbc_init(struct xhci_hcd *xhci)
++struct xhci_dbc *
++xhci_alloc_dbc(struct device *dev, void __iomem *base)
+ {
++      struct xhci_dbc         *dbc;
+       int                     ret;
+-      struct device           *dev = xhci_to_hcd(xhci)->self.controller;
+-      ret = xhci_do_dbc_init(xhci);
++      dbc = kzalloc(sizeof(*dbc), GFP_KERNEL);
++      if (!dbc)
++              return NULL;
++
++      dbc->regs = base;
++      dbc->dev = dev;
++
++      if (readl(&dbc->regs->control) & DBC_CTRL_DBC_ENABLE)
++              return NULL;
++
++      INIT_DELAYED_WORK(&dbc->event_work, xhci_dbc_handle_events);
++      spin_lock_init(&dbc->lock);
++
++      ret = device_create_file(dev, &dev_attr_dbc);
+       if (ret)
+-              goto init_err3;
++              goto err;
++
++      return dbc;
++err:
++      kfree(dbc);
++      return NULL;
++}
++
++/* undo what xhci_alloc_dbc() did */
++void xhci_dbc_remove(struct xhci_dbc *dbc)
++{
++      if (!dbc)
++              return;
++      /* stop hw, stop wq and call dbc->ops->stop() */
++      xhci_dbc_stop(dbc);
++
++      /* remove sysfs files */
++      device_remove_file(dbc->dev, &dev_attr_dbc);
++
++      kfree(dbc);
++}
++
++int xhci_dbc_init(struct xhci_hcd *xhci)
++{
++      struct device           *dev;
++      void __iomem            *base;
++      int                     ret;
++      int                     dbc_cap_offs;
++
++      /* create all parameters needed resembling a dbc device */
++      dev = xhci_to_hcd(xhci)->self.controller;
++      base = &xhci->cap_regs->hc_capbase;
++
++      dbc_cap_offs = xhci_find_next_ext_cap(base, 0, XHCI_EXT_CAPS_DEBUG);
++      if (!dbc_cap_offs)
++              return -ENODEV;
++
++      /* already allocated and in use */
++      if (xhci->dbc)
++              return -EBUSY;
++
++      xhci->dbc = xhci_alloc_dbc(dev, base);
++      if (!xhci->dbc)
++              return -ENOMEM;
+       ret = xhci_dbc_tty_probe(xhci);
+       if (ret)
+               goto init_err2;
+-      ret = device_create_file(dev, &dev_attr_dbc);
+-      if (ret)
+-              goto init_err1;
+-
+       return 0;
+-init_err1:
+-      xhci_dbc_tty_remove(xhci->dbc);
+ init_err2:
+       xhci_do_dbc_exit(xhci);
+-init_err3:
+       return ret;
+ }
+ void xhci_dbc_exit(struct xhci_hcd *xhci)
+ {
+-      struct device           *dev = xhci_to_hcd(xhci)->self.controller;
++      unsigned long           flags;
+       if (!xhci->dbc)
+               return;
+-      device_remove_file(dev, &dev_attr_dbc);
+       xhci_dbc_tty_remove(xhci->dbc);
+-      xhci_dbc_stop(xhci->dbc);
+-      xhci_do_dbc_exit(xhci);
++      xhci_dbc_remove(xhci->dbc);
++      spin_lock_irqsave(&xhci->lock, flags);
++      xhci->dbc = NULL;
++      spin_unlock_irqrestore(&xhci->lock, flags);
+ }
+ #ifdef CONFIG_PM
+-- 
+2.35.1
+
diff --git a/queue-5.15/xhci-dbc-rename-xhci_dbc_init-and-xhci_dbc_exit.patch b/queue-5.15/xhci-dbc-rename-xhci_dbc_init-and-xhci_dbc_exit.patch
new file mode 100644 (file)
index 0000000..94744db
--- /dev/null
@@ -0,0 +1,108 @@
+From 7e6f9e35f7ccec9eb7a80ffb557ca8fd030387ac Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 16 Feb 2022 11:51:47 +0200
+Subject: xhci: dbc: Rename xhci_dbc_init and xhci_dbc_exit
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+[ Upstream commit 5c44d9d7570b244ca08fef817c4c90aa7a1f1b5f ]
+
+These names give the impression the functions are related to
+module init calls, but are in fact creating and removing the dbc
+fake device
+
+Rename them to xhci_create_dbc_dev() and xhci_remove_dbc_dev().
+
+We will need the _init and _exit names for actual dbc module init
+and exit calls.
+
+No functional changes
+
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://lore.kernel.org/r/20220216095153.1303105-4-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci-dbgcap.c | 5 +++--
+ drivers/usb/host/xhci-dbgcap.h | 8 ++++----
+ drivers/usb/host/xhci.c        | 4 ++--
+ 3 files changed, 9 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/usb/host/xhci-dbgcap.c b/drivers/usb/host/xhci-dbgcap.c
+index f4da5708a40f..46c8f3c187f7 100644
+--- a/drivers/usb/host/xhci-dbgcap.c
++++ b/drivers/usb/host/xhci-dbgcap.c
+@@ -1017,7 +1017,8 @@ void xhci_dbc_remove(struct xhci_dbc *dbc)
+       kfree(dbc);
+ }
+-int xhci_dbc_init(struct xhci_hcd *xhci)
++
++int xhci_create_dbc_dev(struct xhci_hcd *xhci)
+ {
+       struct device           *dev;
+       void __iomem            *base;
+@@ -1041,7 +1042,7 @@ int xhci_dbc_init(struct xhci_hcd *xhci)
+       return ret;
+ }
+-void xhci_dbc_exit(struct xhci_hcd *xhci)
++void xhci_remove_dbc_dev(struct xhci_hcd *xhci)
+ {
+       unsigned long           flags;
+diff --git a/drivers/usb/host/xhci-dbgcap.h b/drivers/usb/host/xhci-dbgcap.h
+index 5d8c7815491c..8b5b363a0719 100644
+--- a/drivers/usb/host/xhci-dbgcap.h
++++ b/drivers/usb/host/xhci-dbgcap.h
+@@ -194,8 +194,8 @@ static inline struct dbc_ep *get_out_ep(struct xhci_dbc *dbc)
+ }
+ #ifdef CONFIG_USB_XHCI_DBGCAP
+-int xhci_dbc_init(struct xhci_hcd *xhci);
+-void xhci_dbc_exit(struct xhci_hcd *xhci);
++int xhci_create_dbc_dev(struct xhci_hcd *xhci);
++void xhci_remove_dbc_dev(struct xhci_hcd *xhci);
+ int xhci_dbc_tty_probe(struct device *dev, void __iomem *res, struct xhci_hcd *xhci);
+ void xhci_dbc_tty_remove(struct xhci_dbc *dbc);
+ struct xhci_dbc *xhci_alloc_dbc(struct device *dev, void __iomem *res,
+@@ -211,12 +211,12 @@ int xhci_dbc_suspend(struct xhci_hcd *xhci);
+ int xhci_dbc_resume(struct xhci_hcd *xhci);
+ #endif /* CONFIG_PM */
+ #else
+-static inline int xhci_dbc_init(struct xhci_hcd *xhci)
++static inline int xhci_create_dbc_dev(struct xhci_hcd *xhci)
+ {
+       return 0;
+ }
+-static inline void xhci_dbc_exit(struct xhci_hcd *xhci)
++static inline void xhci_remove_dbc_dev(struct xhci_hcd *xhci)
+ {
+ }
+diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
+index 94fe7d64e762..a4e99f8668b3 100644
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -693,7 +693,7 @@ int xhci_run(struct usb_hcd *hcd)
+       xhci_dbg_trace(xhci, trace_xhci_dbg_init,
+                       "Finished xhci_run for USB2 roothub");
+-      xhci_dbc_init(xhci);
++      xhci_create_dbc_dev(xhci);
+       xhci_debugfs_init(xhci);
+@@ -723,7 +723,7 @@ static void xhci_stop(struct usb_hcd *hcd)
+               return;
+       }
+-      xhci_dbc_exit(xhci);
++      xhci_remove_dbc_dev(xhci);
+       spin_lock_irq(&xhci->lock);
+       xhci->xhc_state |= XHCI_STATE_HALTED;
+-- 
+2.35.1
+
diff --git a/queue-5.15/xhci-set-hcd-flag-to-defer-primary-roothub-registrat.patch b/queue-5.15/xhci-set-hcd-flag-to-defer-primary-roothub-registrat.patch
new file mode 100644 (file)
index 0000000..c42dbed
--- /dev/null
@@ -0,0 +1,52 @@
+From 9769091a63aaae553b541d84f7759899c06977c5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 10 May 2022 14:46:30 +0530
+Subject: xhci: Set HCD flag to defer primary roothub registration
+
+From: Kishon Vijay Abraham I <kishon@ti.com>
+
+[ Upstream commit b7a4f9b5d0e4b6dd937678c546c0b322dd1a4054 ]
+
+Set "HCD_FLAG_DEFER_RH_REGISTER" to hcd->flags in xhci_run() to defer
+registering primary roothub in usb_add_hcd() if xhci has two roothubs.
+This will make sure both primary roothub and secondary roothub will be
+registered along with the second HCD.
+This is required for cold plugged USB devices to be detected in certain
+PCIe USB cards (like Inateck USB card connected to AM64 EVM or J7200 EVM).
+
+This patch has been added and reverted earier as it triggered a race
+in usb device enumeration.
+That race is now fixed in 5.16-rc3, and in stable back to 5.4
+commit 6cca13de26ee ("usb: hub: Fix locking issues with address0_mutex")
+commit 6ae6dc22d2d1 ("usb: hub: Fix usb enumeration issue due to address0
+race")
+
+[minor rebase change, and commit message update -Mathias]
+
+CC: stable@vger.kernel.org # 5.4+
+Suggested-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Tested-by: Chris Chiu <chris.chiu@canonical.com>
+Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
+Link: https://lore.kernel.org/r/20220510091630.16564-3-kishon@ti.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
+index a4e99f8668b3..d76c10f9ad80 100644
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -693,6 +693,8 @@ int xhci_run(struct usb_hcd *hcd)
+       xhci_dbg_trace(xhci, trace_xhci_dbg_init,
+                       "Finished xhci_run for USB2 roothub");
++      set_bit(HCD_FLAG_DEFER_RH_REGISTER, &hcd->flags);
++
+       xhci_create_dbc_dev(xhci);
+       xhci_debugfs_init(xhci);
+-- 
+2.35.1
+