From 9defba81bded4518586bd9a36ce300d3a6276334 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Mon, 25 Jul 2022 14:15:15 -0400 Subject: [PATCH] Fixes for 5.15 Signed-off-by: Sasha Levin --- ...-type-of-reg-too-small-for-mask-test.patch | 63 ++ .../crypto-qat-add-backlog-mechanism.patch | 408 +++++++++++ .../crypto-qat-add-param-check-for-dh.patch | 41 ++ .../crypto-qat-add-param-check-for-rsa.patch | 52 ++ .../crypto-qat-fix-memory-leak-in-rsa.patch | 54 ++ ...re-enable-registration-of-algorithms.patch | 66 ++ ...crypto-qat-refactor-submission-logic.patch | 379 ++++++++++ ...-qat-remove-dma_free_coherent-for-dh.patch | 181 +++++ ...qat-remove-dma_free_coherent-for-rsa.patch | 269 +++++++ ...et-to-zero-dh-parameters-before-free.patch | 51 ++ ...se-pre-allocated-buffers-in-datapath.patch | 207 ++++++ ...nding-remove-if-msg-allocation-fails.patch | 47 ++ ...ncing-wrong-parent-directory-informa.patch | 104 +++ ...i-fw-uefi-add-missing-include-guards.patch | 45 ++ ...y_cmpxchg_user-to-emulate-atomic-acc.patch | 108 +++ ...er-free-by-removing-a-non-rcu-wcid-p.patch | 269 +++++++ queue-5.15/series | 38 + ...-fix-return-value-of-trace_pid_write.patch | 84 +++ ...nt-format-check-not-flag-p-on-__get_.patch | 49 ++ ...ace_pid_list-logic-into-abstract-fun.patch | 497 +++++++++++++ ...io_uml-allow-probing-from-devicetree.patch | 135 ++++ ...x-broken-device-handling-in-time-tra.patch | 122 ++++ .../x86-entry_32-remove-.fixup-usage.patch | 130 ++++ ...extable-extend-extable-functionality.patch | 383 ++++++++++ ...-extable-get-rid-of-redundant-macros.patch | 84 +++ ...ide-ex_type_default_mce_safe-and-ex_.patch | 69 ++ ...x_type_default_mce_safe-and-ex_.patch-2687 | 39 + ...rework-the-exception-table-mechanics.patch | 665 ++++++++++++++++++ ...-tidy-up-redundant-handler-functions.patch | 80 +++ .../x86-futex-remove-.fixup-usage.patch | 95 +++ ...6-mce-deduplicate-exception-handling.patch | 83 +++ queue-5.15/x86-msr-remove-.fixup-usage.patch | 185 +++++ ...ement-macros-for-cmpxchg-on-user-add.patch | 196 ++++++ ...macros-for-cmpxchg-on-user-add.patch-12415 | 144 ++++ ...macros-for-cmpxchg-on-user-add.patch-32473 | 144 ++++ ...and-remove-dbc-structure-in-dbgtty-d.patch | 165 +++++ .../xhci-dbc-refactor-xhci_dbc_init.patch | 198 ++++++ ...name-xhci_dbc_init-and-xhci_dbc_exit.patch | 108 +++ ...g-to-defer-primary-roothub-registrat.patch | 52 ++ 39 files changed, 6089 insertions(+) create mode 100644 queue-5.15/bitfield.h-fix-type-of-reg-too-small-for-mask-test.patch create mode 100644 queue-5.15/crypto-qat-add-backlog-mechanism.patch create mode 100644 queue-5.15/crypto-qat-add-param-check-for-dh.patch create mode 100644 queue-5.15/crypto-qat-add-param-check-for-rsa.patch create mode 100644 queue-5.15/crypto-qat-fix-memory-leak-in-rsa.patch create mode 100644 queue-5.15/crypto-qat-re-enable-registration-of-algorithms.patch create mode 100644 queue-5.15/crypto-qat-refactor-submission-logic.patch create mode 100644 queue-5.15/crypto-qat-remove-dma_free_coherent-for-dh.patch create mode 100644 queue-5.15/crypto-qat-remove-dma_free_coherent-for-rsa.patch create mode 100644 queue-5.15/crypto-qat-set-to-zero-dh-parameters-before-free.patch create mode 100644 queue-5.15/crypto-qat-use-pre-allocated-buffers-in-datapath.patch create mode 100644 queue-5.15/dlm-fix-pending-remove-if-msg-allocation-fails.patch create mode 100644 queue-5.15/exfat-fix-referencing-wrong-parent-directory-informa.patch create mode 100644 queue-5.15/iwlwifi-fw-uefi-add-missing-include-guards.patch create mode 100644 queue-5.15/kvm-x86-use-__try_cmpxchg_user-to-emulate-atomic-acc.patch create mode 100644 queue-5.15/mt76-fix-use-after-free-by-removing-a-non-rcu-wcid-p.patch create mode 100644 queue-5.15/tracing-fix-return-value-of-trace_pid_write.patch create mode 100644 queue-5.15/tracing-have-event-format-check-not-flag-p-on-__get_.patch create mode 100644 queue-5.15/tracing-place-trace_pid_list-logic-into-abstract-fun.patch create mode 100644 queue-5.15/um-virtio_uml-allow-probing-from-devicetree.patch create mode 100644 queue-5.15/um-virtio_uml-fix-broken-device-handling-in-time-tra.patch create mode 100644 queue-5.15/x86-entry_32-remove-.fixup-usage.patch create mode 100644 queue-5.15/x86-extable-extend-extable-functionality.patch create mode 100644 queue-5.15/x86-extable-get-rid-of-redundant-macros.patch create mode 100644 queue-5.15/x86-extable-provide-ex_type_default_mce_safe-and-ex_.patch create mode 100644 queue-5.15/x86-extable-provide-ex_type_default_mce_safe-and-ex_.patch-2687 create mode 100644 queue-5.15/x86-extable-rework-the-exception-table-mechanics.patch create mode 100644 queue-5.15/x86-extable-tidy-up-redundant-handler-functions.patch create mode 100644 queue-5.15/x86-futex-remove-.fixup-usage.patch create mode 100644 queue-5.15/x86-mce-deduplicate-exception-handling.patch create mode 100644 queue-5.15/x86-msr-remove-.fixup-usage.patch create mode 100644 queue-5.15/x86-uaccess-implement-macros-for-cmpxchg-on-user-add.patch create mode 100644 queue-5.15/x86-uaccess-implement-macros-for-cmpxchg-on-user-add.patch-12415 create mode 100644 queue-5.15/x86-uaccess-implement-macros-for-cmpxchg-on-user-add.patch-32473 create mode 100644 queue-5.15/xhci-dbc-create-and-remove-dbc-structure-in-dbgtty-d.patch create mode 100644 queue-5.15/xhci-dbc-refactor-xhci_dbc_init.patch create mode 100644 queue-5.15/xhci-dbc-rename-xhci_dbc_init-and-xhci_dbc_exit.patch create mode 100644 queue-5.15/xhci-set-hcd-flag-to-defer-primary-roothub-registrat.patch diff --git a/queue-5.15/bitfield.h-fix-type-of-reg-too-small-for-mask-test.patch b/queue-5.15/bitfield.h-fix-type-of-reg-too-small-for-mask-test.patch new file mode 100644 index 00000000000..390214dd8c0 --- /dev/null +++ b/queue-5.15/bitfield.h-fix-type-of-reg-too-small-for-mask-test.patch @@ -0,0 +1,63 @@ +From fdc08170907d754143e9a13298cc48ac7011b099 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Nov 2021 11:01:03 +0100 +Subject: bitfield.h: Fix "type of reg too small for mask" test + +From: Peter Zijlstra + +[ 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) +Reviewed-by: Josh Poimboeuf +Link: https://lore.kernel.org/r/20211110101324.950210584@infradead.org +Signed-off-by: Sasha Levin +--- + include/linux/bitfield.h | 19 ++++++++++++++++++- + 1 file changed, 18 insertions(+), 1 deletion(-) + +diff --git a/include/linux/bitfield.h b/include/linux/bitfield.h +index 4e035aca6f7e..6093fa6db260 100644 +--- a/include/linux/bitfield.h ++++ b/include/linux/bitfield.h +@@ -41,6 +41,22 @@ + + #define __bf_shf(x) (__builtin_ffsll(x) - 1) + ++#define __scalar_type_to_unsigned_cases(type) \ ++ unsigned type: (unsigned type)0, \ ++ signed type: (unsigned type)0 ++ ++#define __unsigned_scalar_typeof(x) typeof( \ ++ _Generic((x), \ ++ char: (unsigned char)0, \ ++ __scalar_type_to_unsigned_cases(char), \ ++ __scalar_type_to_unsigned_cases(short), \ ++ __scalar_type_to_unsigned_cases(int), \ ++ __scalar_type_to_unsigned_cases(long), \ ++ __scalar_type_to_unsigned_cases(long long), \ ++ default: (x))) ++ ++#define __bf_cast_unsigned(type, x) ((__unsigned_scalar_typeof(type))(x)) ++ + #define __BF_FIELD_CHECK(_mask, _reg, _val, _pfx) \ + ({ \ + BUILD_BUG_ON_MSG(!__builtin_constant_p(_mask), \ +@@ -49,7 +65,8 @@ + BUILD_BUG_ON_MSG(__builtin_constant_p(_val) ? \ + ~((_mask) >> __bf_shf(_mask)) & (_val) : 0, \ + _pfx "value too large for the field"); \ +- BUILD_BUG_ON_MSG((_mask) > (typeof(_reg))~0ull, \ ++ BUILD_BUG_ON_MSG(__bf_cast_unsigned(_mask, _mask) > \ ++ __bf_cast_unsigned(_reg, ~0ull), \ + _pfx "type of reg too small for mask"); \ + __BUILD_BUG_ON_NOT_POWER_OF_2((_mask) + \ + (1ULL << __bf_shf(_mask))); \ +-- +2.35.1 + diff --git a/queue-5.15/crypto-qat-add-backlog-mechanism.patch b/queue-5.15/crypto-qat-add-backlog-mechanism.patch new file mode 100644 index 00000000000..2fed5be2bf5 --- /dev/null +++ b/queue-5.15/crypto-qat-add-backlog-mechanism.patch @@ -0,0 +1,408 @@ +From 7b81debcf9ab48cfe42bec0eec20b5fd081e222a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 May 2022 14:34:10 +0100 +Subject: crypto: qat - add backlog mechanism + +From: Giovanni Cabiddu + +[ 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 + +Cc: stable@vger.kernel.org +Fixes: d370cec32194 ("crypto: qat - Intel(R) QAT crypto interface") +Reported-by: Mikulas Patocka +Reported-by: Kyle Sanderson +Signed-off-by: Giovanni Cabiddu +Reviewed-by: Marco Chiappero +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/qat/qat_common/adf_transport.c | 11 +++ + drivers/crypto/qat/qat_common/adf_transport.h | 1 + + .../qat/qat_common/adf_transport_internal.h | 1 + + drivers/crypto/qat/qat_common/qat_algs.c | 24 ++++--- + drivers/crypto/qat/qat_common/qat_algs_send.c | 67 ++++++++++++++++++- + drivers/crypto/qat/qat_common/qat_algs_send.h | 1 + + drivers/crypto/qat/qat_common/qat_asym_algs.c | 23 ++++--- + drivers/crypto/qat/qat_common/qat_crypto.c | 3 + + drivers/crypto/qat/qat_common/qat_crypto.h | 10 +++ + 9 files changed, 123 insertions(+), 18 deletions(-) + +diff --git a/drivers/crypto/qat/qat_common/adf_transport.c b/drivers/crypto/qat/qat_common/adf_transport.c +index 8ba28409fb74..630d0483c4e0 100644 +--- a/drivers/crypto/qat/qat_common/adf_transport.c ++++ b/drivers/crypto/qat/qat_common/adf_transport.c +@@ -8,6 +8,9 @@ + #include "adf_cfg.h" + #include "adf_common_drv.h" + ++#define ADF_MAX_RING_THRESHOLD 80 ++#define ADF_PERCENT(tot, percent) (((tot) * (percent)) / 100) ++ + static inline u32 adf_modulo(u32 data, u32 shift) + { + u32 div = data >> shift; +@@ -77,6 +80,11 @@ static void adf_disable_ring_irq(struct adf_etr_bank_data *bank, u32 ring) + bank->irq_mask); + } + ++bool adf_ring_nearly_full(struct adf_etr_ring_data *ring) ++{ ++ return atomic_read(ring->inflights) > ring->threshold; ++} ++ + int adf_send_message(struct adf_etr_ring_data *ring, u32 *msg) + { + struct adf_hw_csr_ops *csr_ops = GET_CSR_OPS(ring->bank->accel_dev); +@@ -217,6 +225,7 @@ int adf_create_ring(struct adf_accel_dev *accel_dev, const char *section, + struct adf_etr_bank_data *bank; + struct adf_etr_ring_data *ring; + char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; ++ int max_inflights; + u32 ring_num; + int ret; + +@@ -263,6 +272,8 @@ int adf_create_ring(struct adf_accel_dev *accel_dev, const char *section, + ring->ring_size = adf_verify_ring_size(msg_size, num_msgs); + ring->head = 0; + ring->tail = 0; ++ max_inflights = ADF_MAX_INFLIGHTS(ring->ring_size, ring->msg_size); ++ ring->threshold = ADF_PERCENT(max_inflights, ADF_MAX_RING_THRESHOLD); + atomic_set(ring->inflights, 0); + ret = adf_init_ring(ring); + if (ret) +diff --git a/drivers/crypto/qat/qat_common/adf_transport.h b/drivers/crypto/qat/qat_common/adf_transport.h +index 2c95f1697c76..e6ef6f9b7691 100644 +--- a/drivers/crypto/qat/qat_common/adf_transport.h ++++ b/drivers/crypto/qat/qat_common/adf_transport.h +@@ -14,6 +14,7 @@ int adf_create_ring(struct adf_accel_dev *accel_dev, const char *section, + const char *ring_name, adf_callback_fn callback, + int poll_mode, struct adf_etr_ring_data **ring_ptr); + ++bool adf_ring_nearly_full(struct adf_etr_ring_data *ring); + int adf_send_message(struct adf_etr_ring_data *ring, u32 *msg); + void adf_remove_ring(struct adf_etr_ring_data *ring); + #endif +diff --git a/drivers/crypto/qat/qat_common/adf_transport_internal.h b/drivers/crypto/qat/qat_common/adf_transport_internal.h +index 501bcf0f1809..8b2c92ba7ca1 100644 +--- a/drivers/crypto/qat/qat_common/adf_transport_internal.h ++++ b/drivers/crypto/qat/qat_common/adf_transport_internal.h +@@ -22,6 +22,7 @@ struct adf_etr_ring_data { + spinlock_t lock; /* protects ring data struct */ + u16 head; + u16 tail; ++ u32 threshold; + u8 ring_number; + u8 ring_size; + u8 msg_size; +diff --git a/drivers/crypto/qat/qat_common/qat_algs.c b/drivers/crypto/qat/qat_common/qat_algs.c +index 6017ae82c713..873533dc43a7 100644 +--- a/drivers/crypto/qat/qat_common/qat_algs.c ++++ b/drivers/crypto/qat/qat_common/qat_algs.c +@@ -935,19 +935,25 @@ void qat_alg_callback(void *resp) + struct icp_qat_fw_la_resp *qat_resp = resp; + struct qat_crypto_request *qat_req = + (void *)(__force long)qat_resp->opaque_data; ++ struct qat_instance_backlog *backlog = qat_req->alg_req.backlog; + + qat_req->cb(qat_resp, qat_req); ++ ++ qat_alg_send_backlog(backlog); + } + + static int qat_alg_send_sym_message(struct qat_crypto_request *qat_req, +- struct qat_crypto_instance *inst) ++ struct qat_crypto_instance *inst, ++ struct crypto_async_request *base) + { +- struct qat_alg_req req; ++ struct qat_alg_req *alg_req = &qat_req->alg_req; + +- req.fw_req = (u32 *)&qat_req->req; +- req.tx_ring = inst->sym_tx; ++ alg_req->fw_req = (u32 *)&qat_req->req; ++ alg_req->tx_ring = inst->sym_tx; ++ alg_req->base = base; ++ alg_req->backlog = &inst->backlog; + +- return qat_alg_send_message(&req); ++ return qat_alg_send_message(alg_req); + } + + static int qat_alg_aead_dec(struct aead_request *areq) +@@ -987,7 +993,7 @@ static int qat_alg_aead_dec(struct aead_request *areq) + auth_param->auth_off = 0; + auth_param->auth_len = areq->assoclen + cipher_param->cipher_length; + +- ret = qat_alg_send_sym_message(qat_req, ctx->inst); ++ ret = qat_alg_send_sym_message(qat_req, ctx->inst, &areq->base); + if (ret == -ENOSPC) + qat_alg_free_bufl(ctx->inst, qat_req); + +@@ -1031,7 +1037,7 @@ static int qat_alg_aead_enc(struct aead_request *areq) + auth_param->auth_off = 0; + auth_param->auth_len = areq->assoclen + areq->cryptlen; + +- ret = qat_alg_send_sym_message(qat_req, ctx->inst); ++ ret = qat_alg_send_sym_message(qat_req, ctx->inst, &areq->base); + if (ret == -ENOSPC) + qat_alg_free_bufl(ctx->inst, qat_req); + +@@ -1212,7 +1218,7 @@ static int qat_alg_skcipher_encrypt(struct skcipher_request *req) + + qat_alg_set_req_iv(qat_req); + +- ret = qat_alg_send_sym_message(qat_req, ctx->inst); ++ ret = qat_alg_send_sym_message(qat_req, ctx->inst, &req->base); + if (ret == -ENOSPC) + qat_alg_free_bufl(ctx->inst, qat_req); + +@@ -1278,7 +1284,7 @@ static int qat_alg_skcipher_decrypt(struct skcipher_request *req) + qat_alg_set_req_iv(qat_req); + qat_alg_update_iv(qat_req); + +- ret = qat_alg_send_sym_message(qat_req, ctx->inst); ++ ret = qat_alg_send_sym_message(qat_req, ctx->inst, &req->base); + if (ret == -ENOSPC) + qat_alg_free_bufl(ctx->inst, qat_req); + +diff --git a/drivers/crypto/qat/qat_common/qat_algs_send.c b/drivers/crypto/qat/qat_common/qat_algs_send.c +index 78f1bb8c26c0..ff5b4347f783 100644 +--- a/drivers/crypto/qat/qat_common/qat_algs_send.c ++++ b/drivers/crypto/qat/qat_common/qat_algs_send.c +@@ -6,7 +6,7 @@ + + #define ADF_MAX_RETRIES 20 + +-int qat_alg_send_message(struct qat_alg_req *req) ++static int qat_alg_send_message_retry(struct qat_alg_req *req) + { + int ret = 0, ctr = 0; + +@@ -19,3 +19,68 @@ int qat_alg_send_message(struct qat_alg_req *req) + + return -EINPROGRESS; + } ++ ++void qat_alg_send_backlog(struct qat_instance_backlog *backlog) ++{ ++ struct qat_alg_req *req, *tmp; ++ ++ spin_lock_bh(&backlog->lock); ++ list_for_each_entry_safe(req, tmp, &backlog->list, list) { ++ if (adf_send_message(req->tx_ring, req->fw_req)) { ++ /* The HW ring is full. Do nothing. ++ * qat_alg_send_backlog() will be invoked again by ++ * another callback. ++ */ ++ break; ++ } ++ list_del(&req->list); ++ req->base->complete(req->base, -EINPROGRESS); ++ } ++ spin_unlock_bh(&backlog->lock); ++} ++ ++static void qat_alg_backlog_req(struct qat_alg_req *req, ++ struct qat_instance_backlog *backlog) ++{ ++ INIT_LIST_HEAD(&req->list); ++ ++ spin_lock_bh(&backlog->lock); ++ list_add_tail(&req->list, &backlog->list); ++ spin_unlock_bh(&backlog->lock); ++} ++ ++static int qat_alg_send_message_maybacklog(struct qat_alg_req *req) ++{ ++ struct qat_instance_backlog *backlog = req->backlog; ++ struct adf_etr_ring_data *tx_ring = req->tx_ring; ++ u32 *fw_req = req->fw_req; ++ ++ /* If any request is already backlogged, then add to backlog list */ ++ if (!list_empty(&backlog->list)) ++ goto enqueue; ++ ++ /* If ring is nearly full, then add to backlog list */ ++ if (adf_ring_nearly_full(tx_ring)) ++ goto enqueue; ++ ++ /* If adding request to HW ring fails, then add to backlog list */ ++ if (adf_send_message(tx_ring, fw_req)) ++ goto enqueue; ++ ++ return -EINPROGRESS; ++ ++enqueue: ++ qat_alg_backlog_req(req, backlog); ++ ++ return -EBUSY; ++} ++ ++int qat_alg_send_message(struct qat_alg_req *req) ++{ ++ u32 flags = req->base->flags; ++ ++ if (flags & CRYPTO_TFM_REQ_MAY_BACKLOG) ++ return qat_alg_send_message_maybacklog(req); ++ else ++ return qat_alg_send_message_retry(req); ++} +diff --git a/drivers/crypto/qat/qat_common/qat_algs_send.h b/drivers/crypto/qat/qat_common/qat_algs_send.h +index 3fa685d0c293..5ce9f4f69d8f 100644 +--- a/drivers/crypto/qat/qat_common/qat_algs_send.h ++++ b/drivers/crypto/qat/qat_common/qat_algs_send.h +@@ -6,5 +6,6 @@ + #include "qat_crypto.h" + + int qat_alg_send_message(struct qat_alg_req *req); ++void qat_alg_send_backlog(struct qat_instance_backlog *backlog); + + #endif +diff --git a/drivers/crypto/qat/qat_common/qat_asym_algs.c b/drivers/crypto/qat/qat_common/qat_asym_algs.c +index 08b8d83e070a..ff7249c093c9 100644 +--- a/drivers/crypto/qat/qat_common/qat_asym_algs.c ++++ b/drivers/crypto/qat/qat_common/qat_asym_algs.c +@@ -136,17 +136,21 @@ struct qat_asym_request { + } areq; + int err; + void (*cb)(struct icp_qat_fw_pke_resp *resp); ++ struct qat_alg_req alg_req; + } __aligned(64); + + static int qat_alg_send_asym_message(struct qat_asym_request *qat_req, +- struct qat_crypto_instance *inst) ++ struct qat_crypto_instance *inst, ++ struct crypto_async_request *base) + { +- struct qat_alg_req req; ++ struct qat_alg_req *alg_req = &qat_req->alg_req; + +- req.fw_req = (u32 *)&qat_req->req; +- req.tx_ring = inst->pke_tx; ++ alg_req->fw_req = (u32 *)&qat_req->req; ++ alg_req->tx_ring = inst->pke_tx; ++ alg_req->base = base; ++ alg_req->backlog = &inst->backlog; + +- return qat_alg_send_message(&req); ++ return qat_alg_send_message(alg_req); + } + + static void qat_dh_cb(struct icp_qat_fw_pke_resp *resp) +@@ -350,7 +354,7 @@ static int qat_dh_compute_value(struct kpp_request *req) + msg->input_param_count = n_input_params; + msg->output_param_count = 1; + +- ret = qat_alg_send_asym_message(qat_req, ctx->inst); ++ ret = qat_alg_send_asym_message(qat_req, inst, &req->base); + if (ret == -ENOSPC) + goto unmap_all; + +@@ -557,8 +561,11 @@ void qat_alg_asym_callback(void *_resp) + { + struct icp_qat_fw_pke_resp *resp = _resp; + struct qat_asym_request *areq = (void *)(__force long)resp->opaque; ++ struct qat_instance_backlog *backlog = areq->alg_req.backlog; + + areq->cb(resp); ++ ++ qat_alg_send_backlog(backlog); + } + + #define PKE_RSA_EP_512 0x1c161b21 +@@ -748,7 +755,7 @@ static int qat_rsa_enc(struct akcipher_request *req) + msg->input_param_count = 3; + msg->output_param_count = 1; + +- ret = qat_alg_send_asym_message(qat_req, ctx->inst); ++ ret = qat_alg_send_asym_message(qat_req, inst, &req->base); + if (ret == -ENOSPC) + goto unmap_all; + +@@ -901,7 +908,7 @@ static int qat_rsa_dec(struct akcipher_request *req) + + msg->output_param_count = 1; + +- ret = qat_alg_send_asym_message(qat_req, ctx->inst); ++ ret = qat_alg_send_asym_message(qat_req, inst, &req->base); + if (ret == -ENOSPC) + goto unmap_all; + +diff --git a/drivers/crypto/qat/qat_common/qat_crypto.c b/drivers/crypto/qat/qat_common/qat_crypto.c +index 3efbb3883601..59e122afa434 100644 +--- a/drivers/crypto/qat/qat_common/qat_crypto.c ++++ b/drivers/crypto/qat/qat_common/qat_crypto.c +@@ -328,6 +328,9 @@ static int qat_crypto_create_instances(struct adf_accel_dev *accel_dev) + &inst->pke_rx); + if (ret) + goto err; ++ ++ INIT_LIST_HEAD(&inst->backlog.list); ++ spin_lock_init(&inst->backlog.lock); + } + return 0; + err: +diff --git a/drivers/crypto/qat/qat_common/qat_crypto.h b/drivers/crypto/qat/qat_common/qat_crypto.h +index 0dcba6fc358c..245b6d9a3650 100644 +--- a/drivers/crypto/qat/qat_common/qat_crypto.h ++++ b/drivers/crypto/qat/qat_common/qat_crypto.h +@@ -9,9 +9,17 @@ + #include "adf_accel_devices.h" + #include "icp_qat_fw_la.h" + ++struct qat_instance_backlog { ++ struct list_head list; ++ spinlock_t lock; /* protects backlog list */ ++}; ++ + struct qat_alg_req { + u32 *fw_req; + struct adf_etr_ring_data *tx_ring; ++ struct crypto_async_request *base; ++ struct list_head list; ++ struct qat_instance_backlog *backlog; + }; + + struct qat_crypto_instance { +@@ -24,6 +32,7 @@ struct qat_crypto_instance { + unsigned long state; + int id; + atomic_t refctr; ++ struct qat_instance_backlog backlog; + }; + + #define QAT_MAX_BUFF_DESC 4 +@@ -82,6 +91,7 @@ struct qat_crypto_request { + u8 iv[AES_BLOCK_SIZE]; + }; + bool encryption; ++ struct qat_alg_req alg_req; + }; + + static inline bool adf_hw_dev_has_crypto(struct adf_accel_dev *accel_dev) +-- +2.35.1 + diff --git a/queue-5.15/crypto-qat-add-param-check-for-dh.patch b/queue-5.15/crypto-qat-add-param-check-for-dh.patch new file mode 100644 index 00000000000..d9865034c8a --- /dev/null +++ b/queue-5.15/crypto-qat-add-param-check-for-dh.patch @@ -0,0 +1,41 @@ +From 5383cc9354f96990402731466133de2b537ea349 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 May 2022 14:34:15 +0100 +Subject: crypto: qat - add param check for DH + +From: Giovanni Cabiddu + +[ 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 +Reviewed-by: Adam Guerin +Reviewed-by: Wojciech Ziemba +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/qat/qat_common/qat_asym_algs.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/crypto/qat/qat_common/qat_asym_algs.c b/drivers/crypto/qat/qat_common/qat_asym_algs.c +index 947eeff181b4..7173a2a0a484 100644 +--- a/drivers/crypto/qat/qat_common/qat_asym_algs.c ++++ b/drivers/crypto/qat/qat_common/qat_asym_algs.c +@@ -235,6 +235,10 @@ static int qat_dh_compute_value(struct kpp_request *req) + req->dst_len = ctx->p_size; + return -EOVERFLOW; + } ++ ++ if (req->src_len > ctx->p_size) ++ return -EINVAL; ++ + memset(msg, '\0', sizeof(*msg)); + ICP_QAT_FW_PKE_HDR_VALID_FLAG_SET(msg->pke_hdr, + ICP_QAT_FW_COMN_REQ_FLAG_SET); +-- +2.35.1 + diff --git a/queue-5.15/crypto-qat-add-param-check-for-rsa.patch b/queue-5.15/crypto-qat-add-param-check-for-rsa.patch new file mode 100644 index 00000000000..15a324d4562 --- /dev/null +++ b/queue-5.15/crypto-qat-add-param-check-for-rsa.patch @@ -0,0 +1,52 @@ +From 9a9d8c8f792723722eecd5bdd9b9e55455800aaa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 May 2022 14:34:14 +0100 +Subject: crypto: qat - add param check for RSA + +From: Giovanni Cabiddu + +[ 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 +Reviewed-by: Adam Guerin +Reviewed-by: Wojciech Ziemba +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/qat/qat_common/qat_asym_algs.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/crypto/qat/qat_common/qat_asym_algs.c b/drivers/crypto/qat/qat_common/qat_asym_algs.c +index 25bbd22085c3..947eeff181b4 100644 +--- a/drivers/crypto/qat/qat_common/qat_asym_algs.c ++++ b/drivers/crypto/qat/qat_common/qat_asym_algs.c +@@ -656,6 +656,10 @@ static int qat_rsa_enc(struct akcipher_request *req) + req->dst_len = ctx->key_sz; + return -EOVERFLOW; + } ++ ++ if (req->src_len > ctx->key_sz) ++ return -EINVAL; ++ + memset(msg, '\0', sizeof(*msg)); + ICP_QAT_FW_PKE_HDR_VALID_FLAG_SET(msg->pke_hdr, + ICP_QAT_FW_COMN_REQ_FLAG_SET); +@@ -785,6 +789,10 @@ static int qat_rsa_dec(struct akcipher_request *req) + req->dst_len = ctx->key_sz; + return -EOVERFLOW; + } ++ ++ if (req->src_len > ctx->key_sz) ++ return -EINVAL; ++ + memset(msg, '\0', sizeof(*msg)); + ICP_QAT_FW_PKE_HDR_VALID_FLAG_SET(msg->pke_hdr, + ICP_QAT_FW_COMN_REQ_FLAG_SET); +-- +2.35.1 + diff --git a/queue-5.15/crypto-qat-fix-memory-leak-in-rsa.patch b/queue-5.15/crypto-qat-fix-memory-leak-in-rsa.patch new file mode 100644 index 00000000000..fb3788c0871 --- /dev/null +++ b/queue-5.15/crypto-qat-fix-memory-leak-in-rsa.patch @@ -0,0 +1,54 @@ +From 4bd21510822b9afcb74765de49b9615415cd19b8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 May 2022 14:34:11 +0100 +Subject: crypto: qat - fix memory leak in RSA + +From: Giovanni Cabiddu + +[ 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 +Reviewed-by: Adam Guerin +Reviewed-by: Wojciech Ziemba +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/qat/qat_common/qat_asym_algs.c | 12 +----------- + 1 file changed, 1 insertion(+), 11 deletions(-) + +diff --git a/drivers/crypto/qat/qat_common/qat_asym_algs.c b/drivers/crypto/qat/qat_common/qat_asym_algs.c +index ff7249c093c9..2bc02c75398e 100644 +--- a/drivers/crypto/qat/qat_common/qat_asym_algs.c ++++ b/drivers/crypto/qat/qat_common/qat_asym_algs.c +@@ -1257,18 +1257,8 @@ static void qat_rsa_exit_tfm(struct crypto_akcipher *tfm) + struct qat_rsa_ctx *ctx = akcipher_tfm_ctx(tfm); + struct device *dev = &GET_DEV(ctx->inst->accel_dev); + +- if (ctx->n) +- dma_free_coherent(dev, ctx->key_sz, ctx->n, ctx->dma_n); +- if (ctx->e) +- dma_free_coherent(dev, ctx->key_sz, ctx->e, ctx->dma_e); +- if (ctx->d) { +- memset(ctx->d, '\0', ctx->key_sz); +- dma_free_coherent(dev, ctx->key_sz, ctx->d, ctx->dma_d); +- } ++ qat_rsa_clear_ctx(dev, ctx); + qat_crypto_put_instance(ctx->inst); +- ctx->n = NULL; +- ctx->e = NULL; +- ctx->d = NULL; + } + + static struct akcipher_alg rsa = { +-- +2.35.1 + diff --git a/queue-5.15/crypto-qat-re-enable-registration-of-algorithms.patch b/queue-5.15/crypto-qat-re-enable-registration-of-algorithms.patch new file mode 100644 index 00000000000..dbe01aa71f6 --- /dev/null +++ b/queue-5.15/crypto-qat-re-enable-registration-of-algorithms.patch @@ -0,0 +1,66 @@ +From 9ce3a04e6488df1e887f3bfcec74f6bf02069397 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 May 2022 14:34:17 +0100 +Subject: crypto: qat - re-enable registration of algorithms + +From: Giovanni Cabiddu + +[ 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 +Reviewed-by: Marco Chiappero +Reviewed-by: Adam Guerin +Reviewed-by: Wojciech Ziemba +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/qat/qat_4xxx/adf_drv.c | 7 ------- + drivers/crypto/qat/qat_common/qat_crypto.c | 7 ------- + 2 files changed, 14 deletions(-) + +diff --git a/drivers/crypto/qat/qat_4xxx/adf_drv.c b/drivers/crypto/qat/qat_4xxx/adf_drv.c +index 8fd44703115f..359fb7989dfb 100644 +--- a/drivers/crypto/qat/qat_4xxx/adf_drv.c ++++ b/drivers/crypto/qat/qat_4xxx/adf_drv.c +@@ -52,13 +52,6 @@ static int adf_crypto_dev_config(struct adf_accel_dev *accel_dev) + if (ret) + goto err; + +- /* Temporarily set the number of crypto instances to zero to avoid +- * registering the crypto algorithms. +- * This will be removed when the algorithms will support the +- * CRYPTO_TFM_REQ_MAY_BACKLOG flag +- */ +- instances = 0; +- + for (i = 0; i < instances; i++) { + val = i; + bank = i * 2; +diff --git a/drivers/crypto/qat/qat_common/qat_crypto.c b/drivers/crypto/qat/qat_common/qat_crypto.c +index 59e122afa434..994e43fab0a4 100644 +--- a/drivers/crypto/qat/qat_common/qat_crypto.c ++++ b/drivers/crypto/qat/qat_common/qat_crypto.c +@@ -136,13 +136,6 @@ int qat_crypto_dev_config(struct adf_accel_dev *accel_dev) + if (ret) + goto err; + +- /* Temporarily set the number of crypto instances to zero to avoid +- * registering the crypto algorithms. +- * This will be removed when the algorithms will support the +- * CRYPTO_TFM_REQ_MAY_BACKLOG flag +- */ +- instances = 0; +- + for (i = 0; i < instances; i++) { + val = i; + snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_ASYM_BANK_NUM, i); +-- +2.35.1 + diff --git a/queue-5.15/crypto-qat-refactor-submission-logic.patch b/queue-5.15/crypto-qat-refactor-submission-logic.patch new file mode 100644 index 00000000000..5dcebb502b0 --- /dev/null +++ b/queue-5.15/crypto-qat-refactor-submission-logic.patch @@ -0,0 +1,379 @@ +From 99b4a13c31aff837af03150dc1b0e79cf6474337 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 May 2022 14:34:09 +0100 +Subject: crypto: qat - refactor submission logic + +From: Giovanni Cabiddu + +[ 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 +Reviewed-by: Marco Chiappero +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + 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 + #include + #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 + #include "icp_qat_fw_pke.h" + #include "adf_accel_devices.h" ++#include "qat_algs_send.h" + #include "adf_transport.h" + #include "adf_common_drv.h" + #include "qat_crypto.h" +@@ -137,6 +138,17 @@ struct qat_asym_request { + void (*cb)(struct icp_qat_fw_pke_resp *resp); + } __aligned(64); + ++static int qat_alg_send_asym_message(struct qat_asym_request *qat_req, ++ struct qat_crypto_instance *inst) ++{ ++ struct qat_alg_req req; ++ ++ req.fw_req = (u32 *)&qat_req->req; ++ req.tx_ring = inst->pke_tx; ++ ++ return qat_alg_send_message(&req); ++} ++ + static void qat_dh_cb(struct icp_qat_fw_pke_resp *resp) + { + struct qat_asym_request *req = (void *)(__force long)resp->opaque; +@@ -213,7 +225,7 @@ static int qat_dh_compute_value(struct kpp_request *req) + struct qat_asym_request *qat_req = + PTR_ALIGN(kpp_request_ctx(req), 64); + struct icp_qat_fw_pke_request *msg = &qat_req->req; +- int ret, ctr = 0; ++ int ret; + int n_input_params = 0; + + if (unlikely(!ctx->xa)) +@@ -338,13 +350,13 @@ static int qat_dh_compute_value(struct kpp_request *req) + msg->input_param_count = n_input_params; + msg->output_param_count = 1; + +- do { +- ret = adf_send_message(ctx->inst->pke_tx, (u32 *)msg); +- } while (ret == -EBUSY && ctr++ < 100); ++ ret = qat_alg_send_asym_message(qat_req, ctx->inst); ++ if (ret == -ENOSPC) ++ goto unmap_all; + +- if (!ret) +- return -EINPROGRESS; ++ return ret; + ++unmap_all: + if (!dma_mapping_error(dev, qat_req->phy_out)) + dma_unmap_single(dev, qat_req->phy_out, + sizeof(struct qat_dh_output_params), +@@ -645,7 +657,7 @@ static int qat_rsa_enc(struct akcipher_request *req) + struct qat_asym_request *qat_req = + PTR_ALIGN(akcipher_request_ctx(req), 64); + struct icp_qat_fw_pke_request *msg = &qat_req->req; +- int ret, ctr = 0; ++ int ret; + + if (unlikely(!ctx->n || !ctx->e)) + return -EINVAL; +@@ -735,13 +747,14 @@ static int qat_rsa_enc(struct akcipher_request *req) + msg->pke_mid.opaque = (u64)(__force long)qat_req; + msg->input_param_count = 3; + msg->output_param_count = 1; +- do { +- ret = adf_send_message(ctx->inst->pke_tx, (u32 *)msg); +- } while (ret == -EBUSY && ctr++ < 100); + +- if (!ret) +- return -EINPROGRESS; ++ ret = qat_alg_send_asym_message(qat_req, ctx->inst); ++ if (ret == -ENOSPC) ++ goto unmap_all; ++ ++ return ret; + ++unmap_all: + if (!dma_mapping_error(dev, qat_req->phy_out)) + dma_unmap_single(dev, qat_req->phy_out, + sizeof(struct qat_rsa_output_params), +@@ -779,7 +792,7 @@ static int qat_rsa_dec(struct akcipher_request *req) + struct qat_asym_request *qat_req = + PTR_ALIGN(akcipher_request_ctx(req), 64); + struct icp_qat_fw_pke_request *msg = &qat_req->req; +- int ret, ctr = 0; ++ int ret; + + if (unlikely(!ctx->n || !ctx->d)) + return -EINVAL; +@@ -887,13 +900,14 @@ static int qat_rsa_dec(struct akcipher_request *req) + msg->input_param_count = 3; + + msg->output_param_count = 1; +- do { +- ret = adf_send_message(ctx->inst->pke_tx, (u32 *)msg); +- } while (ret == -EBUSY && ctr++ < 100); + +- if (!ret) +- return -EINPROGRESS; ++ ret = qat_alg_send_asym_message(qat_req, ctx->inst); ++ if (ret == -ENOSPC) ++ goto unmap_all; ++ ++ return ret; + ++unmap_all: + if (!dma_mapping_error(dev, qat_req->phy_out)) + dma_unmap_single(dev, qat_req->phy_out, + sizeof(struct qat_rsa_output_params), +diff --git a/drivers/crypto/qat/qat_common/qat_crypto.h b/drivers/crypto/qat/qat_common/qat_crypto.h +index 0928f159ea99..0dcba6fc358c 100644 +--- a/drivers/crypto/qat/qat_common/qat_crypto.h ++++ b/drivers/crypto/qat/qat_common/qat_crypto.h +@@ -9,6 +9,11 @@ + #include "adf_accel_devices.h" + #include "icp_qat_fw_la.h" + ++struct qat_alg_req { ++ u32 *fw_req; ++ struct adf_etr_ring_data *tx_ring; ++}; ++ + struct qat_crypto_instance { + struct adf_etr_ring_data *sym_tx; + struct adf_etr_ring_data *sym_rx; +-- +2.35.1 + diff --git a/queue-5.15/crypto-qat-remove-dma_free_coherent-for-dh.patch b/queue-5.15/crypto-qat-remove-dma_free_coherent-for-dh.patch new file mode 100644 index 00000000000..d722620aed7 --- /dev/null +++ b/queue-5.15/crypto-qat-remove-dma_free_coherent-for-dh.patch @@ -0,0 +1,181 @@ +From 997c0edb37fd39f3f31f5e821d2e23f816c70aa4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 May 2022 14:34:13 +0100 +Subject: crypto: qat - remove dma_free_coherent() for DH + +From: Giovanni Cabiddu + +[ 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 +Reviewed-by: Adam Guerin +Reviewed-by: Wojciech Ziemba +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/qat/qat_common/qat_asym_algs.c | 83 ++++++++----------- + 1 file changed, 34 insertions(+), 49 deletions(-) + +diff --git a/drivers/crypto/qat/qat_common/qat_asym_algs.c b/drivers/crypto/qat/qat_common/qat_asym_algs.c +index b31372bddb96..25bbd22085c3 100644 +--- a/drivers/crypto/qat/qat_common/qat_asym_algs.c ++++ b/drivers/crypto/qat/qat_common/qat_asym_algs.c +@@ -164,26 +164,21 @@ static void qat_dh_cb(struct icp_qat_fw_pke_resp *resp) + err = (err == ICP_QAT_FW_COMN_STATUS_FLAG_OK) ? 0 : -EINVAL; + + if (areq->src) { +- if (req->src_align) +- dma_free_coherent(dev, req->ctx.dh->p_size, +- req->src_align, req->in.dh.in.b); +- else +- dma_unmap_single(dev, req->in.dh.in.b, +- req->ctx.dh->p_size, DMA_TO_DEVICE); ++ dma_unmap_single(dev, req->in.dh.in.b, req->ctx.dh->p_size, ++ DMA_TO_DEVICE); ++ kfree_sensitive(req->src_align); + } + + areq->dst_len = req->ctx.dh->p_size; + if (req->dst_align) { + scatterwalk_map_and_copy(req->dst_align, areq->dst, 0, + areq->dst_len, 1); +- +- dma_free_coherent(dev, req->ctx.dh->p_size, req->dst_align, +- req->out.dh.r); +- } else { +- dma_unmap_single(dev, req->out.dh.r, req->ctx.dh->p_size, +- DMA_FROM_DEVICE); ++ kfree_sensitive(req->dst_align); + } + ++ dma_unmap_single(dev, req->out.dh.r, req->ctx.dh->p_size, ++ DMA_FROM_DEVICE); ++ + dma_unmap_single(dev, req->phy_in, sizeof(struct qat_dh_input_params), + DMA_TO_DEVICE); + dma_unmap_single(dev, req->phy_out, +@@ -231,6 +226,7 @@ static int qat_dh_compute_value(struct kpp_request *req) + struct icp_qat_fw_pke_request *msg = &qat_req->req; + int ret; + int n_input_params = 0; ++ u8 *vaddr; + + if (unlikely(!ctx->xa)) + return -EINVAL; +@@ -287,27 +283,24 @@ static int qat_dh_compute_value(struct kpp_request *req) + */ + if (sg_is_last(req->src) && req->src_len == ctx->p_size) { + qat_req->src_align = NULL; +- qat_req->in.dh.in.b = dma_map_single(dev, +- sg_virt(req->src), +- req->src_len, +- DMA_TO_DEVICE); +- if (unlikely(dma_mapping_error(dev, +- qat_req->in.dh.in.b))) +- return ret; +- ++ vaddr = sg_virt(req->src); + } else { + int shift = ctx->p_size - req->src_len; + +- qat_req->src_align = dma_alloc_coherent(dev, +- ctx->p_size, +- &qat_req->in.dh.in.b, +- GFP_KERNEL); ++ qat_req->src_align = kzalloc(ctx->p_size, GFP_KERNEL); + if (unlikely(!qat_req->src_align)) + return ret; + + scatterwalk_map_and_copy(qat_req->src_align + shift, + req->src, 0, req->src_len, 0); ++ ++ vaddr = qat_req->src_align; + } ++ ++ qat_req->in.dh.in.b = dma_map_single(dev, vaddr, ctx->p_size, ++ DMA_TO_DEVICE); ++ if (unlikely(dma_mapping_error(dev, qat_req->in.dh.in.b))) ++ goto unmap_src; + } + /* + * dst can be of any size in valid range, but HW expects it to be the +@@ -318,20 +311,18 @@ static int qat_dh_compute_value(struct kpp_request *req) + */ + if (sg_is_last(req->dst) && req->dst_len == ctx->p_size) { + qat_req->dst_align = NULL; +- qat_req->out.dh.r = dma_map_single(dev, sg_virt(req->dst), +- req->dst_len, +- DMA_FROM_DEVICE); +- +- if (unlikely(dma_mapping_error(dev, qat_req->out.dh.r))) +- goto unmap_src; +- ++ vaddr = sg_virt(req->dst); + } else { +- qat_req->dst_align = dma_alloc_coherent(dev, ctx->p_size, +- &qat_req->out.dh.r, +- GFP_KERNEL); ++ qat_req->dst_align = kzalloc(ctx->p_size, GFP_KERNEL); + if (unlikely(!qat_req->dst_align)) + goto unmap_src; ++ ++ vaddr = qat_req->dst_align; + } ++ qat_req->out.dh.r = dma_map_single(dev, vaddr, ctx->p_size, ++ DMA_FROM_DEVICE); ++ if (unlikely(dma_mapping_error(dev, qat_req->out.dh.r))) ++ goto unmap_dst; + + qat_req->in.dh.in_tab[n_input_params] = 0; + qat_req->out.dh.out_tab[1] = 0; +@@ -371,23 +362,17 @@ static int qat_dh_compute_value(struct kpp_request *req) + sizeof(struct qat_dh_input_params), + DMA_TO_DEVICE); + unmap_dst: +- if (qat_req->dst_align) +- dma_free_coherent(dev, ctx->p_size, qat_req->dst_align, +- qat_req->out.dh.r); +- else +- if (!dma_mapping_error(dev, qat_req->out.dh.r)) +- dma_unmap_single(dev, qat_req->out.dh.r, ctx->p_size, +- DMA_FROM_DEVICE); ++ if (!dma_mapping_error(dev, qat_req->out.dh.r)) ++ dma_unmap_single(dev, qat_req->out.dh.r, ctx->p_size, ++ DMA_FROM_DEVICE); ++ kfree_sensitive(qat_req->dst_align); + unmap_src: + if (req->src) { +- if (qat_req->src_align) +- dma_free_coherent(dev, ctx->p_size, qat_req->src_align, +- qat_req->in.dh.in.b); +- else +- if (!dma_mapping_error(dev, qat_req->in.dh.in.b)) +- dma_unmap_single(dev, qat_req->in.dh.in.b, +- ctx->p_size, +- DMA_TO_DEVICE); ++ if (!dma_mapping_error(dev, qat_req->in.dh.in.b)) ++ dma_unmap_single(dev, qat_req->in.dh.in.b, ++ ctx->p_size, ++ DMA_TO_DEVICE); ++ kfree_sensitive(qat_req->src_align); + } + return ret; + } +-- +2.35.1 + diff --git a/queue-5.15/crypto-qat-remove-dma_free_coherent-for-rsa.patch b/queue-5.15/crypto-qat-remove-dma_free_coherent-for-rsa.patch new file mode 100644 index 00000000000..ba04c33bdc6 --- /dev/null +++ b/queue-5.15/crypto-qat-remove-dma_free_coherent-for-rsa.patch @@ -0,0 +1,269 @@ +From 0fd019b01348c0b3c7d9dc02114e46d7c8ed1d78 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 May 2022 14:34:12 +0100 +Subject: crypto: qat - remove dma_free_coherent() for RSA + +From: Giovanni Cabiddu + +[ 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 +Reviewed-by: Adam Guerin +Reviewed-by: Wojciech Ziemba +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/qat/qat_common/qat_asym_algs.c | 137 ++++++++---------- + 1 file changed, 60 insertions(+), 77 deletions(-) + +diff --git a/drivers/crypto/qat/qat_common/qat_asym_algs.c b/drivers/crypto/qat/qat_common/qat_asym_algs.c +index 2bc02c75398e..b31372bddb96 100644 +--- a/drivers/crypto/qat/qat_common/qat_asym_algs.c ++++ b/drivers/crypto/qat/qat_common/qat_asym_algs.c +@@ -529,25 +529,22 @@ static void qat_rsa_cb(struct icp_qat_fw_pke_resp *resp) + + err = (err == ICP_QAT_FW_COMN_STATUS_FLAG_OK) ? 0 : -EINVAL; + +- if (req->src_align) +- dma_free_coherent(dev, req->ctx.rsa->key_sz, req->src_align, +- req->in.rsa.enc.m); +- else +- dma_unmap_single(dev, req->in.rsa.enc.m, req->ctx.rsa->key_sz, +- DMA_TO_DEVICE); ++ kfree_sensitive(req->src_align); ++ ++ dma_unmap_single(dev, req->in.rsa.enc.m, req->ctx.rsa->key_sz, ++ DMA_TO_DEVICE); + + areq->dst_len = req->ctx.rsa->key_sz; + if (req->dst_align) { + scatterwalk_map_and_copy(req->dst_align, areq->dst, 0, + areq->dst_len, 1); + +- dma_free_coherent(dev, req->ctx.rsa->key_sz, req->dst_align, +- req->out.rsa.enc.c); +- } else { +- dma_unmap_single(dev, req->out.rsa.enc.c, req->ctx.rsa->key_sz, +- DMA_FROM_DEVICE); ++ kfree_sensitive(req->dst_align); + } + ++ dma_unmap_single(dev, req->out.rsa.enc.c, req->ctx.rsa->key_sz, ++ DMA_FROM_DEVICE); ++ + dma_unmap_single(dev, req->phy_in, sizeof(struct qat_rsa_input_params), + DMA_TO_DEVICE); + dma_unmap_single(dev, req->phy_out, +@@ -664,6 +661,7 @@ static int qat_rsa_enc(struct akcipher_request *req) + struct qat_asym_request *qat_req = + PTR_ALIGN(akcipher_request_ctx(req), 64); + struct icp_qat_fw_pke_request *msg = &qat_req->req; ++ u8 *vaddr; + int ret; + + if (unlikely(!ctx->n || !ctx->e)) +@@ -701,40 +699,39 @@ static int qat_rsa_enc(struct akcipher_request *req) + */ + if (sg_is_last(req->src) && req->src_len == ctx->key_sz) { + qat_req->src_align = NULL; +- qat_req->in.rsa.enc.m = dma_map_single(dev, sg_virt(req->src), +- req->src_len, DMA_TO_DEVICE); +- if (unlikely(dma_mapping_error(dev, qat_req->in.rsa.enc.m))) +- return ret; +- ++ vaddr = sg_virt(req->src); + } else { + int shift = ctx->key_sz - req->src_len; + +- qat_req->src_align = dma_alloc_coherent(dev, ctx->key_sz, +- &qat_req->in.rsa.enc.m, +- GFP_KERNEL); ++ qat_req->src_align = kzalloc(ctx->key_sz, GFP_KERNEL); + if (unlikely(!qat_req->src_align)) + return ret; + + scatterwalk_map_and_copy(qat_req->src_align + shift, req->src, + 0, req->src_len, 0); ++ vaddr = qat_req->src_align; + } +- if (sg_is_last(req->dst) && req->dst_len == ctx->key_sz) { +- qat_req->dst_align = NULL; +- qat_req->out.rsa.enc.c = dma_map_single(dev, sg_virt(req->dst), +- req->dst_len, +- DMA_FROM_DEVICE); + +- if (unlikely(dma_mapping_error(dev, qat_req->out.rsa.enc.c))) +- goto unmap_src; ++ qat_req->in.rsa.enc.m = dma_map_single(dev, vaddr, ctx->key_sz, ++ DMA_TO_DEVICE); ++ if (unlikely(dma_mapping_error(dev, qat_req->in.rsa.enc.m))) ++ goto unmap_src; + ++ if (sg_is_last(req->dst) && req->dst_len == ctx->key_sz) { ++ qat_req->dst_align = NULL; ++ vaddr = sg_virt(req->dst); + } else { +- qat_req->dst_align = dma_alloc_coherent(dev, ctx->key_sz, +- &qat_req->out.rsa.enc.c, +- GFP_KERNEL); ++ qat_req->dst_align = kzalloc(ctx->key_sz, GFP_KERNEL); + if (unlikely(!qat_req->dst_align)) + goto unmap_src; +- ++ vaddr = qat_req->dst_align; + } ++ ++ qat_req->out.rsa.enc.c = dma_map_single(dev, vaddr, ctx->key_sz, ++ DMA_FROM_DEVICE); ++ if (unlikely(dma_mapping_error(dev, qat_req->out.rsa.enc.c))) ++ goto unmap_dst; ++ + qat_req->in.rsa.in_tab[3] = 0; + qat_req->out.rsa.out_tab[1] = 0; + qat_req->phy_in = dma_map_single(dev, &qat_req->in.rsa.enc.m, +@@ -772,21 +769,15 @@ static int qat_rsa_enc(struct akcipher_request *req) + sizeof(struct qat_rsa_input_params), + DMA_TO_DEVICE); + unmap_dst: +- if (qat_req->dst_align) +- dma_free_coherent(dev, ctx->key_sz, qat_req->dst_align, +- qat_req->out.rsa.enc.c); +- else +- if (!dma_mapping_error(dev, qat_req->out.rsa.enc.c)) +- dma_unmap_single(dev, qat_req->out.rsa.enc.c, +- ctx->key_sz, DMA_FROM_DEVICE); ++ if (!dma_mapping_error(dev, qat_req->out.rsa.enc.c)) ++ dma_unmap_single(dev, qat_req->out.rsa.enc.c, ++ ctx->key_sz, DMA_FROM_DEVICE); ++ kfree_sensitive(qat_req->dst_align); + unmap_src: +- if (qat_req->src_align) +- dma_free_coherent(dev, ctx->key_sz, qat_req->src_align, +- qat_req->in.rsa.enc.m); +- else +- if (!dma_mapping_error(dev, qat_req->in.rsa.enc.m)) +- dma_unmap_single(dev, qat_req->in.rsa.enc.m, +- ctx->key_sz, DMA_TO_DEVICE); ++ if (!dma_mapping_error(dev, qat_req->in.rsa.enc.m)) ++ dma_unmap_single(dev, qat_req->in.rsa.enc.m, ctx->key_sz, ++ DMA_TO_DEVICE); ++ kfree_sensitive(qat_req->src_align); + return ret; + } + +@@ -799,6 +790,7 @@ static int qat_rsa_dec(struct akcipher_request *req) + struct qat_asym_request *qat_req = + PTR_ALIGN(akcipher_request_ctx(req), 64); + struct icp_qat_fw_pke_request *msg = &qat_req->req; ++ u8 *vaddr; + int ret; + + if (unlikely(!ctx->n || !ctx->d)) +@@ -846,40 +838,37 @@ static int qat_rsa_dec(struct akcipher_request *req) + */ + if (sg_is_last(req->src) && req->src_len == ctx->key_sz) { + qat_req->src_align = NULL; +- qat_req->in.rsa.dec.c = dma_map_single(dev, sg_virt(req->src), +- req->dst_len, DMA_TO_DEVICE); +- if (unlikely(dma_mapping_error(dev, qat_req->in.rsa.dec.c))) +- return ret; +- ++ vaddr = sg_virt(req->src); + } else { + int shift = ctx->key_sz - req->src_len; + +- qat_req->src_align = dma_alloc_coherent(dev, ctx->key_sz, +- &qat_req->in.rsa.dec.c, +- GFP_KERNEL); ++ qat_req->src_align = kzalloc(ctx->key_sz, GFP_KERNEL); + if (unlikely(!qat_req->src_align)) + return ret; + + scatterwalk_map_and_copy(qat_req->src_align + shift, req->src, + 0, req->src_len, 0); ++ vaddr = qat_req->src_align; + } +- if (sg_is_last(req->dst) && req->dst_len == ctx->key_sz) { +- qat_req->dst_align = NULL; +- qat_req->out.rsa.dec.m = dma_map_single(dev, sg_virt(req->dst), +- req->dst_len, +- DMA_FROM_DEVICE); + +- if (unlikely(dma_mapping_error(dev, qat_req->out.rsa.dec.m))) +- goto unmap_src; ++ qat_req->in.rsa.dec.c = dma_map_single(dev, vaddr, ctx->key_sz, ++ DMA_TO_DEVICE); ++ if (unlikely(dma_mapping_error(dev, qat_req->in.rsa.dec.c))) ++ goto unmap_src; + ++ if (sg_is_last(req->dst) && req->dst_len == ctx->key_sz) { ++ qat_req->dst_align = NULL; ++ vaddr = sg_virt(req->dst); + } else { +- qat_req->dst_align = dma_alloc_coherent(dev, ctx->key_sz, +- &qat_req->out.rsa.dec.m, +- GFP_KERNEL); ++ qat_req->dst_align = kzalloc(ctx->key_sz, GFP_KERNEL); + if (unlikely(!qat_req->dst_align)) + goto unmap_src; +- ++ vaddr = qat_req->dst_align; + } ++ qat_req->out.rsa.dec.m = dma_map_single(dev, vaddr, ctx->key_sz, ++ DMA_FROM_DEVICE); ++ if (unlikely(dma_mapping_error(dev, qat_req->out.rsa.dec.m))) ++ goto unmap_dst; + + if (ctx->crt_mode) + qat_req->in.rsa.in_tab[6] = 0; +@@ -925,21 +914,15 @@ static int qat_rsa_dec(struct akcipher_request *req) + sizeof(struct qat_rsa_input_params), + DMA_TO_DEVICE); + unmap_dst: +- if (qat_req->dst_align) +- dma_free_coherent(dev, ctx->key_sz, qat_req->dst_align, +- qat_req->out.rsa.dec.m); +- else +- if (!dma_mapping_error(dev, qat_req->out.rsa.dec.m)) +- dma_unmap_single(dev, qat_req->out.rsa.dec.m, +- ctx->key_sz, DMA_FROM_DEVICE); ++ if (!dma_mapping_error(dev, qat_req->out.rsa.dec.m)) ++ dma_unmap_single(dev, qat_req->out.rsa.dec.m, ++ ctx->key_sz, DMA_FROM_DEVICE); ++ kfree_sensitive(qat_req->dst_align); + unmap_src: +- if (qat_req->src_align) +- dma_free_coherent(dev, ctx->key_sz, qat_req->src_align, +- qat_req->in.rsa.dec.c); +- else +- if (!dma_mapping_error(dev, qat_req->in.rsa.dec.c)) +- dma_unmap_single(dev, qat_req->in.rsa.dec.c, +- ctx->key_sz, DMA_TO_DEVICE); ++ if (!dma_mapping_error(dev, qat_req->in.rsa.dec.c)) ++ dma_unmap_single(dev, qat_req->in.rsa.dec.c, ctx->key_sz, ++ DMA_TO_DEVICE); ++ kfree_sensitive(qat_req->src_align); + return ret; + } + +-- +2.35.1 + diff --git a/queue-5.15/crypto-qat-set-to-zero-dh-parameters-before-free.patch b/queue-5.15/crypto-qat-set-to-zero-dh-parameters-before-free.patch new file mode 100644 index 00000000000..986e087f561 --- /dev/null +++ b/queue-5.15/crypto-qat-set-to-zero-dh-parameters-before-free.patch @@ -0,0 +1,51 @@ +From e0a264c24ee61b90290dd986462452ef7b78cc59 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 May 2022 14:19:27 +0100 +Subject: crypto: qat - set to zero DH parameters before free + +From: Giovanni Cabiddu + +[ 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 +Reviewed-by: Adam Guerin +Reviewed-by: Wojciech Ziemba +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/qat/qat_common/qat_asym_algs.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/crypto/qat/qat_common/qat_asym_algs.c b/drivers/crypto/qat/qat_common/qat_asym_algs.c +index b0b78445418b..5633f9df3b6f 100644 +--- a/drivers/crypto/qat/qat_common/qat_asym_algs.c ++++ b/drivers/crypto/qat/qat_common/qat_asym_algs.c +@@ -420,14 +420,17 @@ static int qat_dh_set_params(struct qat_dh_ctx *ctx, struct dh *params) + static void qat_dh_clear_ctx(struct device *dev, struct qat_dh_ctx *ctx) + { + if (ctx->g) { ++ memset(ctx->g, 0, ctx->p_size); + dma_free_coherent(dev, ctx->p_size, ctx->g, ctx->dma_g); + ctx->g = NULL; + } + if (ctx->xa) { ++ memset(ctx->xa, 0, ctx->p_size); + dma_free_coherent(dev, ctx->p_size, ctx->xa, ctx->dma_xa); + ctx->xa = NULL; + } + if (ctx->p) { ++ memset(ctx->p, 0, ctx->p_size); + dma_free_coherent(dev, ctx->p_size, ctx->p, ctx->dma_p); + ctx->p = NULL; + } +-- +2.35.1 + diff --git a/queue-5.15/crypto-qat-use-pre-allocated-buffers-in-datapath.patch b/queue-5.15/crypto-qat-use-pre-allocated-buffers-in-datapath.patch new file mode 100644 index 00000000000..7bac764891f --- /dev/null +++ b/queue-5.15/crypto-qat-use-pre-allocated-buffers-in-datapath.patch @@ -0,0 +1,207 @@ +From ff874c620d2dd9bf3de09a38974e33988757a202 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 May 2022 14:34:08 +0100 +Subject: crypto: qat - use pre-allocated buffers in datapath + +From: Giovanni Cabiddu + +[ 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 +Signed-off-by: Giovanni Cabiddu +Reviewed-by: Marco Chiappero +Reviewed-by: Wojciech Ziemba +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/qat/qat_common/qat_algs.c | 64 +++++++++++++--------- + drivers/crypto/qat/qat_common/qat_crypto.h | 24 ++++++++ + 2 files changed, 61 insertions(+), 27 deletions(-) + +diff --git a/drivers/crypto/qat/qat_common/qat_algs.c b/drivers/crypto/qat/qat_common/qat_algs.c +index f998ed58457c..ec635fe44c1f 100644 +--- a/drivers/crypto/qat/qat_common/qat_algs.c ++++ b/drivers/crypto/qat/qat_common/qat_algs.c +@@ -46,19 +46,6 @@ + static DEFINE_MUTEX(algs_lock); + static unsigned int active_devs; + +-struct qat_alg_buf { +- u32 len; +- u32 resrvd; +- u64 addr; +-} __packed; +- +-struct qat_alg_buf_list { +- u64 resrvd; +- u32 num_bufs; +- u32 num_mapped_bufs; +- struct qat_alg_buf bufers[]; +-} __packed __aligned(64); +- + /* Common content descriptor */ + struct qat_alg_cd { + union { +@@ -693,7 +680,10 @@ static void qat_alg_free_bufl(struct qat_crypto_instance *inst, + bl->bufers[i].len, DMA_BIDIRECTIONAL); + + dma_unmap_single(dev, blp, sz, DMA_TO_DEVICE); +- kfree(bl); ++ ++ if (!qat_req->buf.sgl_src_valid) ++ kfree(bl); ++ + if (blp != blpout) { + /* If out of place operation dma unmap only data */ + int bufless = blout->num_bufs - blout->num_mapped_bufs; +@@ -704,7 +694,9 @@ static void qat_alg_free_bufl(struct qat_crypto_instance *inst, + DMA_BIDIRECTIONAL); + } + dma_unmap_single(dev, blpout, sz_out, DMA_TO_DEVICE); +- kfree(blout); ++ ++ if (!qat_req->buf.sgl_dst_valid) ++ kfree(blout); + } + } + +@@ -721,15 +713,24 @@ static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst, + dma_addr_t blp = DMA_MAPPING_ERROR; + dma_addr_t bloutp = DMA_MAPPING_ERROR; + struct scatterlist *sg; +- size_t sz_out, sz = struct_size(bufl, bufers, n + 1); ++ size_t sz_out, sz = struct_size(bufl, bufers, n); ++ int node = dev_to_node(&GET_DEV(inst->accel_dev)); + + if (unlikely(!n)) + return -EINVAL; + +- bufl = kzalloc_node(sz, GFP_ATOMIC, +- dev_to_node(&GET_DEV(inst->accel_dev))); +- if (unlikely(!bufl)) +- return -ENOMEM; ++ qat_req->buf.sgl_src_valid = false; ++ qat_req->buf.sgl_dst_valid = false; ++ ++ if (n > QAT_MAX_BUFF_DESC) { ++ bufl = kzalloc_node(sz, GFP_ATOMIC, node); ++ if (unlikely(!bufl)) ++ return -ENOMEM; ++ } else { ++ bufl = &qat_req->buf.sgl_src.sgl_hdr; ++ memset(bufl, 0, sizeof(struct qat_alg_buf_list)); ++ qat_req->buf.sgl_src_valid = true; ++ } + + for_each_sg(sgl, sg, n, i) + bufl->bufers[i].addr = DMA_MAPPING_ERROR; +@@ -760,12 +761,18 @@ static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst, + struct qat_alg_buf *bufers; + + n = sg_nents(sglout); +- sz_out = struct_size(buflout, bufers, n + 1); ++ sz_out = struct_size(buflout, bufers, n); + sg_nctr = 0; +- buflout = kzalloc_node(sz_out, GFP_ATOMIC, +- dev_to_node(&GET_DEV(inst->accel_dev))); +- if (unlikely(!buflout)) +- goto err_in; ++ ++ if (n > QAT_MAX_BUFF_DESC) { ++ buflout = kzalloc_node(sz_out, GFP_ATOMIC, node); ++ if (unlikely(!buflout)) ++ goto err_in; ++ } else { ++ buflout = &qat_req->buf.sgl_dst.sgl_hdr; ++ memset(buflout, 0, sizeof(struct qat_alg_buf_list)); ++ qat_req->buf.sgl_dst_valid = true; ++ } + + bufers = buflout->bufers; + for_each_sg(sglout, sg, n, i) +@@ -810,7 +817,9 @@ static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst, + dma_unmap_single(dev, buflout->bufers[i].addr, + buflout->bufers[i].len, + DMA_BIDIRECTIONAL); +- kfree(buflout); ++ ++ if (!qat_req->buf.sgl_dst_valid) ++ kfree(buflout); + + err_in: + if (!dma_mapping_error(dev, blp)) +@@ -823,7 +832,8 @@ static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst, + bufl->bufers[i].len, + DMA_BIDIRECTIONAL); + +- kfree(bufl); ++ if (!qat_req->buf.sgl_src_valid) ++ kfree(bufl); + + dev_err(dev, "Failed to map buf for dma\n"); + return -ENOMEM; +diff --git a/drivers/crypto/qat/qat_common/qat_crypto.h b/drivers/crypto/qat/qat_common/qat_crypto.h +index b6a4c95ae003..0928f159ea99 100644 +--- a/drivers/crypto/qat/qat_common/qat_crypto.h ++++ b/drivers/crypto/qat/qat_common/qat_crypto.h +@@ -21,6 +21,26 @@ struct qat_crypto_instance { + atomic_t refctr; + }; + ++#define QAT_MAX_BUFF_DESC 4 ++ ++struct qat_alg_buf { ++ u32 len; ++ u32 resrvd; ++ u64 addr; ++} __packed; ++ ++struct qat_alg_buf_list { ++ u64 resrvd; ++ u32 num_bufs; ++ u32 num_mapped_bufs; ++ struct qat_alg_buf bufers[]; ++} __packed; ++ ++struct qat_alg_fixed_buf_list { ++ struct qat_alg_buf_list sgl_hdr; ++ struct qat_alg_buf descriptors[QAT_MAX_BUFF_DESC]; ++} __packed __aligned(64); ++ + struct qat_crypto_request_buffs { + struct qat_alg_buf_list *bl; + dma_addr_t blp; +@@ -28,6 +48,10 @@ struct qat_crypto_request_buffs { + dma_addr_t bloutp; + size_t sz; + size_t sz_out; ++ bool sgl_src_valid; ++ bool sgl_dst_valid; ++ struct qat_alg_fixed_buf_list sgl_src; ++ struct qat_alg_fixed_buf_list sgl_dst; + }; + + struct qat_crypto_request; +-- +2.35.1 + diff --git a/queue-5.15/dlm-fix-pending-remove-if-msg-allocation-fails.patch b/queue-5.15/dlm-fix-pending-remove-if-msg-allocation-fails.patch new file mode 100644 index 00000000000..16a77f77a24 --- /dev/null +++ b/queue-5.15/dlm-fix-pending-remove-if-msg-allocation-fails.patch @@ -0,0 +1,47 @@ +From 95c49d163f77537d678276bbfd2c145e8d3c0e1a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 6 Apr 2022 13:34:16 -0400 +Subject: dlm: fix pending remove if msg allocation fails + +From: Alexander Aring + +[ 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 +Signed-off-by: David Teigland +Signed-off-by: Sasha Levin +--- + fs/dlm/lock.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c +index bb9e85e8819c..9f93496d2cc9 100644 +--- a/fs/dlm/lock.c ++++ b/fs/dlm/lock.c +@@ -4065,13 +4065,14 @@ static void send_repeat_remove(struct dlm_ls *ls, char *ms_name, int len) + rv = _create_message(ls, sizeof(struct dlm_message) + len, + dir_nodeid, DLM_MSG_REMOVE, &ms, &mh); + if (rv) +- return; ++ goto out; + + memcpy(ms->m_extra, name, len); + ms->m_hash = hash; + + send_message(mh, ms); + ++out: + spin_lock(&ls->ls_remove_spin); + ls->ls_remove_len = 0; + memset(ls->ls_remove_name, 0, DLM_RESNAME_MAXLEN); +-- +2.35.1 + diff --git a/queue-5.15/exfat-fix-referencing-wrong-parent-directory-informa.patch b/queue-5.15/exfat-fix-referencing-wrong-parent-directory-informa.patch new file mode 100644 index 00000000000..e23c13cbe59 --- /dev/null +++ b/queue-5.15/exfat-fix-referencing-wrong-parent-directory-informa.patch @@ -0,0 +1,104 @@ +From 6d860fc831dd23c2f8025bce767755709d1dff57 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Apr 2022 11:58:06 +0900 +Subject: exfat: fix referencing wrong parent directory information after + renaming + +From: Yuezhang Mo + +[ 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 +Reviewed-by: Andy Wu +Reviewed-by: Aoyama Wataru +Reviewed-by: Daniel Palmer +Reviewed-by: Sungjong Seo +Signed-off-by: Namjae Jeon +Signed-off-by: Sasha Levin +--- + fs/exfat/namei.c | 27 +-------------------------- + 1 file changed, 1 insertion(+), 26 deletions(-) + +diff --git a/fs/exfat/namei.c b/fs/exfat/namei.c +index 9d8ada781250..939737ba520d 100644 +--- a/fs/exfat/namei.c ++++ b/fs/exfat/namei.c +@@ -1069,6 +1069,7 @@ static int exfat_rename_file(struct inode *inode, struct exfat_chain *p_dir, + + exfat_remove_entries(inode, p_dir, oldentry, 0, + num_old_entries); ++ ei->dir = *p_dir; + ei->entry = newentry; + } else { + if (exfat_get_entry_type(epold) == TYPE_FILE) { +@@ -1159,28 +1160,6 @@ static int exfat_move_file(struct inode *inode, struct exfat_chain *p_olddir, + return 0; + } + +-static void exfat_update_parent_info(struct exfat_inode_info *ei, +- struct inode *parent_inode) +-{ +- struct exfat_sb_info *sbi = EXFAT_SB(parent_inode->i_sb); +- struct exfat_inode_info *parent_ei = EXFAT_I(parent_inode); +- loff_t parent_isize = i_size_read(parent_inode); +- +- /* +- * the problem that struct exfat_inode_info caches wrong parent info. +- * +- * because of flag-mismatch of ei->dir, +- * there is abnormal traversing cluster chain. +- */ +- if (unlikely(parent_ei->flags != ei->dir.flags || +- parent_isize != EXFAT_CLU_TO_B(ei->dir.size, sbi) || +- parent_ei->start_clu != ei->dir.dir)) { +- exfat_chain_set(&ei->dir, parent_ei->start_clu, +- EXFAT_B_TO_CLU_ROUND_UP(parent_isize, sbi), +- parent_ei->flags); +- } +-} +- + /* rename or move a old file into a new file */ + static int __exfat_rename(struct inode *old_parent_inode, + struct exfat_inode_info *ei, struct inode *new_parent_inode, +@@ -1211,8 +1190,6 @@ static int __exfat_rename(struct inode *old_parent_inode, + return -ENOENT; + } + +- exfat_update_parent_info(ei, old_parent_inode); +- + exfat_chain_dup(&olddir, &ei->dir); + dentry = ei->entry; + +@@ -1233,8 +1210,6 @@ static int __exfat_rename(struct inode *old_parent_inode, + goto out; + } + +- exfat_update_parent_info(new_ei, new_parent_inode); +- + p_dir = &(new_ei->dir); + new_entry = new_ei->entry; + ep = exfat_get_dentry(sb, p_dir, new_entry, &new_bh, NULL); +-- +2.35.1 + diff --git a/queue-5.15/iwlwifi-fw-uefi-add-missing-include-guards.patch b/queue-5.15/iwlwifi-fw-uefi-add-missing-include-guards.patch new file mode 100644 index 00000000000..fb7923538b0 --- /dev/null +++ b/queue-5.15/iwlwifi-fw-uefi-add-missing-include-guards.patch @@ -0,0 +1,45 @@ +From 239baa4cd3eda4d636427c9978b24f26c8a07b64 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 24 Oct 2021 18:20:26 +0300 +Subject: iwlwifi: fw: uefi: add missing include guards + +From: Johannes Berg + +[ 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 +Fixes: 84c3c9952afb ("iwlwifi: move UEFI code to a separate file") +Signed-off-by: Luca Coelho +Link: https://lore.kernel.org/r/iwlwifi.20211024181719.7fc9988ed49b.I87e300fab664047581e51fb9b02744c75320d08c@changeid +Signed-off-by: Luca Coelho +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/fw/uefi.h | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h +index 45d0b36d79b5..d552c656ac9f 100644 +--- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h ++++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h +@@ -2,7 +2,8 @@ + /* + * Copyright(c) 2021 Intel Corporation + */ +- ++#ifndef __iwl_fw_uefi__ ++#define __iwl_fw_uefi__ + + #define IWL_UEFI_OEM_PNVM_NAME L"UefiCnvWlanOemSignedPnvm" + #define IWL_UEFI_REDUCED_POWER_NAME L"UefiCnvWlanReducedPower" +@@ -40,3 +41,5 @@ void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len) + return ERR_PTR(-EOPNOTSUPP); + } + #endif /* CONFIG_EFI */ ++ ++#endif /* __iwl_fw_uefi__ */ +-- +2.35.1 + diff --git a/queue-5.15/kvm-x86-use-__try_cmpxchg_user-to-emulate-atomic-acc.patch b/queue-5.15/kvm-x86-use-__try_cmpxchg_user-to-emulate-atomic-acc.patch new file mode 100644 index 00000000000..617517ad2ad --- /dev/null +++ b/queue-5.15/kvm-x86-use-__try_cmpxchg_user-to-emulate-atomic-acc.patch @@ -0,0 +1,108 @@ +From 51f20d6e54986ad0ccb68306cba496699b465007 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Feb 2022 00:49:44 +0000 +Subject: KVM: x86: Use __try_cmpxchg_user() to emulate atomic accesses + +From: Sean Christopherson + +[ 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 +Message-Id: <20220202004945.2540433-5-seanjc@google.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Sasha Levin +--- + arch/x86/kvm/x86.c | 35 ++++++++++++++--------------------- + 1 file changed, 14 insertions(+), 21 deletions(-) + +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index 4525d0b25a43..f9802ceed60a 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -6894,15 +6894,8 @@ static int emulator_write_emulated(struct x86_emulate_ctxt *ctxt, + exception, &write_emultor); + } + +-#define CMPXCHG_TYPE(t, ptr, old, new) \ +- (cmpxchg((t *)(ptr), *(t *)(old), *(t *)(new)) == *(t *)(old)) +- +-#ifdef CONFIG_X86_64 +-# define CMPXCHG64(ptr, old, new) CMPXCHG_TYPE(u64, ptr, old, new) +-#else +-# define CMPXCHG64(ptr, old, new) \ +- (cmpxchg64((u64 *)(ptr), *(u64 *)(old), *(u64 *)(new)) == *(u64 *)(old)) +-#endif ++#define emulator_try_cmpxchg_user(t, ptr, old, new) \ ++ (__try_cmpxchg_user((t __user *)(ptr), (t *)(old), *(t *)(new), efault ## t)) + + static int emulator_cmpxchg_emulated(struct x86_emulate_ctxt *ctxt, + unsigned long addr, +@@ -6911,12 +6904,11 @@ static int emulator_cmpxchg_emulated(struct x86_emulate_ctxt *ctxt, + unsigned int bytes, + struct x86_exception *exception) + { +- struct kvm_host_map map; + struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt); + u64 page_line_mask; ++ unsigned long hva; + gpa_t gpa; +- char *kaddr; +- bool exchanged; ++ int r; + + /* guests cmpxchg8b have to be emulated atomically */ + if (bytes > 8 || (bytes & (bytes - 1))) +@@ -6940,31 +6932,32 @@ static int emulator_cmpxchg_emulated(struct x86_emulate_ctxt *ctxt, + if (((gpa + bytes - 1) & page_line_mask) != (gpa & page_line_mask)) + goto emul_write; + +- if (kvm_vcpu_map(vcpu, gpa_to_gfn(gpa), &map)) ++ hva = kvm_vcpu_gfn_to_hva(vcpu, gpa_to_gfn(gpa)); ++ if (kvm_is_error_hva(addr)) + goto emul_write; + +- kaddr = map.hva + offset_in_page(gpa); ++ hva += offset_in_page(gpa); + + switch (bytes) { + case 1: +- exchanged = CMPXCHG_TYPE(u8, kaddr, old, new); ++ r = emulator_try_cmpxchg_user(u8, hva, old, new); + break; + case 2: +- exchanged = CMPXCHG_TYPE(u16, kaddr, old, new); ++ r = emulator_try_cmpxchg_user(u16, hva, old, new); + break; + case 4: +- exchanged = CMPXCHG_TYPE(u32, kaddr, old, new); ++ r = emulator_try_cmpxchg_user(u32, hva, old, new); + break; + case 8: +- exchanged = CMPXCHG64(kaddr, old, new); ++ r = emulator_try_cmpxchg_user(u64, hva, old, new); + break; + default: + BUG(); + } + +- kvm_vcpu_unmap(vcpu, &map, true); +- +- if (!exchanged) ++ if (r < 0) ++ goto emul_write; ++ if (r) + return X86EMUL_CMPXCHG_FAILED; + + kvm_page_track_write(vcpu, gpa, new, bytes); +-- +2.35.1 + diff --git a/queue-5.15/mt76-fix-use-after-free-by-removing-a-non-rcu-wcid-p.patch b/queue-5.15/mt76-fix-use-after-free-by-removing-a-non-rcu-wcid-p.patch new file mode 100644 index 00000000000..eccff20cf84 --- /dev/null +++ b/queue-5.15/mt76-fix-use-after-free-by-removing-a-non-rcu-wcid-p.patch @@ -0,0 +1,269 @@ +From afddbf32fbd8d90ed32596deb1d0060dd59bb455 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/series b/queue-5.15/series index 756d57442f1..abbce8748aa 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -136,3 +136,41 @@ mm-mempolicy-fix-uninit-value-in-mpol_rebind_policy.patch bpf-make-sure-mac_header-was-set-before-using-it.patch sched-deadline-fix-bug_on-condition-for-deboosted-tasks.patch x86-bugs-warn-when-ibrs-mitigation-is-selected-on-enhanced-ibrs-parts.patch +dlm-fix-pending-remove-if-msg-allocation-fails.patch +x86-uaccess-implement-macros-for-cmpxchg-on-user-add.patch +x86-uaccess-implement-macros-for-cmpxchg-on-user-add.patch-32473 +x86-extable-tidy-up-redundant-handler-functions.patch +x86-extable-get-rid-of-redundant-macros.patch +x86-mce-deduplicate-exception-handling.patch +x86-extable-rework-the-exception-table-mechanics.patch +x86-extable-provide-ex_type_default_mce_safe-and-ex_.patch +bitfield.h-fix-type-of-reg-too-small-for-mask-test.patch +x86-entry_32-remove-.fixup-usage.patch +x86-extable-extend-extable-functionality.patch +x86-msr-remove-.fixup-usage.patch +x86-futex-remove-.fixup-usage.patch +kvm-x86-use-__try_cmpxchg_user-to-emulate-atomic-acc.patch +xhci-dbc-refactor-xhci_dbc_init.patch +xhci-dbc-create-and-remove-dbc-structure-in-dbgtty-d.patch +xhci-dbc-rename-xhci_dbc_init-and-xhci_dbc_exit.patch +xhci-set-hcd-flag-to-defer-primary-roothub-registrat.patch +mt76-fix-use-after-free-by-removing-a-non-rcu-wcid-p.patch +iwlwifi-fw-uefi-add-missing-include-guards.patch +crypto-qat-set-to-zero-dh-parameters-before-free.patch +crypto-qat-use-pre-allocated-buffers-in-datapath.patch +crypto-qat-refactor-submission-logic.patch +crypto-qat-add-backlog-mechanism.patch +crypto-qat-fix-memory-leak-in-rsa.patch +crypto-qat-remove-dma_free_coherent-for-rsa.patch +crypto-qat-remove-dma_free_coherent-for-dh.patch +crypto-qat-add-param-check-for-rsa.patch +crypto-qat-add-param-check-for-dh.patch +crypto-qat-re-enable-registration-of-algorithms.patch +exfat-fix-referencing-wrong-parent-directory-informa.patch +tracing-have-event-format-check-not-flag-p-on-__get_.patch +tracing-place-trace_pid_list-logic-into-abstract-fun.patch +tracing-fix-return-value-of-trace_pid_write.patch +um-virtio_uml-allow-probing-from-devicetree.patch +um-virtio_uml-fix-broken-device-handling-in-time-tra.patch +x86-uaccess-implement-macros-for-cmpxchg-on-user-add.patch-12415 +x86-extable-provide-ex_type_default_mce_safe-and-ex_.patch-2687 diff --git a/queue-5.15/tracing-fix-return-value-of-trace_pid_write.patch b/queue-5.15/tracing-fix-return-value-of-trace_pid_write.patch new file mode 100644 index 00000000000..58758779ec1 --- /dev/null +++ b/queue-5.15/tracing-fix-return-value-of-trace_pid_write.patch @@ -0,0 +1,84 @@ +From 3aea4627fccb657fb44380302e116c6f9a0a9f0f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 3 May 2022 14:05:46 +0900 +Subject: tracing: Fix return value of trace_pid_write() + +From: Wonhyuk Yang + +[ 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 +Cc: Baik Song An +Cc: Hong Yeon Kim +Cc: Taeung Song +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 +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Sasha Levin +--- + kernel/trace/trace.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c +index abbe8489faae..d93f9c59f50e 100644 +--- a/kernel/trace/trace.c ++++ b/kernel/trace/trace.c +@@ -711,13 +711,16 @@ int trace_pid_write(struct trace_pid_list *filtered_pids, + pos = 0; + + ret = trace_get_user(&parser, ubuf, cnt, &pos); +- if (ret < 0 || !trace_parser_loaded(&parser)) ++ if (ret < 0) + break; + + read += ret; + ubuf += ret; + cnt -= ret; + ++ if (!trace_parser_loaded(&parser)) ++ break; ++ + ret = -EINVAL; + if (kstrtoul(parser.buffer, 0, &val)) + break; +@@ -743,7 +746,6 @@ int trace_pid_write(struct trace_pid_list *filtered_pids, + if (!nr_pids) { + /* Cleared the list of pids */ + trace_pid_list_free(pid_list); +- read = ret; + pid_list = NULL; + } + +-- +2.35.1 + diff --git a/queue-5.15/tracing-have-event-format-check-not-flag-p-on-__get_.patch b/queue-5.15/tracing-have-event-format-check-not-flag-p-on-__get_.patch new file mode 100644 index 00000000000..9ebbadf2041 --- /dev/null +++ b/queue-5.15/tracing-have-event-format-check-not-flag-p-on-__get_.patch @@ -0,0 +1,49 @@ +From a6dadf3a29532dbfd9443af5baeb80e80b78596c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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) + +[ 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 +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Sasha Levin +--- + kernel/trace/trace_events.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c +index c072e8b9849c..ea3fbfa87fdd 100644 +--- a/kernel/trace/trace_events.c ++++ b/kernel/trace/trace_events.c +@@ -407,7 +407,14 @@ static void test_event_printk(struct trace_event_call *call) + a = strchr(fmt + i, '&'); + if ((a && (a < r)) || test_field(r, call)) + dereference_flags &= ~(1ULL << arg); ++ } else if ((r = strstr(fmt + i, "__get_dynamic_array(")) && ++ (!c || r < c)) { ++ dereference_flags &= ~(1ULL << arg); ++ } else if ((r = strstr(fmt + i, "__get_sockaddr(")) && ++ (!c || r < c)) { ++ dereference_flags &= ~(1ULL << arg); + } ++ + next_arg: + i--; + arg++; +-- +2.35.1 + diff --git a/queue-5.15/tracing-place-trace_pid_list-logic-into-abstract-fun.patch b/queue-5.15/tracing-place-trace_pid_list-logic-into-abstract-fun.patch new file mode 100644 index 00000000000..fabcb945b3c --- /dev/null +++ b/queue-5.15/tracing-place-trace_pid_list-logic-into-abstract-fun.patch @@ -0,0 +1,497 @@ +From 292cd5bf28c45bc83801b70bb1a221f020fe395f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Sep 2021 21:03:49 -0400 +Subject: tracing: Place trace_pid_list logic into abstract functions + +From: Steven Rostedt (VMware) + +[ 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) +Signed-off-by: Sasha Levin +--- + 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 ++ */ ++#include ++#include ++#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 + #include + ++#include "pid_list.h" ++ + #ifdef CONFIG_FTRACE_SYSCALLS + #include /* For NR_SYSCALLS */ + #include /* some archs define it here */ +@@ -191,10 +193,14 @@ struct trace_options { + struct trace_option_dentry *topts; + }; + +-struct trace_pid_list { +- int pid_max; +- unsigned long *pids; +-}; ++struct trace_pid_list *trace_pid_list_alloc(void); ++void trace_pid_list_free(struct trace_pid_list *pid_list); ++bool trace_pid_list_is_set(struct trace_pid_list *pid_list, unsigned int pid); ++int trace_pid_list_set(struct trace_pid_list *pid_list, unsigned int pid); ++int trace_pid_list_clear(struct trace_pid_list *pid_list, unsigned int pid); ++int trace_pid_list_first(struct trace_pid_list *pid_list, unsigned int *pid); ++int trace_pid_list_next(struct trace_pid_list *pid_list, unsigned int pid, ++ unsigned int *next); + + enum { + TRACE_PIDS = BIT(0), +diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c +index ea3fbfa87fdd..c4f654efb77a 100644 +--- a/kernel/trace/trace_events.c ++++ b/kernel/trace/trace_events.c +@@ -900,10 +900,10 @@ static void __ftrace_clear_event_pids(struct trace_array *tr, int type) + tracepoint_synchronize_unregister(); + + if ((type & TRACE_PIDS) && pid_list) +- trace_free_pid_list(pid_list); ++ trace_pid_list_free(pid_list); + + if ((type & TRACE_NO_PIDS) && no_pid_list) +- trace_free_pid_list(no_pid_list); ++ trace_pid_list_free(no_pid_list); + } + + static void ftrace_clear_event_pids(struct trace_array *tr, int type) +@@ -1982,7 +1982,7 @@ event_pid_write(struct file *filp, const char __user *ubuf, + + if (filtered_pids) { + tracepoint_synchronize_unregister(); +- trace_free_pid_list(filtered_pids); ++ trace_pid_list_free(filtered_pids); + } else if (pid_list && !other_pids) { + register_pid_events(tr); + } +-- +2.35.1 + diff --git a/queue-5.15/um-virtio_uml-allow-probing-from-devicetree.patch b/queue-5.15/um-virtio_uml-allow-probing-from-devicetree.patch new file mode 100644 index 00000000000..411ae6b3782 --- /dev/null +++ b/queue-5.15/um-virtio_uml-allow-probing-from-devicetree.patch @@ -0,0 +1,135 @@ +From d1e3f5bf6241fc4a6f315763eb5608f2f656da4e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Dec 2021 10:04:46 +0100 +Subject: um: virtio_uml: Allow probing from devicetree + +From: Vincent Whitchurch + +[ 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 +Signed-off-by: Richard Weinberger +Signed-off-by: Sasha Levin +--- + 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 ++#include + #include + #include + #include +@@ -49,6 +50,7 @@ struct virtio_uml_platform_data { + struct virtio_uml_device { + struct virtio_device vdev; + struct platform_device *pdev; ++ struct virtio_uml_platform_data *pdata; + + spinlock_t sock_lock; + int sock, req_fd, irq; +@@ -149,7 +151,7 @@ static int vhost_user_recv(struct virtio_uml_device *vu_dev, + if (rc == -ECONNRESET && vu_dev->registered) { + struct virtio_uml_platform_data *pdata; + +- pdata = vu_dev->pdev->dev.platform_data; ++ pdata = vu_dev->pdata; + + virtio_break_device(&vu_dev->vdev); + schedule_work(&pdata->conn_broken_wk); +@@ -1115,21 +1117,63 @@ void virtio_uml_set_no_vq_suspend(struct virtio_device *vdev, + no_vq_suspend ? "dis" : "en"); + } + ++static void vu_of_conn_broken(struct work_struct *wk) ++{ ++ /* ++ * We can't remove the device from the devicetree so the only thing we ++ * can do is warn. ++ */ ++ WARN_ON(1); ++} ++ + /* Platform device */ + ++static struct virtio_uml_platform_data * ++virtio_uml_create_pdata(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct virtio_uml_platform_data *pdata; ++ int ret; ++ ++ if (!np) ++ return ERR_PTR(-EINVAL); ++ ++ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); ++ if (!pdata) ++ return ERR_PTR(-ENOMEM); ++ ++ INIT_WORK(&pdata->conn_broken_wk, vu_of_conn_broken); ++ pdata->pdev = pdev; ++ ++ ret = of_property_read_string(np, "socket-path", &pdata->socket_path); ++ if (ret) ++ return ERR_PTR(ret); ++ ++ ret = of_property_read_u32(np, "virtio-device-id", ++ &pdata->virtio_device_id); ++ if (ret) ++ return ERR_PTR(ret); ++ ++ return pdata; ++} ++ + static int virtio_uml_probe(struct platform_device *pdev) + { + struct virtio_uml_platform_data *pdata = pdev->dev.platform_data; + struct virtio_uml_device *vu_dev; + int rc; + +- if (!pdata) +- return -EINVAL; ++ if (!pdata) { ++ pdata = virtio_uml_create_pdata(pdev); ++ if (IS_ERR(pdata)) ++ return PTR_ERR(pdata); ++ } + + vu_dev = kzalloc(sizeof(*vu_dev), GFP_KERNEL); + if (!vu_dev) + return -ENOMEM; + ++ vu_dev->pdata = pdata; + vu_dev->vdev.dev.parent = &pdev->dev; + vu_dev->vdev.dev.release = virtio_uml_release_dev; + vu_dev->vdev.config = &virtio_uml_config_ops; +-- +2.35.1 + diff --git a/queue-5.15/um-virtio_uml-fix-broken-device-handling-in-time-tra.patch b/queue-5.15/um-virtio_uml-fix-broken-device-handling-in-time-tra.patch new file mode 100644 index 00000000000..c6ce9180d95 --- /dev/null +++ b/queue-5.15/um-virtio_uml-fix-broken-device-handling-in-time-tra.patch @@ -0,0 +1,122 @@ +From 553ad0ac9df5625106875386382e05797b7df23a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 May 2022 22:52:50 +0200 +Subject: um: virtio_uml: Fix broken device handling in time-travel + +From: Johannes Berg + +[ 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 +Signed-off-by: Richard Weinberger +Signed-off-by: Sasha Levin +--- + arch/um/drivers/virtio_uml.c | 33 +++++++++++++++++++++++---------- + 1 file changed, 23 insertions(+), 10 deletions(-) + +diff --git a/arch/um/drivers/virtio_uml.c b/arch/um/drivers/virtio_uml.c +index ba562d68dc04..82ff3785bf69 100644 +--- a/arch/um/drivers/virtio_uml.c ++++ b/arch/um/drivers/virtio_uml.c +@@ -63,6 +63,7 @@ struct virtio_uml_device { + + u8 config_changed_irq:1; + uint64_t vq_irq_vq_map; ++ int recv_rc; + }; + + struct virtio_uml_vq_info { +@@ -148,14 +149,6 @@ static int vhost_user_recv(struct virtio_uml_device *vu_dev, + + rc = vhost_user_recv_header(fd, msg); + +- if (rc == -ECONNRESET && vu_dev->registered) { +- struct virtio_uml_platform_data *pdata; +- +- pdata = vu_dev->pdata; +- +- virtio_break_device(&vu_dev->vdev); +- schedule_work(&pdata->conn_broken_wk); +- } + if (rc) + return rc; + size = msg->header.size; +@@ -164,6 +157,21 @@ static int vhost_user_recv(struct virtio_uml_device *vu_dev, + return full_read(fd, &msg->payload, size, false); + } + ++static void vhost_user_check_reset(struct virtio_uml_device *vu_dev, ++ int rc) ++{ ++ struct virtio_uml_platform_data *pdata = vu_dev->pdata; ++ ++ if (rc != -ECONNRESET) ++ return; ++ ++ if (!vu_dev->registered) ++ return; ++ ++ virtio_break_device(&vu_dev->vdev); ++ schedule_work(&pdata->conn_broken_wk); ++} ++ + static int vhost_user_recv_resp(struct virtio_uml_device *vu_dev, + struct vhost_user_msg *msg, + size_t max_payload_size) +@@ -171,8 +179,10 @@ static int vhost_user_recv_resp(struct virtio_uml_device *vu_dev, + int rc = vhost_user_recv(vu_dev, vu_dev->sock, msg, + max_payload_size, true); + +- if (rc) ++ if (rc) { ++ vhost_user_check_reset(vu_dev, rc); + return rc; ++ } + + if (msg->header.flags != (VHOST_USER_FLAG_REPLY | VHOST_USER_VERSION)) + return -EPROTO; +@@ -369,6 +379,7 @@ static irqreturn_t vu_req_read_message(struct virtio_uml_device *vu_dev, + sizeof(msg.msg.payload) + + sizeof(msg.extra_payload)); + ++ vu_dev->recv_rc = rc; + if (rc) + return IRQ_NONE; + +@@ -412,7 +423,9 @@ static irqreturn_t vu_req_interrupt(int irq, void *data) + if (!um_irq_timetravel_handler_used()) + ret = vu_req_read_message(vu_dev, NULL); + +- if (vu_dev->vq_irq_vq_map) { ++ if (vu_dev->recv_rc) { ++ vhost_user_check_reset(vu_dev, vu_dev->recv_rc); ++ } else if (vu_dev->vq_irq_vq_map) { + struct virtqueue *vq; + + virtio_device_for_each_vq((&vu_dev->vdev), vq) { +-- +2.35.1 + diff --git a/queue-5.15/x86-entry_32-remove-.fixup-usage.patch b/queue-5.15/x86-entry_32-remove-.fixup-usage.patch new file mode 100644 index 00000000000..5559eb1f762 --- /dev/null +++ b/queue-5.15/x86-entry_32-remove-.fixup-usage.patch @@ -0,0 +1,130 @@ +From 682a415a9bab479fe5e3f45a1062a5eb495a9c34 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Nov 2021 11:01:08 +0100 +Subject: x86/entry_32: Remove .fixup usage + +From: Peter Zijlstra + +[ 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) +Reviewed-by: Josh Poimboeuf +Link: https://lore.kernel.org/r/20211110101325.245184699@infradead.org +Signed-off-by: Sasha Levin +--- + arch/x86/entry/entry_32.S | 28 +++++++--------------- + arch/x86/include/asm/extable_fixup_types.h | 2 ++ + arch/x86/mm/extable.c | 14 +++++++++++ + 3 files changed, 24 insertions(+), 20 deletions(-) + +diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S +index 5bd3baf36d87..2cba70f9753b 100644 +--- a/arch/x86/entry/entry_32.S ++++ b/arch/x86/entry/entry_32.S +@@ -270,17 +270,9 @@ + 3: popl %fs + addl $(4 + \pop), %esp /* pop the unused "gs" slot */ + IRET_FRAME +-.pushsection .fixup, "ax" +-4: movl $0, (%esp) +- jmp 1b +-5: movl $0, (%esp) +- jmp 2b +-6: movl $0, (%esp) +- jmp 3b +-.popsection +- _ASM_EXTABLE(1b, 4b) +- _ASM_EXTABLE(2b, 5b) +- _ASM_EXTABLE(3b, 6b) ++ _ASM_EXTABLE_TYPE(1b, 1b, EX_TYPE_POP_ZERO) ++ _ASM_EXTABLE_TYPE(2b, 2b, EX_TYPE_POP_ZERO) ++ _ASM_EXTABLE_TYPE(3b, 3b, EX_TYPE_POP_ZERO) + .endm + + .macro RESTORE_ALL_NMI cr3_reg:req pop=0 +@@ -923,10 +915,8 @@ SYM_FUNC_START(entry_SYSENTER_32) + sti + sysexit + +-.pushsection .fixup, "ax" +-2: movl $0, PT_FS(%esp) +- jmp 1b +-.popsection ++2: movl $0, PT_FS(%esp) ++ jmp 1b + _ASM_EXTABLE(1b, 2b) + + .Lsysenter_fix_flags: +@@ -994,8 +984,7 @@ restore_all_switch_stack: + */ + iret + +-.section .fixup, "ax" +-SYM_CODE_START(asm_iret_error) ++.Lasm_iret_error: + pushl $0 # no error code + pushl $iret_error + +@@ -1012,9 +1001,8 @@ SYM_CODE_START(asm_iret_error) + #endif + + jmp handle_exception +-SYM_CODE_END(asm_iret_error) +-.previous +- _ASM_EXTABLE(.Lirq_return, asm_iret_error) ++ ++ _ASM_EXTABLE(.Lirq_return, .Lasm_iret_error) + SYM_FUNC_END(entry_INT80_32) + + .macro FIXUP_ESPFIX_STACK +diff --git a/arch/x86/include/asm/extable_fixup_types.h b/arch/x86/include/asm/extable_fixup_types.h +index 409524d5d2eb..4d709a2768bb 100644 +--- a/arch/x86/include/asm/extable_fixup_types.h ++++ b/arch/x86/include/asm/extable_fixup_types.h +@@ -19,4 +19,6 @@ + #define EX_TYPE_DEFAULT_MCE_SAFE 12 + #define EX_TYPE_FAULT_MCE_SAFE 13 + ++#define EX_TYPE_POP_ZERO 14 ++ + #endif +diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c +index f37e290e6d0a..f59a4d017070 100644 +--- a/arch/x86/mm/extable.c ++++ b/arch/x86/mm/extable.c +@@ -99,6 +99,18 @@ static bool ex_handler_clear_fs(const struct exception_table_entry *fixup, + return ex_handler_default(fixup, regs); + } + ++static bool ex_handler_pop_zero(const struct exception_table_entry *fixup, ++ struct pt_regs *regs) ++{ ++ /* ++ * Typically used for when "pop %seg" traps, in which case we'll clear ++ * the stack slot and re-try the instruction, which will then succeed ++ * to pop zero. ++ */ ++ *((unsigned long *)regs->sp) = 0; ++ return ex_handler_default(fixup, regs); ++} ++ + int ex_get_fixup_type(unsigned long ip) + { + const struct exception_table_entry *e = search_exception_tables(ip); +@@ -156,6 +168,8 @@ int fixup_exception(struct pt_regs *regs, int trapnr, unsigned long error_code, + case EX_TYPE_WRMSR_IN_MCE: + ex_handler_msr_mce(regs, true); + break; ++ case EX_TYPE_POP_ZERO: ++ return ex_handler_pop_zero(e, regs); + } + BUG(); + } +-- +2.35.1 + diff --git a/queue-5.15/x86-extable-extend-extable-functionality.patch b/queue-5.15/x86-extable-extend-extable-functionality.patch new file mode 100644 index 00000000000..ba1f69f0940 --- /dev/null +++ b/queue-5.15/x86-extable-extend-extable-functionality.patch @@ -0,0 +1,383 @@ +From 008147ae0631666dbe799b2f4ca7dbf37d98d280 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Nov 2021 11:01:09 +0100 +Subject: x86/extable: Extend extable functionality + +From: Peter Zijlstra + +[ 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) +Reviewed-by: Josh Poimboeuf +Reviewed-by: Nick Desaulniers +Tested-by: Nick Desaulniers +Link: https://lore.kernel.org/r/20211110101325.303890153@infradead.org +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include + #include + + #include + #include + #include + #include ++#include ++ ++static inline unsigned long *pt_regs_nr(struct pt_regs *regs, int nr) ++{ ++ int reg_offset = pt_regs_offset(regs, nr); ++ static unsigned long __dummy; ++ ++ if (WARN_ON_ONCE(reg_offset < 0)) ++ return &__dummy; ++ ++ return (unsigned long *)((unsigned long)regs + reg_offset); ++} + + static inline unsigned long + ex_fixup_addr(const struct exception_table_entry *x) +@@ -15,10 +28,15 @@ ex_fixup_addr(const struct exception_table_entry *x) + return (unsigned long)&x->fixup + x->fixup; + } + +-static bool ex_handler_default(const struct exception_table_entry *fixup, ++static bool ex_handler_default(const struct exception_table_entry *e, + struct pt_regs *regs) + { +- regs->ip = ex_fixup_addr(fixup); ++ if (e->data & EX_FLAG_CLEAR_AX) ++ regs->ax = 0; ++ if (e->data & EX_FLAG_CLEAR_DX) ++ regs->dx = 0; ++ ++ regs->ip = ex_fixup_addr(e); + return true; + } + +@@ -111,17 +129,25 @@ static bool ex_handler_pop_zero(const struct exception_table_entry *fixup, + return ex_handler_default(fixup, regs); + } + ++static bool ex_handler_imm_reg(const struct exception_table_entry *fixup, ++ struct pt_regs *regs, int reg, int imm) ++{ ++ *pt_regs_nr(regs, reg) = (long)imm; ++ return ex_handler_default(fixup, regs); ++} ++ + int ex_get_fixup_type(unsigned long ip) + { + const struct exception_table_entry *e = search_exception_tables(ip); + +- return e ? e->type : EX_TYPE_NONE; ++ return e ? FIELD_GET(EX_DATA_TYPE_MASK, e->data) : EX_TYPE_NONE; + } + + int fixup_exception(struct pt_regs *regs, int trapnr, unsigned long error_code, + unsigned long fault_addr) + { + const struct exception_table_entry *e; ++ int type, reg, imm; + + #ifdef CONFIG_PNPBIOS + if (unlikely(SEGMENT_IS_PNP_CODE(regs->cs))) { +@@ -141,7 +167,11 @@ int fixup_exception(struct pt_regs *regs, int trapnr, unsigned long error_code, + if (!e) + return 0; + +- switch (e->type) { ++ type = FIELD_GET(EX_DATA_TYPE_MASK, e->data); ++ reg = FIELD_GET(EX_DATA_REG_MASK, e->data); ++ imm = FIELD_GET(EX_DATA_IMM_MASK, e->data); ++ ++ switch (type) { + case EX_TYPE_DEFAULT: + case EX_TYPE_DEFAULT_MCE_SAFE: + return ex_handler_default(e, regs); +@@ -170,6 +200,8 @@ int fixup_exception(struct pt_regs *regs, int trapnr, unsigned long error_code, + break; + case EX_TYPE_POP_ZERO: + return ex_handler_pop_zero(e, regs); ++ case EX_TYPE_IMM_REG: ++ return ex_handler_imm_reg(e, regs, reg, imm); + } + BUG(); + } +diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c +index 4f3a60037150..dccaab2113f9 100644 +--- a/arch/x86/net/bpf_jit_comp.c ++++ b/arch/x86/net/bpf_jit_comp.c +@@ -1342,7 +1342,7 @@ st: if (is_imm8(insn->off)) + } + ex->insn = delta; + +- ex->type = EX_TYPE_BPF; ++ ex->data = EX_TYPE_BPF; + + if (dst_reg > BPF_REG_9) { + pr_err("verifier error\n"); +-- +2.35.1 + diff --git a/queue-5.15/x86-extable-get-rid-of-redundant-macros.patch b/queue-5.15/x86-extable-get-rid-of-redundant-macros.patch new file mode 100644 index 00000000000..9bdc92290ee --- /dev/null +++ b/queue-5.15/x86-extable-get-rid-of-redundant-macros.patch @@ -0,0 +1,84 @@ +From 7aa07863a71fb723dd25779d2457479386d7e4e3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Sep 2021 15:29:13 +0200 +Subject: x86/extable: Get rid of redundant macros + +From: Thomas Gleixner + +[ 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 +Signed-off-by: Borislav Petkov +Link: https://lkml.kernel.org/r/20210908132525.023659534@linutronix.de +Signed-off-by: Sasha Levin +--- + arch/x86/include/asm/asm.h | 36 ++++++++++++------------------------ + 1 file changed, 12 insertions(+), 24 deletions(-) + +diff --git a/arch/x86/include/asm/asm.h b/arch/x86/include/asm/asm.h +index 3ad3da9a7d97..719955e658a2 100644 +--- a/arch/x86/include/asm/asm.h ++++ b/arch/x86/include/asm/asm.h +@@ -132,18 +132,6 @@ + .long (handler) - . ; \ + .popsection + +-# define _ASM_EXTABLE(from, to) \ +- _ASM_EXTABLE_HANDLE(from, to, ex_handler_default) +- +-# define _ASM_EXTABLE_UA(from, to) \ +- _ASM_EXTABLE_HANDLE(from, to, ex_handler_uaccess) +- +-# define _ASM_EXTABLE_CPY(from, to) \ +- _ASM_EXTABLE_HANDLE(from, to, ex_handler_copy) +- +-# define _ASM_EXTABLE_FAULT(from, to) \ +- _ASM_EXTABLE_HANDLE(from, to, ex_handler_fault) +- + # ifdef CONFIG_KPROBES + # define _ASM_NOKPROBE(entry) \ + .pushsection "_kprobe_blacklist","aw" ; \ +@@ -164,18 +152,6 @@ + " .long (" _EXPAND_EXTABLE_HANDLE(handler) ") - .\n" \ + " .popsection\n" + +-# define _ASM_EXTABLE(from, to) \ +- _ASM_EXTABLE_HANDLE(from, to, ex_handler_default) +- +-# define _ASM_EXTABLE_UA(from, to) \ +- _ASM_EXTABLE_HANDLE(from, to, ex_handler_uaccess) +- +-# define _ASM_EXTABLE_CPY(from, to) \ +- _ASM_EXTABLE_HANDLE(from, to, ex_handler_copy) +- +-# define _ASM_EXTABLE_FAULT(from, to) \ +- _ASM_EXTABLE_HANDLE(from, to, ex_handler_fault) +- + /* For C file, we already have NOKPROBE_SYMBOL macro */ + + /* +@@ -188,6 +164,18 @@ register unsigned long current_stack_pointer asm(_ASM_SP); + #define ASM_CALL_CONSTRAINT "+r" (current_stack_pointer) + #endif /* __ASSEMBLY__ */ + ++#define _ASM_EXTABLE(from, to) \ ++ _ASM_EXTABLE_HANDLE(from, to, ex_handler_default) ++ ++#define _ASM_EXTABLE_UA(from, to) \ ++ _ASM_EXTABLE_HANDLE(from, to, ex_handler_uaccess) ++ ++#define _ASM_EXTABLE_CPY(from, to) \ ++ _ASM_EXTABLE_HANDLE(from, to, ex_handler_copy) ++ ++#define _ASM_EXTABLE_FAULT(from, to) \ ++ _ASM_EXTABLE_HANDLE(from, to, ex_handler_fault) ++ + #endif /* __KERNEL__ */ + + #endif /* _ASM_X86_ASM_H */ +-- +2.35.1 + diff --git a/queue-5.15/x86-extable-provide-ex_type_default_mce_safe-and-ex_.patch b/queue-5.15/x86-extable-provide-ex_type_default_mce_safe-and-ex_.patch new file mode 100644 index 00000000000..252a2b49a22 --- /dev/null +++ b/queue-5.15/x86-extable-provide-ex_type_default_mce_safe-and-ex_.patch @@ -0,0 +1,69 @@ +From a8cb7913e1c09d3ca5ff12f408d26b1a5fb57fb0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Borislav Petkov +Link: https://lkml.kernel.org/r/20210908132525.269689153@linutronix.de +Signed-off-by: Sasha Levin +--- + arch/x86/include/asm/extable_fixup_types.h | 3 +++ + arch/x86/kernel/cpu/mce/severity.c | 2 ++ + arch/x86/mm/extable.c | 2 ++ + 3 files changed, 7 insertions(+) + +diff --git a/arch/x86/include/asm/extable_fixup_types.h b/arch/x86/include/asm/extable_fixup_types.h +index 0adc117618e6..409524d5d2eb 100644 +--- a/arch/x86/include/asm/extable_fixup_types.h ++++ b/arch/x86/include/asm/extable_fixup_types.h +@@ -16,4 +16,7 @@ + #define EX_TYPE_WRMSR_IN_MCE 10 + #define EX_TYPE_RDMSR_IN_MCE 11 + ++#define EX_TYPE_DEFAULT_MCE_SAFE 12 ++#define EX_TYPE_FAULT_MCE_SAFE 13 ++ + #endif +diff --git a/arch/x86/kernel/cpu/mce/severity.c b/arch/x86/kernel/cpu/mce/severity.c +index 74fe763bffda..d9b77a74f8d2 100644 +--- a/arch/x86/kernel/cpu/mce/severity.c ++++ b/arch/x86/kernel/cpu/mce/severity.c +@@ -278,6 +278,8 @@ static int error_context(struct mce *m, struct pt_regs *regs) + m->kflags |= MCE_IN_KERNEL_COPYIN; + fallthrough; + case EX_TYPE_FAULT: ++ case EX_TYPE_FAULT_MCE_SAFE: ++ case EX_TYPE_DEFAULT_MCE_SAFE: + m->kflags |= MCE_IN_KERNEL_RECOV; + return IN_KERNEL_RECOV; + default: +diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c +index 5db46df409b5..f37e290e6d0a 100644 +--- a/arch/x86/mm/extable.c ++++ b/arch/x86/mm/extable.c +@@ -131,8 +131,10 @@ int fixup_exception(struct pt_regs *regs, int trapnr, unsigned long error_code, + + switch (e->type) { + case EX_TYPE_DEFAULT: ++ case EX_TYPE_DEFAULT_MCE_SAFE: + return ex_handler_default(e, regs); + case EX_TYPE_FAULT: ++ case EX_TYPE_FAULT_MCE_SAFE: + return ex_handler_fault(e, regs, trapnr); + case EX_TYPE_UACCESS: + return ex_handler_uaccess(e, regs, trapnr); +-- +2.35.1 + diff --git a/queue-5.15/x86-extable-provide-ex_type_default_mce_safe-and-ex_.patch-2687 b/queue-5.15/x86-extable-provide-ex_type_default_mce_safe-and-ex_.patch-2687 new file mode 100644 index 00000000000..5e90a228f73 --- /dev/null +++ b/queue-5.15/x86-extable-provide-ex_type_default_mce_safe-and-ex_.patch-2687 @@ -0,0 +1,39 @@ +From 53d65cb5022c6e46747335a85b4b638a26a9ca0d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Borislav Petkov +Link: https://lkml.kernel.org/r/20210908132525.269689153@linutronix.de +Signed-off-by: Sasha Levin +--- + arch/x86/include/asm/extable_fixup_types.h | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/arch/x86/include/asm/extable_fixup_types.h b/arch/x86/include/asm/extable_fixup_types.h +index 7469038de100..82c263f74971 100644 +--- a/arch/x86/include/asm/extable_fixup_types.h ++++ b/arch/x86/include/asm/extable_fixup_types.h +@@ -46,4 +46,7 @@ + #define EX_TYPE_IMM_REG 17 /* reg := (long)imm */ + #define EX_TYPE_EFAULT_REG (EX_TYPE_IMM_REG | EX_DATA_IMM(-EFAULT)) + ++#define EX_TYPE_DEFAULT_MCE_SAFE 12 ++#define EX_TYPE_FAULT_MCE_SAFE 13 ++ + #endif +-- +2.35.1 + diff --git a/queue-5.15/x86-extable-rework-the-exception-table-mechanics.patch b/queue-5.15/x86-extable-rework-the-exception-table-mechanics.patch new file mode 100644 index 00000000000..daf5dbcc5d5 --- /dev/null +++ b/queue-5.15/x86-extable-rework-the-exception-table-mechanics.patch @@ -0,0 +1,665 @@ +From fb7315cf41170c88c38982a20db3e321ea9b9663 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Sep 2021 15:29:18 +0200 +Subject: x86/extable: Rework the exception table mechanics + +From: Thomas Gleixner + +[ 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 +Signed-off-by: Borislav Petkov +Acked-by: Alexei Starovoitov +Link: https://lkml.kernel.org/r/20210908132525.211958725@linutronix.de +Signed-off-by: Sasha Levin +--- + 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 ++ + /* 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 ++ + /* +- * 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 + #include + +-typedef bool (*ex_handler_t)(const struct exception_table_entry *, +- struct pt_regs *, int, unsigned long, +- unsigned long); +- + static inline unsigned long + ex_fixup_addr(const struct exception_table_entry *x) + { + return (unsigned long)&x->fixup + x->fixup; + } +-static inline ex_handler_t +-ex_fixup_handler(const struct exception_table_entry *x) +-{ +- return (ex_handler_t)((unsigned long)&x->handler + x->handler); +-} + +-__visible bool ex_handler_default(const struct exception_table_entry *fixup, +- struct pt_regs *regs, int trapnr, +- unsigned long error_code, +- unsigned long fault_addr) ++static bool ex_handler_default(const struct exception_table_entry *fixup, ++ struct pt_regs *regs) + { + regs->ip = ex_fixup_addr(fixup); + return true; + } +-EXPORT_SYMBOL(ex_handler_default); + +-__visible bool ex_handler_fault(const struct exception_table_entry *fixup, +- struct pt_regs *regs, int trapnr, +- unsigned long error_code, +- unsigned long fault_addr) ++static bool ex_handler_fault(const struct exception_table_entry *fixup, ++ struct pt_regs *regs, int trapnr) + { + regs->ax = trapnr; +- return ex_handler_default(fixup, regs, trapnr, error_code, fault_addr); ++ return ex_handler_default(fixup, regs); + } +-EXPORT_SYMBOL_GPL(ex_handler_fault); + + /* + * Handler for when we fail to restore a task's FPU state. We should never get +@@ -54,10 +39,8 @@ EXPORT_SYMBOL_GPL(ex_handler_fault); + * of vulnerability by restoring from the initial state (essentially, zeroing + * out all the FPU registers) if we can't restore from the task's FPU state. + */ +-__visible bool ex_handler_fprestore(const struct exception_table_entry *fixup, +- struct pt_regs *regs, int trapnr, +- unsigned long error_code, +- unsigned long fault_addr) ++static bool ex_handler_fprestore(const struct exception_table_entry *fixup, ++ struct pt_regs *regs) + { + regs->ip = ex_fixup_addr(fixup); + +@@ -67,32 +50,23 @@ __visible bool ex_handler_fprestore(const struct exception_table_entry *fixup, + __restore_fpregs_from_fpstate(&init_fpstate, xfeatures_mask_fpstate()); + return true; + } +-EXPORT_SYMBOL_GPL(ex_handler_fprestore); + +-__visible bool ex_handler_uaccess(const struct exception_table_entry *fixup, +- struct pt_regs *regs, int trapnr, +- unsigned long error_code, +- unsigned long fault_addr) ++static bool ex_handler_uaccess(const struct exception_table_entry *fixup, ++ struct pt_regs *regs, int trapnr) + { + WARN_ONCE(trapnr == X86_TRAP_GP, "General protection fault in user access. Non-canonical address?"); +- return ex_handler_default(fixup, regs, trapnr, error_code, fault_addr); ++ return ex_handler_default(fixup, regs); + } +-EXPORT_SYMBOL(ex_handler_uaccess); + +-__visible bool ex_handler_copy(const struct exception_table_entry *fixup, +- struct pt_regs *regs, int trapnr, +- unsigned long error_code, +- unsigned long fault_addr) ++static bool ex_handler_copy(const struct exception_table_entry *fixup, ++ struct pt_regs *regs, int trapnr) + { + WARN_ONCE(trapnr == X86_TRAP_GP, "General protection fault in user access. Non-canonical address?"); +- return ex_handler_fault(fixup, regs, trapnr, error_code, fault_addr); ++ return ex_handler_fault(fixup, regs, trapnr); + } +-EXPORT_SYMBOL(ex_handler_copy); + +-__visible bool ex_handler_rdmsr_unsafe(const struct exception_table_entry *fixup, +- struct pt_regs *regs, int trapnr, +- unsigned long error_code, +- unsigned long fault_addr) ++static bool ex_handler_rdmsr_unsafe(const struct exception_table_entry *fixup, ++ struct pt_regs *regs) + { + if (pr_warn_once("unchecked MSR access error: RDMSR from 0x%x at rIP: 0x%lx (%pS)\n", + (unsigned int)regs->cx, regs->ip, (void *)regs->ip)) +@@ -101,14 +75,11 @@ __visible bool ex_handler_rdmsr_unsafe(const struct exception_table_entry *fixup + /* Pretend that the read succeeded and returned 0. */ + regs->ax = 0; + regs->dx = 0; +- return ex_handler_default(fixup, regs, trapnr, error_code, fault_addr); ++ return ex_handler_default(fixup, regs); + } +-EXPORT_SYMBOL(ex_handler_rdmsr_unsafe); + +-__visible bool ex_handler_wrmsr_unsafe(const struct exception_table_entry *fixup, +- struct pt_regs *regs, int trapnr, +- unsigned long error_code, +- unsigned long fault_addr) ++static bool ex_handler_wrmsr_unsafe(const struct exception_table_entry *fixup, ++ struct pt_regs *regs) + { + if (pr_warn_once("unchecked MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x) at rIP: 0x%lx (%pS)\n", + (unsigned int)regs->cx, (unsigned int)regs->dx, +@@ -116,44 +87,29 @@ __visible bool ex_handler_wrmsr_unsafe(const struct exception_table_entry *fixup + show_stack_regs(regs); + + /* Pretend that the write succeeded. */ +- return ex_handler_default(fixup, regs, trapnr, error_code, fault_addr); ++ return ex_handler_default(fixup, regs); + } +-EXPORT_SYMBOL(ex_handler_wrmsr_unsafe); + +-__visible bool ex_handler_clear_fs(const struct exception_table_entry *fixup, +- struct pt_regs *regs, int trapnr, +- unsigned long error_code, +- unsigned long fault_addr) ++static bool ex_handler_clear_fs(const struct exception_table_entry *fixup, ++ struct pt_regs *regs) + { + if (static_cpu_has(X86_BUG_NULL_SEG)) + asm volatile ("mov %0, %%fs" : : "rm" (__USER_DS)); + asm volatile ("mov %0, %%fs" : : "rm" (0)); +- return ex_handler_default(fixup, regs, trapnr, error_code, fault_addr); ++ return ex_handler_default(fixup, regs); + } +-EXPORT_SYMBOL(ex_handler_clear_fs); + +-enum handler_type ex_get_fault_handler_type(unsigned long ip) ++int ex_get_fixup_type(unsigned long ip) + { +- const struct exception_table_entry *e; +- ex_handler_t handler; ++ const struct exception_table_entry *e = search_exception_tables(ip); + +- e = search_exception_tables(ip); +- if (!e) +- return EX_HANDLER_NONE; +- handler = ex_fixup_handler(e); +- if (handler == ex_handler_fault) +- return EX_HANDLER_FAULT; +- else if (handler == ex_handler_uaccess || handler == ex_handler_copy) +- return EX_HANDLER_UACCESS; +- else +- return EX_HANDLER_OTHER; ++ return e ? e->type : EX_TYPE_NONE; + } + + int fixup_exception(struct pt_regs *regs, int trapnr, unsigned long error_code, + unsigned long fault_addr) + { + const struct exception_table_entry *e; +- ex_handler_t handler; + + #ifdef CONFIG_PNPBIOS + if (unlikely(SEGMENT_IS_PNP_CODE(regs->cs))) { +@@ -173,8 +129,33 @@ int fixup_exception(struct pt_regs *regs, int trapnr, unsigned long error_code, + if (!e) + return 0; + +- handler = ex_fixup_handler(e); +- return handler(e, regs, trapnr, error_code, fault_addr); ++ switch (e->type) { ++ case EX_TYPE_DEFAULT: ++ return ex_handler_default(e, regs); ++ case EX_TYPE_FAULT: ++ return ex_handler_fault(e, regs, trapnr); ++ case EX_TYPE_UACCESS: ++ return ex_handler_uaccess(e, regs, trapnr); ++ case EX_TYPE_COPY: ++ return ex_handler_copy(e, regs, trapnr); ++ case EX_TYPE_CLEAR_FS: ++ return ex_handler_clear_fs(e, regs); ++ case EX_TYPE_FPU_RESTORE: ++ return ex_handler_fprestore(e, regs); ++ case EX_TYPE_RDMSR: ++ return ex_handler_rdmsr_unsafe(e, regs); ++ case EX_TYPE_WRMSR: ++ return ex_handler_wrmsr_unsafe(e, regs); ++ case EX_TYPE_BPF: ++ return ex_handler_bpf(e, regs); ++ case EX_TYPE_RDMSR_IN_MCE: ++ ex_handler_msr_mce(regs, false); ++ break; ++ case EX_TYPE_WRMSR_IN_MCE: ++ ex_handler_msr_mce(regs, true); ++ break; ++ } ++ BUG(); + } + + extern unsigned int early_recursion_flag; +diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c +index 131f7ceb54dc..4f3a60037150 100644 +--- a/arch/x86/net/bpf_jit_comp.c ++++ b/arch/x86/net/bpf_jit_comp.c +@@ -832,9 +832,7 @@ static int emit_atomic(u8 **pprog, u8 atomic_op, + return 0; + } + +-static bool ex_handler_bpf(const struct exception_table_entry *x, +- struct pt_regs *regs, int trapnr, +- unsigned long error_code, unsigned long fault_addr) ++bool ex_handler_bpf(const struct exception_table_entry *x, struct pt_regs *regs) + { + u32 reg = x->fixup >> 8; + +@@ -1344,12 +1342,7 @@ st: if (is_imm8(insn->off)) + } + ex->insn = delta; + +- delta = (u8 *)ex_handler_bpf - (u8 *)&ex->handler; +- if (!is_simm32(delta)) { +- pr_err("extable->handler doesn't fit into 32-bit\n"); +- return -EFAULT; +- } +- ex->handler = delta; ++ ex->type = EX_TYPE_BPF; + + if (dst_reg > BPF_REG_9) { + pr_err("verifier error\n"); +diff --git a/scripts/sorttable.c b/scripts/sorttable.c +index 6ee4fa882919..278bb53b325c 100644 +--- a/scripts/sorttable.c ++++ b/scripts/sorttable.c +@@ -240,7 +240,7 @@ static void x86_sort_relative_table(char *extab_image, int image_size) + + w(r(loc) + i, loc); + w(r(loc + 1) + i + 4, loc + 1); +- w(r(loc + 2) + i + 8, loc + 2); ++ /* Don't touch the fixup type */ + + i += sizeof(uint32_t) * 3; + } +@@ -253,7 +253,7 @@ static void x86_sort_relative_table(char *extab_image, int image_size) + + w(r(loc) - i, loc); + w(r(loc + 1) - (i + 4), loc + 1); +- w(r(loc + 2) - (i + 8), loc + 2); ++ /* Don't touch the fixup type */ + + i += sizeof(uint32_t) * 3; + } +-- +2.35.1 + diff --git a/queue-5.15/x86-extable-tidy-up-redundant-handler-functions.patch b/queue-5.15/x86-extable-tidy-up-redundant-handler-functions.patch new file mode 100644 index 00000000000..b3a3f255625 --- /dev/null +++ b/queue-5.15/x86-extable-tidy-up-redundant-handler-functions.patch @@ -0,0 +1,80 @@ +From 19962250ce126724b25c19141bb7ae2ab9fc6946 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Sep 2021 15:29:12 +0200 +Subject: x86/extable: Tidy up redundant handler functions + +From: Thomas Gleixner + +[ Upstream commit 326b567f82df0c4c8f50092b9af9a3014616fb3c ] + +No need to have the same code all over the place. + +Signed-off-by: Thomas Gleixner +Signed-off-by: Borislav Petkov +Link: https://lkml.kernel.org/r/20210908132524.963232825@linutronix.de +Signed-off-by: Sasha Levin +--- + arch/x86/mm/extable.c | 16 +++++----------- + 1 file changed, 5 insertions(+), 11 deletions(-) + +diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c +index e1664e9f969c..d9a1046f3a98 100644 +--- a/arch/x86/mm/extable.c ++++ b/arch/x86/mm/extable.c +@@ -39,9 +39,8 @@ __visible bool ex_handler_fault(const struct exception_table_entry *fixup, + unsigned long error_code, + unsigned long fault_addr) + { +- regs->ip = ex_fixup_addr(fixup); + regs->ax = trapnr; +- return true; ++ return ex_handler_default(fixup, regs, trapnr, error_code, fault_addr); + } + EXPORT_SYMBOL_GPL(ex_handler_fault); + +@@ -76,8 +75,7 @@ __visible bool ex_handler_uaccess(const struct exception_table_entry *fixup, + unsigned long fault_addr) + { + WARN_ONCE(trapnr == X86_TRAP_GP, "General protection fault in user access. Non-canonical address?"); +- regs->ip = ex_fixup_addr(fixup); +- return true; ++ return ex_handler_default(fixup, regs, trapnr, error_code, fault_addr); + } + EXPORT_SYMBOL(ex_handler_uaccess); + +@@ -87,9 +85,7 @@ __visible bool ex_handler_copy(const struct exception_table_entry *fixup, + unsigned long fault_addr) + { + WARN_ONCE(trapnr == X86_TRAP_GP, "General protection fault in user access. Non-canonical address?"); +- regs->ip = ex_fixup_addr(fixup); +- regs->ax = trapnr; +- return true; ++ return ex_handler_fault(fixup, regs, trapnr, error_code, fault_addr); + } + EXPORT_SYMBOL(ex_handler_copy); + +@@ -103,10 +99,9 @@ __visible bool ex_handler_rdmsr_unsafe(const struct exception_table_entry *fixup + show_stack_regs(regs); + + /* Pretend that the read succeeded and returned 0. */ +- regs->ip = ex_fixup_addr(fixup); + regs->ax = 0; + regs->dx = 0; +- return true; ++ return ex_handler_default(fixup, regs, trapnr, error_code, fault_addr); + } + EXPORT_SYMBOL(ex_handler_rdmsr_unsafe); + +@@ -121,8 +116,7 @@ __visible bool ex_handler_wrmsr_unsafe(const struct exception_table_entry *fixup + show_stack_regs(regs); + + /* Pretend that the write succeeded. */ +- regs->ip = ex_fixup_addr(fixup); +- return true; ++ return ex_handler_default(fixup, regs, trapnr, error_code, fault_addr); + } + EXPORT_SYMBOL(ex_handler_wrmsr_unsafe); + +-- +2.35.1 + diff --git a/queue-5.15/x86-futex-remove-.fixup-usage.patch b/queue-5.15/x86-futex-remove-.fixup-usage.patch new file mode 100644 index 00000000000..f0405b6e583 --- /dev/null +++ b/queue-5.15/x86-futex-remove-.fixup-usage.patch @@ -0,0 +1,95 @@ +From ba85de34586b23fe8324d35656f8644f1854a8ae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Nov 2021 11:01:11 +0100 +Subject: x86/futex: Remove .fixup usage + +From: Peter Zijlstra + +[ 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) +Reviewed-by: Josh Poimboeuf +Link: https://lore.kernel.org/r/20211110101325.426016322@infradead.org +Signed-off-by: Sasha Levin +--- + arch/x86/include/asm/extable_fixup_types.h | 2 ++ + arch/x86/include/asm/futex.h | 28 +++++++--------------- + 2 files changed, 10 insertions(+), 20 deletions(-) + +diff --git a/arch/x86/include/asm/extable_fixup_types.h b/arch/x86/include/asm/extable_fixup_types.h +index 9d597fe1017d..7469038de100 100644 +--- a/arch/x86/include/asm/extable_fixup_types.h ++++ b/arch/x86/include/asm/extable_fixup_types.h +@@ -42,6 +42,8 @@ + #define EX_TYPE_DEFAULT_MCE_SAFE 14 + #define EX_TYPE_FAULT_MCE_SAFE 15 + #define EX_TYPE_POP_ZERO 16 ++ + #define EX_TYPE_IMM_REG 17 /* reg := (long)imm */ ++#define EX_TYPE_EFAULT_REG (EX_TYPE_IMM_REG | EX_DATA_IMM(-EFAULT)) + + #endif +diff --git a/arch/x86/include/asm/futex.h b/arch/x86/include/asm/futex.h +index f9c00110a69a..99d345b686fa 100644 +--- a/arch/x86/include/asm/futex.h ++++ b/arch/x86/include/asm/futex.h +@@ -17,13 +17,9 @@ do { \ + int oldval = 0, ret; \ + asm volatile("1:\t" insn "\n" \ + "2:\n" \ +- "\t.section .fixup,\"ax\"\n" \ +- "3:\tmov\t%3, %1\n" \ +- "\tjmp\t2b\n" \ +- "\t.previous\n" \ +- _ASM_EXTABLE_UA(1b, 3b) \ ++ _ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_EFAULT_REG, %1) \ + : "=r" (oldval), "=r" (ret), "+m" (*uaddr) \ +- : "i" (-EFAULT), "0" (oparg), "1" (0)); \ ++ : "0" (oparg), "1" (0)); \ + if (ret) \ + goto label; \ + *oval = oldval; \ +@@ -39,15 +35,11 @@ do { \ + "3:\t" LOCK_PREFIX "cmpxchgl %3, %2\n" \ + "\tjnz\t2b\n" \ + "4:\n" \ +- "\t.section .fixup,\"ax\"\n" \ +- "5:\tmov\t%5, %1\n" \ +- "\tjmp\t4b\n" \ +- "\t.previous\n" \ +- _ASM_EXTABLE_UA(1b, 5b) \ +- _ASM_EXTABLE_UA(3b, 5b) \ ++ _ASM_EXTABLE_TYPE_REG(1b, 4b, EX_TYPE_EFAULT_REG, %1) \ ++ _ASM_EXTABLE_TYPE_REG(3b, 4b, EX_TYPE_EFAULT_REG, %1) \ + : "=&a" (oldval), "=&r" (ret), \ + "+m" (*uaddr), "=&r" (tem) \ +- : "r" (oparg), "i" (-EFAULT), "1" (0)); \ ++ : "r" (oparg), "1" (0)); \ + if (ret) \ + goto label; \ + *oval = oldval; \ +@@ -95,15 +87,11 @@ static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, + if (!user_access_begin(uaddr, sizeof(u32))) + return -EFAULT; + asm volatile("\n" +- "1:\t" LOCK_PREFIX "cmpxchgl %4, %2\n" ++ "1:\t" LOCK_PREFIX "cmpxchgl %3, %2\n" + "2:\n" +- "\t.section .fixup, \"ax\"\n" +- "3:\tmov %3, %0\n" +- "\tjmp 2b\n" +- "\t.previous\n" +- _ASM_EXTABLE_UA(1b, 3b) ++ _ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_EFAULT_REG, %0) \ + : "+r" (ret), "=a" (oldval), "+m" (*uaddr) +- : "i" (-EFAULT), "r" (newval), "1" (oldval) ++ : "r" (newval), "1" (oldval) + : "memory" + ); + user_access_end(); +-- +2.35.1 + diff --git a/queue-5.15/x86-mce-deduplicate-exception-handling.patch b/queue-5.15/x86-mce-deduplicate-exception-handling.patch new file mode 100644 index 00000000000..84f909ac9a4 --- /dev/null +++ b/queue-5.15/x86-mce-deduplicate-exception-handling.patch @@ -0,0 +1,83 @@ +From 59c536dddffbccd8cd338206c01c9d46dc99496e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Sep 2021 15:29:15 +0200 +Subject: x86/mce: Deduplicate exception handling + +From: Thomas Gleixner + +[ Upstream commit e42404afc4ca856c48f1e05752541faa3587c472 ] + +Prepare code for further simplification. No functional change. + +Signed-off-by: Thomas Gleixner +Signed-off-by: Borislav Petkov +Link: https://lkml.kernel.org/r/20210908132525.096452100@linutronix.de +Signed-off-by: Sasha Levin +--- + arch/x86/kernel/cpu/mce/core.c | 34 +++++++++++++++++----------------- + 1 file changed, 17 insertions(+), 17 deletions(-) + +diff --git a/arch/x86/kernel/cpu/mce/core.c b/arch/x86/kernel/cpu/mce/core.c +index 848cfb013f58..d8da3acf1ffd 100644 +--- a/arch/x86/kernel/cpu/mce/core.c ++++ b/arch/x86/kernel/cpu/mce/core.c +@@ -382,13 +382,16 @@ static int msr_to_offset(u32 msr) + return -1; + } + +-__visible bool ex_handler_rdmsr_fault(const struct exception_table_entry *fixup, +- struct pt_regs *regs, int trapnr, +- unsigned long error_code, +- unsigned long fault_addr) ++static void ex_handler_msr_mce(struct pt_regs *regs, bool wrmsr) + { +- pr_emerg("MSR access error: RDMSR from 0x%x at rIP: 0x%lx (%pS)\n", +- (unsigned int)regs->cx, regs->ip, (void *)regs->ip); ++ if (wrmsr) { ++ pr_emerg("MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x) at rIP: 0x%lx (%pS)\n", ++ (unsigned int)regs->cx, (unsigned int)regs->dx, (unsigned int)regs->ax, ++ regs->ip, (void *)regs->ip); ++ } else { ++ pr_emerg("MSR access error: RDMSR from 0x%x at rIP: 0x%lx (%pS)\n", ++ (unsigned int)regs->cx, regs->ip, (void *)regs->ip); ++ } + + show_stack_regs(regs); + +@@ -396,7 +399,14 @@ __visible bool ex_handler_rdmsr_fault(const struct exception_table_entry *fixup, + + while (true) + cpu_relax(); ++} + ++__visible bool ex_handler_rdmsr_fault(const struct exception_table_entry *fixup, ++ struct pt_regs *regs, int trapnr, ++ unsigned long error_code, ++ unsigned long fault_addr) ++{ ++ ex_handler_msr_mce(regs, false); + return true; + } + +@@ -441,17 +451,7 @@ __visible bool ex_handler_wrmsr_fault(const struct exception_table_entry *fixup, + unsigned long error_code, + unsigned long fault_addr) + { +- pr_emerg("MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x) at rIP: 0x%lx (%pS)\n", +- (unsigned int)regs->cx, (unsigned int)regs->dx, (unsigned int)regs->ax, +- regs->ip, (void *)regs->ip); +- +- show_stack_regs(regs); +- +- panic("MCA architectural violation!\n"); +- +- while (true) +- cpu_relax(); +- ++ ex_handler_msr_mce(regs, true); + return true; + } + +-- +2.35.1 + diff --git a/queue-5.15/x86-msr-remove-.fixup-usage.patch b/queue-5.15/x86-msr-remove-.fixup-usage.patch new file mode 100644 index 00000000000..6d934cd1936 --- /dev/null +++ b/queue-5.15/x86-msr-remove-.fixup-usage.patch @@ -0,0 +1,185 @@ +From 0d99dcd85c36ae7f26fb7af68f3555028a4926b1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Nov 2021 11:01:10 +0100 +Subject: x86/msr: Remove .fixup usage + +From: Peter Zijlstra + +[ 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) +Reviewed-by: Josh Poimboeuf +Link: https://lore.kernel.org/r/20211110101325.364084212@infradead.org +Signed-off-by: Sasha Levin +--- + arch/x86/include/asm/extable_fixup_types.h | 23 +++++----- + arch/x86/include/asm/msr.h | 26 ++++------- + arch/x86/mm/extable.c | 51 ++++++++++++---------- + 3 files changed, 47 insertions(+), 53 deletions(-) + +diff --git a/arch/x86/include/asm/extable_fixup_types.h b/arch/x86/include/asm/extable_fixup_types.h +index 944f8329022a..9d597fe1017d 100644 +--- a/arch/x86/include/asm/extable_fixup_types.h ++++ b/arch/x86/include/asm/extable_fixup_types.h +@@ -32,17 +32,16 @@ + #define EX_TYPE_COPY 4 + #define EX_TYPE_CLEAR_FS 5 + #define EX_TYPE_FPU_RESTORE 6 +-#define EX_TYPE_WRMSR 7 +-#define EX_TYPE_RDMSR 8 +-#define EX_TYPE_BPF 9 +- +-#define EX_TYPE_WRMSR_IN_MCE 10 +-#define EX_TYPE_RDMSR_IN_MCE 11 +- +-#define EX_TYPE_DEFAULT_MCE_SAFE 12 +-#define EX_TYPE_FAULT_MCE_SAFE 13 +- +-#define EX_TYPE_POP_ZERO 14 +-#define EX_TYPE_IMM_REG 15 /* reg := (long)imm */ ++#define EX_TYPE_BPF 7 ++#define EX_TYPE_WRMSR 8 ++#define EX_TYPE_RDMSR 9 ++#define EX_TYPE_WRMSR_SAFE 10 /* reg := -EIO */ ++#define EX_TYPE_RDMSR_SAFE 11 /* reg := -EIO */ ++#define EX_TYPE_WRMSR_IN_MCE 12 ++#define EX_TYPE_RDMSR_IN_MCE 13 ++#define EX_TYPE_DEFAULT_MCE_SAFE 14 ++#define EX_TYPE_FAULT_MCE_SAFE 15 ++#define EX_TYPE_POP_ZERO 16 ++#define EX_TYPE_IMM_REG 17 /* reg := (long)imm */ + + #endif +diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h +index 6b52182e178a..d42e6c6b47b1 100644 +--- a/arch/x86/include/asm/msr.h ++++ b/arch/x86/include/asm/msr.h +@@ -137,17 +137,11 @@ static inline unsigned long long native_read_msr_safe(unsigned int msr, + { + DECLARE_ARGS(val, low, high); + +- asm volatile("2: rdmsr ; xor %[err],%[err]\n" +- "1:\n\t" +- ".section .fixup,\"ax\"\n\t" +- "3: mov %[fault],%[err]\n\t" +- "xorl %%eax, %%eax\n\t" +- "xorl %%edx, %%edx\n\t" +- "jmp 1b\n\t" +- ".previous\n\t" +- _ASM_EXTABLE(2b, 3b) ++ asm volatile("1: rdmsr ; xor %[err],%[err]\n" ++ "2:\n\t" ++ _ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_RDMSR_SAFE, %[err]) + : [err] "=r" (*err), EAX_EDX_RET(val, low, high) +- : "c" (msr), [fault] "i" (-EIO)); ++ : "c" (msr)); + if (tracepoint_enabled(read_msr)) + do_trace_read_msr(msr, EAX_EDX_VAL(val, low, high), *err); + return EAX_EDX_VAL(val, low, high); +@@ -169,15 +163,11 @@ native_write_msr_safe(unsigned int msr, u32 low, u32 high) + { + int err; + +- asm volatile("2: wrmsr ; xor %[err],%[err]\n" +- "1:\n\t" +- ".section .fixup,\"ax\"\n\t" +- "3: mov %[fault],%[err] ; jmp 1b\n\t" +- ".previous\n\t" +- _ASM_EXTABLE(2b, 3b) ++ asm volatile("1: wrmsr ; xor %[err],%[err]\n" ++ "2:\n\t" ++ _ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_WRMSR_SAFE, %[err]) + : [err] "=a" (err) +- : "c" (msr), "0" (low), "d" (high), +- [fault] "i" (-EIO) ++ : "c" (msr), "0" (low), "d" (high) + : "memory"); + if (tracepoint_enabled(write_msr)) + do_trace_write_msr(msr, ((u64)high << 32 | low), err); +diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c +index 251732113624..1c558f8e8c07 100644 +--- a/arch/x86/mm/extable.c ++++ b/arch/x86/mm/extable.c +@@ -83,28 +83,29 @@ static bool ex_handler_copy(const struct exception_table_entry *fixup, + return ex_handler_fault(fixup, regs, trapnr); + } + +-static bool ex_handler_rdmsr_unsafe(const struct exception_table_entry *fixup, +- struct pt_regs *regs) ++static bool ex_handler_msr(const struct exception_table_entry *fixup, ++ struct pt_regs *regs, bool wrmsr, bool safe, int reg) + { +- if (pr_warn_once("unchecked MSR access error: RDMSR from 0x%x at rIP: 0x%lx (%pS)\n", ++ if (!safe && wrmsr && ++ pr_warn_once("unchecked MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x) at rIP: 0x%lx (%pS)\n", ++ (unsigned int)regs->cx, (unsigned int)regs->dx, ++ (unsigned int)regs->ax, regs->ip, (void *)regs->ip)) ++ show_stack_regs(regs); ++ ++ if (!safe && !wrmsr && ++ pr_warn_once("unchecked MSR access error: RDMSR from 0x%x at rIP: 0x%lx (%pS)\n", + (unsigned int)regs->cx, regs->ip, (void *)regs->ip)) + show_stack_regs(regs); + +- /* Pretend that the read succeeded and returned 0. */ +- regs->ax = 0; +- regs->dx = 0; +- return ex_handler_default(fixup, regs); +-} ++ if (!wrmsr) { ++ /* Pretend that the read succeeded and returned 0. */ ++ regs->ax = 0; ++ regs->dx = 0; ++ } + +-static bool ex_handler_wrmsr_unsafe(const struct exception_table_entry *fixup, +- struct pt_regs *regs) +-{ +- if (pr_warn_once("unchecked MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x) at rIP: 0x%lx (%pS)\n", +- (unsigned int)regs->cx, (unsigned int)regs->dx, +- (unsigned int)regs->ax, regs->ip, (void *)regs->ip)) +- show_stack_regs(regs); ++ if (safe) ++ *pt_regs_nr(regs, reg) = -EIO; + +- /* Pretend that the write succeeded. */ + return ex_handler_default(fixup, regs); + } + +@@ -186,18 +187,22 @@ int fixup_exception(struct pt_regs *regs, int trapnr, unsigned long error_code, + return ex_handler_clear_fs(e, regs); + case EX_TYPE_FPU_RESTORE: + return ex_handler_fprestore(e, regs); +- case EX_TYPE_RDMSR: +- return ex_handler_rdmsr_unsafe(e, regs); +- case EX_TYPE_WRMSR: +- return ex_handler_wrmsr_unsafe(e, regs); + case EX_TYPE_BPF: + return ex_handler_bpf(e, regs); +- case EX_TYPE_RDMSR_IN_MCE: +- ex_handler_msr_mce(regs, false); +- break; ++ case EX_TYPE_WRMSR: ++ return ex_handler_msr(e, regs, true, false, reg); ++ case EX_TYPE_RDMSR: ++ return ex_handler_msr(e, regs, false, false, reg); ++ case EX_TYPE_WRMSR_SAFE: ++ return ex_handler_msr(e, regs, true, true, reg); ++ case EX_TYPE_RDMSR_SAFE: ++ return ex_handler_msr(e, regs, false, true, reg); + case EX_TYPE_WRMSR_IN_MCE: + ex_handler_msr_mce(regs, true); + break; ++ case EX_TYPE_RDMSR_IN_MCE: ++ ex_handler_msr_mce(regs, false); ++ break; + case EX_TYPE_POP_ZERO: + return ex_handler_pop_zero(e, regs); + case EX_TYPE_IMM_REG: +-- +2.35.1 + diff --git a/queue-5.15/x86-uaccess-implement-macros-for-cmpxchg-on-user-add.patch b/queue-5.15/x86-uaccess-implement-macros-for-cmpxchg-on-user-add.patch new file mode 100644 index 00000000000..6a3ed3308d9 --- /dev/null +++ b/queue-5.15/x86-uaccess-implement-macros-for-cmpxchg-on-user-add.patch @@ -0,0 +1,196 @@ +From ac2daa7af9eb665242ed56b610762a7ca45bcbbc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Feb 2022 00:49:42 +0000 +Subject: x86/uaccess: Implement macros for CMPXCHG on user addresses + +From: Peter Zijlstra + +[ 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) +Co-developed-by: Sean Christopherson +Signed-off-by: Sean Christopherson +Message-Id: <20220202004945.2540433-3-seanjc@google.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Sasha Levin +--- + 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 to match the size expected by the asm helper. ++ * clang/LLVM compiles all cases and only discards the unused paths after ++ * processing errors, which breaks i386 if the pointer is an 8-byte value. ++ */ ++#define unsafe_try_cmpxchg_user(_ptr, _oldp, _nval, _label) ({ \ ++ bool __ret; \ ++ __chk_user_ptr(_ptr); \ ++ switch (sizeof(*(_ptr))) { \ ++ case 1: __ret = __try_cmpxchg_user_asm("b", "q", \ ++ (__force u8 *)(_ptr), (_oldp), \ ++ (_nval), _label); \ ++ break; \ ++ case 2: __ret = __try_cmpxchg_user_asm("w", "r", \ ++ (__force u16 *)(_ptr), (_oldp), \ ++ (_nval), _label); \ ++ break; \ ++ case 4: __ret = __try_cmpxchg_user_asm("l", "r", \ ++ (__force u32 *)(_ptr), (_oldp), \ ++ (_nval), _label); \ ++ break; \ ++ case 8: __ret = __try_cmpxchg64_user_asm((__force u64 *)(_ptr), (_oldp),\ ++ (_nval), _label); \ ++ break; \ ++ default: __try_cmpxchg_user_wrong_size(); \ ++ } \ ++ __ret; }) ++ ++/* "Returns" 0 on success, 1 on failure, -EFAULT if the access faults. */ ++#define __try_cmpxchg_user(_ptr, _oldp, _nval, _label) ({ \ ++ int __ret = -EFAULT; \ ++ __uaccess_begin_nospec(); \ ++ __ret = !unsafe_try_cmpxchg_user(_ptr, _oldp, _nval, _label); \ ++_label: \ ++ __uaccess_end(); \ ++ __ret; \ ++ }) ++ + /* + * We want the unsafe accessors to always be inlined and use + * the error labels - thus the macro games. +-- +2.35.1 + diff --git a/queue-5.15/x86-uaccess-implement-macros-for-cmpxchg-on-user-add.patch-12415 b/queue-5.15/x86-uaccess-implement-macros-for-cmpxchg-on-user-add.patch-12415 new file mode 100644 index 00000000000..c87474b8a1a --- /dev/null +++ b/queue-5.15/x86-uaccess-implement-macros-for-cmpxchg-on-user-add.patch-12415 @@ -0,0 +1,144 @@ +From 8a0706834a022fcc9d6d7b4b80c9cc8f3342539f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Feb 2022 00:49:42 +0000 +Subject: x86/uaccess: Implement macros for CMPXCHG on user addresses + +From: Peter Zijlstra + +[ 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) +Co-developed-by: Sean Christopherson +Signed-off-by: Sean Christopherson +Message-Id: <20220202004945.2540433-3-seanjc@google.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Sasha Levin +--- + arch/x86/include/asm/uaccess.h | 97 ++++++++++++++++++++++++++++++++++ + 1 file changed, 97 insertions(+) + +diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h +index 775f1162da74..9af1a27fa568 100644 +--- a/arch/x86/include/asm/uaccess.h ++++ b/arch/x86/include/asm/uaccess.h +@@ -608,6 +608,103 @@ do { \ + #endif // CONFIG_X86_32 + #endif // CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT + ++#ifdef CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT ++#define __try_cmpxchg_user_asm(itype, ltype, _ptr, _pold, _new, label) ({ \ ++ bool success; \ ++ __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold); \ ++ __typeof__(*(_ptr)) __old = *_old; \ ++ __typeof__(*(_ptr)) __new = (_new); \ ++ asm_volatile_goto("\n" \ ++ "1: " LOCK_PREFIX "cmpxchg"itype" %[new], %[ptr]\n"\ ++ _ASM_EXTABLE_UA(1b, %l[label]) \ ++ : CC_OUT(z) (success), \ ++ [ptr] "+m" (*_ptr), \ ++ [old] "+a" (__old) \ ++ : [new] ltype (__new) \ ++ : "memory" \ ++ : label); \ ++ if (unlikely(!success)) \ ++ *_old = __old; \ ++ likely(success); }) ++ ++#ifdef CONFIG_X86_32 ++#define __try_cmpxchg64_user_asm(_ptr, _pold, _new, label) ({ \ ++ bool success; \ ++ __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold); \ ++ __typeof__(*(_ptr)) __old = *_old; \ ++ __typeof__(*(_ptr)) __new = (_new); \ ++ asm_volatile_goto("\n" \ ++ "1: " LOCK_PREFIX "cmpxchg8b %[ptr]\n" \ ++ _ASM_EXTABLE_UA(1b, %l[label]) \ ++ : CC_OUT(z) (success), \ ++ "+A" (__old), \ ++ [ptr] "+m" (*_ptr) \ ++ : "b" ((u32)__new), \ ++ "c" ((u32)((u64)__new >> 32)) \ ++ : "memory" \ ++ : label); \ ++ if (unlikely(!success)) \ ++ *_old = __old; \ ++ likely(success); }) ++#endif // CONFIG_X86_32 ++#else // !CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT ++#define __try_cmpxchg_user_asm(itype, ltype, _ptr, _pold, _new, label) ({ \ ++ int __err = 0; \ ++ bool success; \ ++ __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold); \ ++ __typeof__(*(_ptr)) __old = *_old; \ ++ __typeof__(*(_ptr)) __new = (_new); \ ++ asm volatile("\n" \ ++ "1: " LOCK_PREFIX "cmpxchg"itype" %[new], %[ptr]\n"\ ++ CC_SET(z) \ ++ "2:\n" \ ++ _ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_EFAULT_REG, \ ++ %[errout]) \ ++ : CC_OUT(z) (success), \ ++ [errout] "+r" (__err), \ ++ [ptr] "+m" (*_ptr), \ ++ [old] "+a" (__old) \ ++ : [new] ltype (__new) \ ++ : "memory", "cc"); \ ++ if (unlikely(__err)) \ ++ goto label; \ ++ if (unlikely(!success)) \ ++ *_old = __old; \ ++ likely(success); }) ++ ++#ifdef CONFIG_X86_32 ++/* ++ * Unlike the normal CMPXCHG, hardcode ECX for both success/fail and error. ++ * There are only six GPRs available and four (EAX, EBX, ECX, and EDX) are ++ * hardcoded by CMPXCHG8B, leaving only ESI and EDI. If the compiler uses ++ * both ESI and EDI for the memory operand, compilation will fail if the error ++ * is an input+output as there will be no register available for input. ++ */ ++#define __try_cmpxchg64_user_asm(_ptr, _pold, _new, label) ({ \ ++ int __result; \ ++ __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold); \ ++ __typeof__(*(_ptr)) __old = *_old; \ ++ __typeof__(*(_ptr)) __new = (_new); \ ++ asm volatile("\n" \ ++ "1: " LOCK_PREFIX "cmpxchg8b %[ptr]\n" \ ++ "mov $0, %%ecx\n\t" \ ++ "setz %%cl\n" \ ++ "2:\n" \ ++ _ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_EFAULT_REG, %%ecx) \ ++ : [result]"=c" (__result), \ ++ "+A" (__old), \ ++ [ptr] "+m" (*_ptr) \ ++ : "b" ((u32)__new), \ ++ "c" ((u32)((u64)__new >> 32)) \ ++ : "memory", "cc"); \ ++ if (unlikely(__result < 0)) \ ++ goto label; \ ++ if (unlikely(!__result)) \ ++ *_old = __old; \ ++ likely(__result); }) ++#endif // CONFIG_X86_32 ++#endif // CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT ++ + /* FIXME: this hack is definitely wrong -AK */ + struct __large_struct { unsigned long buf[100]; }; + #define __m(x) (*(struct __large_struct __user *)(x)) +-- +2.35.1 + diff --git a/queue-5.15/x86-uaccess-implement-macros-for-cmpxchg-on-user-add.patch-32473 b/queue-5.15/x86-uaccess-implement-macros-for-cmpxchg-on-user-add.patch-32473 new file mode 100644 index 00000000000..63e8637ab83 --- /dev/null +++ b/queue-5.15/x86-uaccess-implement-macros-for-cmpxchg-on-user-add.patch-32473 @@ -0,0 +1,144 @@ +From 9fd1d1b2e1d0f4aadee5632111f011a0a4e2ca5d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Feb 2022 00:49:42 +0000 +Subject: x86/uaccess: Implement macros for CMPXCHG on user addresses + +From: Peter Zijlstra + +[ 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) +Co-developed-by: Sean Christopherson +Signed-off-by: Sean Christopherson +Message-Id: <20220202004945.2540433-3-seanjc@google.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Sasha Levin +--- + arch/x86/include/asm/uaccess.h | 97 ++++++++++++++++++++++++++++++++++ + 1 file changed, 97 insertions(+) + +diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h +index 2f4c9c168b11..775f1162da74 100644 +--- a/arch/x86/include/asm/uaccess.h ++++ b/arch/x86/include/asm/uaccess.h +@@ -511,6 +511,103 @@ do { \ + #endif // CONFIG_X86_32 + #endif // CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT + ++#ifdef CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT ++#define __try_cmpxchg_user_asm(itype, ltype, _ptr, _pold, _new, label) ({ \ ++ bool success; \ ++ __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold); \ ++ __typeof__(*(_ptr)) __old = *_old; \ ++ __typeof__(*(_ptr)) __new = (_new); \ ++ asm_volatile_goto("\n" \ ++ "1: " LOCK_PREFIX "cmpxchg"itype" %[new], %[ptr]\n"\ ++ _ASM_EXTABLE_UA(1b, %l[label]) \ ++ : CC_OUT(z) (success), \ ++ [ptr] "+m" (*_ptr), \ ++ [old] "+a" (__old) \ ++ : [new] ltype (__new) \ ++ : "memory" \ ++ : label); \ ++ if (unlikely(!success)) \ ++ *_old = __old; \ ++ likely(success); }) ++ ++#ifdef CONFIG_X86_32 ++#define __try_cmpxchg64_user_asm(_ptr, _pold, _new, label) ({ \ ++ bool success; \ ++ __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold); \ ++ __typeof__(*(_ptr)) __old = *_old; \ ++ __typeof__(*(_ptr)) __new = (_new); \ ++ asm_volatile_goto("\n" \ ++ "1: " LOCK_PREFIX "cmpxchg8b %[ptr]\n" \ ++ _ASM_EXTABLE_UA(1b, %l[label]) \ ++ : CC_OUT(z) (success), \ ++ "+A" (__old), \ ++ [ptr] "+m" (*_ptr) \ ++ : "b" ((u32)__new), \ ++ "c" ((u32)((u64)__new >> 32)) \ ++ : "memory" \ ++ : label); \ ++ if (unlikely(!success)) \ ++ *_old = __old; \ ++ likely(success); }) ++#endif // CONFIG_X86_32 ++#else // !CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT ++#define __try_cmpxchg_user_asm(itype, ltype, _ptr, _pold, _new, label) ({ \ ++ int __err = 0; \ ++ bool success; \ ++ __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold); \ ++ __typeof__(*(_ptr)) __old = *_old; \ ++ __typeof__(*(_ptr)) __new = (_new); \ ++ asm volatile("\n" \ ++ "1: " LOCK_PREFIX "cmpxchg"itype" %[new], %[ptr]\n"\ ++ CC_SET(z) \ ++ "2:\n" \ ++ _ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_EFAULT_REG, \ ++ %[errout]) \ ++ : CC_OUT(z) (success), \ ++ [errout] "+r" (__err), \ ++ [ptr] "+m" (*_ptr), \ ++ [old] "+a" (__old) \ ++ : [new] ltype (__new) \ ++ : "memory", "cc"); \ ++ if (unlikely(__err)) \ ++ goto label; \ ++ if (unlikely(!success)) \ ++ *_old = __old; \ ++ likely(success); }) ++ ++#ifdef CONFIG_X86_32 ++/* ++ * Unlike the normal CMPXCHG, hardcode ECX for both success/fail and error. ++ * There are only six GPRs available and four (EAX, EBX, ECX, and EDX) are ++ * hardcoded by CMPXCHG8B, leaving only ESI and EDI. If the compiler uses ++ * both ESI and EDI for the memory operand, compilation will fail if the error ++ * is an input+output as there will be no register available for input. ++ */ ++#define __try_cmpxchg64_user_asm(_ptr, _pold, _new, label) ({ \ ++ int __result; \ ++ __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold); \ ++ __typeof__(*(_ptr)) __old = *_old; \ ++ __typeof__(*(_ptr)) __new = (_new); \ ++ asm volatile("\n" \ ++ "1: " LOCK_PREFIX "cmpxchg8b %[ptr]\n" \ ++ "mov $0, %%ecx\n\t" \ ++ "setz %%cl\n" \ ++ "2:\n" \ ++ _ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_EFAULT_REG, %%ecx) \ ++ : [result]"=c" (__result), \ ++ "+A" (__old), \ ++ [ptr] "+m" (*_ptr) \ ++ : "b" ((u32)__new), \ ++ "c" ((u32)((u64)__new >> 32)) \ ++ : "memory", "cc"); \ ++ if (unlikely(__result < 0)) \ ++ goto label; \ ++ if (unlikely(!__result)) \ ++ *_old = __old; \ ++ likely(__result); }) ++#endif // CONFIG_X86_32 ++#endif // CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT ++ + /* FIXME: this hack is definitely wrong -AK */ + struct __large_struct { unsigned long buf[100]; }; + #define __m(x) (*(struct __large_struct __user *)(x)) +-- +2.35.1 + diff --git a/queue-5.15/xhci-dbc-create-and-remove-dbc-structure-in-dbgtty-d.patch b/queue-5.15/xhci-dbc-create-and-remove-dbc-structure-in-dbgtty-d.patch new file mode 100644 index 00000000000..459411ab1c7 --- /dev/null +++ b/queue-5.15/xhci-dbc-create-and-remove-dbc-structure-in-dbgtty-d.patch @@ -0,0 +1,165 @@ +From e91dffa8b81880565d0c625f19d16c7b5b261b77 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 16 Feb 2022 11:51:46 +0200 +Subject: xhci: dbc: create and remove dbc structure in dbgtty driver. + +From: Mathias Nyman + +[ 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 +Link: https://lore.kernel.org/r/20220216095153.1303105-3-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/host/xhci-dbgcap.c | 26 +++----------------------- + drivers/usb/host/xhci-dbgcap.h | 5 ++++- + drivers/usb/host/xhci-dbgtty.c | 22 +++++++++++++++------- + 3 files changed, 22 insertions(+), 31 deletions(-) + +diff --git a/drivers/usb/host/xhci-dbgcap.c b/drivers/usb/host/xhci-dbgcap.c +index 6a437862b498..f4da5708a40f 100644 +--- a/drivers/usb/host/xhci-dbgcap.c ++++ b/drivers/usb/host/xhci-dbgcap.c +@@ -914,16 +914,6 @@ static void xhci_dbc_handle_events(struct work_struct *work) + mod_delayed_work(system_wq, &dbc->event_work, 1); + } + +-static void xhci_do_dbc_exit(struct xhci_hcd *xhci) +-{ +- unsigned long flags; +- +- spin_lock_irqsave(&xhci->lock, flags); +- kfree(xhci->dbc); +- xhci->dbc = NULL; +- spin_unlock_irqrestore(&xhci->lock, flags); +-} +- + static ssize_t dbc_show(struct device *dev, + struct device_attribute *attr, + char *buf) +@@ -984,7 +974,7 @@ static ssize_t dbc_store(struct device *dev, + static DEVICE_ATTR_RW(dbc); + + struct xhci_dbc * +-xhci_alloc_dbc(struct device *dev, void __iomem *base) ++xhci_alloc_dbc(struct device *dev, void __iomem *base, const struct dbc_driver *driver) + { + struct xhci_dbc *dbc; + int ret; +@@ -995,6 +985,7 @@ xhci_alloc_dbc(struct device *dev, void __iomem *base) + + dbc->regs = base; + dbc->dev = dev; ++ dbc->driver = driver; + + if (readl(&dbc->regs->control) & DBC_CTRL_DBC_ENABLE) + return NULL; +@@ -1045,18 +1036,8 @@ int xhci_dbc_init(struct xhci_hcd *xhci) + if (xhci->dbc) + return -EBUSY; + +- xhci->dbc = xhci_alloc_dbc(dev, base); +- if (!xhci->dbc) +- return -ENOMEM; +- +- ret = xhci_dbc_tty_probe(xhci); +- if (ret) +- goto init_err2; +- +- return 0; ++ ret = xhci_dbc_tty_probe(dev, base + dbc_cap_offs, xhci); + +-init_err2: +- xhci_do_dbc_exit(xhci); + return ret; + } + +@@ -1068,7 +1049,6 @@ void xhci_dbc_exit(struct xhci_hcd *xhci) + return; + + xhci_dbc_tty_remove(xhci->dbc); +- xhci_dbc_remove(xhci->dbc); + spin_lock_irqsave(&xhci->lock, flags); + xhci->dbc = NULL; + spin_unlock_irqrestore(&xhci->lock, flags); +diff --git a/drivers/usb/host/xhci-dbgcap.h b/drivers/usb/host/xhci-dbgcap.h +index c70b78d504eb..5d8c7815491c 100644 +--- a/drivers/usb/host/xhci-dbgcap.h ++++ b/drivers/usb/host/xhci-dbgcap.h +@@ -196,8 +196,11 @@ static inline struct dbc_ep *get_out_ep(struct xhci_dbc *dbc) + #ifdef CONFIG_USB_XHCI_DBGCAP + int xhci_dbc_init(struct xhci_hcd *xhci); + void xhci_dbc_exit(struct xhci_hcd *xhci); +-int xhci_dbc_tty_probe(struct xhci_hcd *xhci); ++int xhci_dbc_tty_probe(struct device *dev, void __iomem *res, struct xhci_hcd *xhci); + void xhci_dbc_tty_remove(struct xhci_dbc *dbc); ++struct xhci_dbc *xhci_alloc_dbc(struct device *dev, void __iomem *res, ++ const struct dbc_driver *driver); ++void xhci_dbc_remove(struct xhci_dbc *dbc); + struct dbc_request *dbc_alloc_request(struct xhci_dbc *dbc, + unsigned int direction, + gfp_t flags); +diff --git a/drivers/usb/host/xhci-dbgtty.c b/drivers/usb/host/xhci-dbgtty.c +index eb46e642e87a..18bcc96853ae 100644 +--- a/drivers/usb/host/xhci-dbgtty.c ++++ b/drivers/usb/host/xhci-dbgtty.c +@@ -468,9 +468,9 @@ static const struct dbc_driver dbc_driver = { + .disconnect = xhci_dbc_tty_unregister_device, + }; + +-int xhci_dbc_tty_probe(struct xhci_hcd *xhci) ++int xhci_dbc_tty_probe(struct device *dev, void __iomem *base, struct xhci_hcd *xhci) + { +- struct xhci_dbc *dbc = xhci->dbc; ++ struct xhci_dbc *dbc; + struct dbc_port *port; + int status; + +@@ -485,13 +485,22 @@ int xhci_dbc_tty_probe(struct xhci_hcd *xhci) + goto out; + } + +- dbc->driver = &dbc_driver; +- dbc->priv = port; ++ dbc_tty_driver->driver_state = port; ++ ++ dbc = xhci_alloc_dbc(dev, base, &dbc_driver); ++ if (!dbc) { ++ status = -ENOMEM; ++ goto out2; ++ } + ++ dbc->priv = port; + +- dbc_tty_driver->driver_state = port; ++ /* get rid of xhci once this is a real driver binding to a device */ ++ xhci->dbc = dbc; + + return 0; ++out2: ++ kfree(port); + out: + /* dbc_tty_exit will be called by module_exit() in the future */ + dbc_tty_exit(); +@@ -506,8 +515,7 @@ void xhci_dbc_tty_remove(struct xhci_dbc *dbc) + { + struct dbc_port *port = dbc_to_port(dbc); + +- dbc->driver = NULL; +- dbc->priv = NULL; ++ xhci_dbc_remove(dbc); + kfree(port); + + /* dbc_tty_exit will be called by module_exit() in the future */ +-- +2.35.1 + diff --git a/queue-5.15/xhci-dbc-refactor-xhci_dbc_init.patch b/queue-5.15/xhci-dbc-refactor-xhci_dbc_init.patch new file mode 100644 index 00000000000..e4eeef10730 --- /dev/null +++ b/queue-5.15/xhci-dbc-refactor-xhci_dbc_init.patch @@ -0,0 +1,198 @@ +From 9d851a34f8198d8a3f57265da0c0dc7a31c6fff9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 16 Feb 2022 11:51:45 +0200 +Subject: xhci: dbc: refactor xhci_dbc_init() + +From: Mathias Nyman + +[ 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 +Link: https://lore.kernel.org/r/20220216095153.1303105-2-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/host/xhci-dbgcap.c | 124 ++++++++++++++++++--------------- + 1 file changed, 66 insertions(+), 58 deletions(-) + +diff --git a/drivers/usb/host/xhci-dbgcap.c b/drivers/usb/host/xhci-dbgcap.c +index ccb0156fcebe..6a437862b498 100644 +--- a/drivers/usb/host/xhci-dbgcap.c ++++ b/drivers/usb/host/xhci-dbgcap.c +@@ -924,49 +924,6 @@ static void xhci_do_dbc_exit(struct xhci_hcd *xhci) + spin_unlock_irqrestore(&xhci->lock, flags); + } + +-static int xhci_do_dbc_init(struct xhci_hcd *xhci) +-{ +- u32 reg; +- struct xhci_dbc *dbc; +- unsigned long flags; +- void __iomem *base; +- int dbc_cap_offs; +- +- base = &xhci->cap_regs->hc_capbase; +- dbc_cap_offs = xhci_find_next_ext_cap(base, 0, XHCI_EXT_CAPS_DEBUG); +- if (!dbc_cap_offs) +- return -ENODEV; +- +- dbc = kzalloc(sizeof(*dbc), GFP_KERNEL); +- if (!dbc) +- return -ENOMEM; +- +- dbc->regs = base + dbc_cap_offs; +- +- /* We will avoid using DbC in xhci driver if it's in use. */ +- reg = readl(&dbc->regs->control); +- if (reg & DBC_CTRL_DBC_ENABLE) { +- kfree(dbc); +- return -EBUSY; +- } +- +- spin_lock_irqsave(&xhci->lock, flags); +- if (xhci->dbc) { +- spin_unlock_irqrestore(&xhci->lock, flags); +- kfree(dbc); +- return -EBUSY; +- } +- xhci->dbc = dbc; +- spin_unlock_irqrestore(&xhci->lock, flags); +- +- dbc->xhci = xhci; +- dbc->dev = xhci_to_hcd(xhci)->self.sysdev; +- INIT_DELAYED_WORK(&dbc->event_work, xhci_dbc_handle_events); +- spin_lock_init(&dbc->lock); +- +- return 0; +-} +- + static ssize_t dbc_show(struct device *dev, + struct device_attribute *attr, + char *buf) +@@ -1026,44 +983,95 @@ static ssize_t dbc_store(struct device *dev, + + static DEVICE_ATTR_RW(dbc); + +-int xhci_dbc_init(struct xhci_hcd *xhci) ++struct xhci_dbc * ++xhci_alloc_dbc(struct device *dev, void __iomem *base) + { ++ struct xhci_dbc *dbc; + int ret; +- struct device *dev = xhci_to_hcd(xhci)->self.controller; + +- ret = xhci_do_dbc_init(xhci); ++ dbc = kzalloc(sizeof(*dbc), GFP_KERNEL); ++ if (!dbc) ++ return NULL; ++ ++ dbc->regs = base; ++ dbc->dev = dev; ++ ++ if (readl(&dbc->regs->control) & DBC_CTRL_DBC_ENABLE) ++ return NULL; ++ ++ INIT_DELAYED_WORK(&dbc->event_work, xhci_dbc_handle_events); ++ spin_lock_init(&dbc->lock); ++ ++ ret = device_create_file(dev, &dev_attr_dbc); + if (ret) +- goto init_err3; ++ goto err; ++ ++ return dbc; ++err: ++ kfree(dbc); ++ return NULL; ++} ++ ++/* undo what xhci_alloc_dbc() did */ ++void xhci_dbc_remove(struct xhci_dbc *dbc) ++{ ++ if (!dbc) ++ return; ++ /* stop hw, stop wq and call dbc->ops->stop() */ ++ xhci_dbc_stop(dbc); ++ ++ /* remove sysfs files */ ++ device_remove_file(dbc->dev, &dev_attr_dbc); ++ ++ kfree(dbc); ++} ++ ++int xhci_dbc_init(struct xhci_hcd *xhci) ++{ ++ struct device *dev; ++ void __iomem *base; ++ int ret; ++ int dbc_cap_offs; ++ ++ /* create all parameters needed resembling a dbc device */ ++ dev = xhci_to_hcd(xhci)->self.controller; ++ base = &xhci->cap_regs->hc_capbase; ++ ++ dbc_cap_offs = xhci_find_next_ext_cap(base, 0, XHCI_EXT_CAPS_DEBUG); ++ if (!dbc_cap_offs) ++ return -ENODEV; ++ ++ /* already allocated and in use */ ++ if (xhci->dbc) ++ return -EBUSY; ++ ++ xhci->dbc = xhci_alloc_dbc(dev, base); ++ if (!xhci->dbc) ++ return -ENOMEM; + + ret = xhci_dbc_tty_probe(xhci); + if (ret) + goto init_err2; + +- ret = device_create_file(dev, &dev_attr_dbc); +- if (ret) +- goto init_err1; +- + return 0; + +-init_err1: +- xhci_dbc_tty_remove(xhci->dbc); + init_err2: + xhci_do_dbc_exit(xhci); +-init_err3: + return ret; + } + + void xhci_dbc_exit(struct xhci_hcd *xhci) + { +- struct device *dev = xhci_to_hcd(xhci)->self.controller; ++ unsigned long flags; + + if (!xhci->dbc) + return; + +- device_remove_file(dev, &dev_attr_dbc); + xhci_dbc_tty_remove(xhci->dbc); +- xhci_dbc_stop(xhci->dbc); +- xhci_do_dbc_exit(xhci); ++ xhci_dbc_remove(xhci->dbc); ++ spin_lock_irqsave(&xhci->lock, flags); ++ xhci->dbc = NULL; ++ spin_unlock_irqrestore(&xhci->lock, flags); + } + + #ifdef CONFIG_PM +-- +2.35.1 + diff --git a/queue-5.15/xhci-dbc-rename-xhci_dbc_init-and-xhci_dbc_exit.patch b/queue-5.15/xhci-dbc-rename-xhci_dbc_init-and-xhci_dbc_exit.patch new file mode 100644 index 00000000000..94744db6c82 --- /dev/null +++ b/queue-5.15/xhci-dbc-rename-xhci_dbc_init-and-xhci_dbc_exit.patch @@ -0,0 +1,108 @@ +From 7e6f9e35f7ccec9eb7a80ffb557ca8fd030387ac Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 16 Feb 2022 11:51:47 +0200 +Subject: xhci: dbc: Rename xhci_dbc_init and xhci_dbc_exit + +From: Mathias Nyman + +[ 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 +Link: https://lore.kernel.org/r/20220216095153.1303105-4-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/host/xhci-dbgcap.c | 5 +++-- + drivers/usb/host/xhci-dbgcap.h | 8 ++++---- + drivers/usb/host/xhci.c | 4 ++-- + 3 files changed, 9 insertions(+), 8 deletions(-) + +diff --git a/drivers/usb/host/xhci-dbgcap.c b/drivers/usb/host/xhci-dbgcap.c +index f4da5708a40f..46c8f3c187f7 100644 +--- a/drivers/usb/host/xhci-dbgcap.c ++++ b/drivers/usb/host/xhci-dbgcap.c +@@ -1017,7 +1017,8 @@ void xhci_dbc_remove(struct xhci_dbc *dbc) + kfree(dbc); + } + +-int xhci_dbc_init(struct xhci_hcd *xhci) ++ ++int xhci_create_dbc_dev(struct xhci_hcd *xhci) + { + struct device *dev; + void __iomem *base; +@@ -1041,7 +1042,7 @@ int xhci_dbc_init(struct xhci_hcd *xhci) + return ret; + } + +-void xhci_dbc_exit(struct xhci_hcd *xhci) ++void xhci_remove_dbc_dev(struct xhci_hcd *xhci) + { + unsigned long flags; + +diff --git a/drivers/usb/host/xhci-dbgcap.h b/drivers/usb/host/xhci-dbgcap.h +index 5d8c7815491c..8b5b363a0719 100644 +--- a/drivers/usb/host/xhci-dbgcap.h ++++ b/drivers/usb/host/xhci-dbgcap.h +@@ -194,8 +194,8 @@ static inline struct dbc_ep *get_out_ep(struct xhci_dbc *dbc) + } + + #ifdef CONFIG_USB_XHCI_DBGCAP +-int xhci_dbc_init(struct xhci_hcd *xhci); +-void xhci_dbc_exit(struct xhci_hcd *xhci); ++int xhci_create_dbc_dev(struct xhci_hcd *xhci); ++void xhci_remove_dbc_dev(struct xhci_hcd *xhci); + int xhci_dbc_tty_probe(struct device *dev, void __iomem *res, struct xhci_hcd *xhci); + void xhci_dbc_tty_remove(struct xhci_dbc *dbc); + struct xhci_dbc *xhci_alloc_dbc(struct device *dev, void __iomem *res, +@@ -211,12 +211,12 @@ int xhci_dbc_suspend(struct xhci_hcd *xhci); + int xhci_dbc_resume(struct xhci_hcd *xhci); + #endif /* CONFIG_PM */ + #else +-static inline int xhci_dbc_init(struct xhci_hcd *xhci) ++static inline int xhci_create_dbc_dev(struct xhci_hcd *xhci) + { + return 0; + } + +-static inline void xhci_dbc_exit(struct xhci_hcd *xhci) ++static inline void xhci_remove_dbc_dev(struct xhci_hcd *xhci) + { + } + +diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c +index 94fe7d64e762..a4e99f8668b3 100644 +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -693,7 +693,7 @@ int xhci_run(struct usb_hcd *hcd) + xhci_dbg_trace(xhci, trace_xhci_dbg_init, + "Finished xhci_run for USB2 roothub"); + +- xhci_dbc_init(xhci); ++ xhci_create_dbc_dev(xhci); + + xhci_debugfs_init(xhci); + +@@ -723,7 +723,7 @@ static void xhci_stop(struct usb_hcd *hcd) + return; + } + +- xhci_dbc_exit(xhci); ++ xhci_remove_dbc_dev(xhci); + + spin_lock_irq(&xhci->lock); + xhci->xhc_state |= XHCI_STATE_HALTED; +-- +2.35.1 + diff --git a/queue-5.15/xhci-set-hcd-flag-to-defer-primary-roothub-registrat.patch b/queue-5.15/xhci-set-hcd-flag-to-defer-primary-roothub-registrat.patch new file mode 100644 index 00000000000..c42dbed9be2 --- /dev/null +++ b/queue-5.15/xhci-set-hcd-flag-to-defer-primary-roothub-registrat.patch @@ -0,0 +1,52 @@ +From 9769091a63aaae553b541d84f7759899c06977c5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 10 May 2022 14:46:30 +0530 +Subject: xhci: Set HCD flag to defer primary roothub registration + +From: Kishon Vijay Abraham I + +[ 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 +Tested-by: Chris Chiu +Signed-off-by: Kishon Vijay Abraham I +Link: https://lore.kernel.org/r/20220510091630.16564-3-kishon@ti.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 + -- 2.47.3