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