* [RFC PATCH v6 1/1] crypto: atmel-ecc - fix multi-device use-after-free and registration races
From: Lothar Rubusch @ 2026-06-09 9:29 UTC (permalink / raw)
To: thorsten.blum, herbert, davem, nicolas.ferre, alexandre.belloni,
claudiu.beznea, tudor.ambarus, krzk+dt
Cc: linux-crypto, linux-arm-kernel, linux-kernel, l.rubusch
During parallel driver initialization or driver teardown sequences
in setups with multiple atmel-ecc instances, a race condition exists
between atmel_ecc_i2c_client_alloc() and the probe/remove paths.
A concurrent transformation request can fetch an i2c_client instance
from the global i2c_client_list before the kpp is fully registered, or
while it is actively being unbound, resulting in a use-after-free (UAF)
risk.
1. The initialization problem in probe(): Adding first an i2c client to the
i2c_client_list, and then registering the kpp algorim may result in a race,
when this happens for a second (or further) probed device. In this case the
algorithm is already registered, so a TFM may arrive, while the latest
probing device is added to the list, but not kpp registered. In case this
fails and this last device is going to be removed again from the list, this
leaves a window where the TFM might obtain a pointer to the - now deleted -
i2c client, which opens a UAF risk. Furthermore, there will happen atempts
to multiple registering the same driver to the same type of algorithm.
Note, a simple reverting of the order: first register kpp, second add the
i2c client to the i2c_client_list - is not possible here, since the kpp
registration immediately triggers the self tests, which then will allocate
and require an i2c client.
2. The critical race condition problem: It exists when an Atmel device
instance is rapidly removed and immediately re-probed, before the global
resources are fully cleaned up. In this scenario, the asynchronous
unregistration sequence in the remove() lags behind the incoming probe()
function. Because of the global algorithm structure being not yet
completely cleaned up, the newly re-probed device incorrectly intercepts
the static, partially-dismantled global context. It then overwrites active
pointers and re-acquires the global instance prematurely. In this way, when
the deregistration sequence finally completes its execution, under the
newly initialized device, it may lose the tracking references, leaking the
older driver memory blocks, and introducing an immediate UAF risk.
3. The removal race problem, when a call to remove() starts removing the
device, but another thread executing a TFM, a severe Time-of-Check to
Time-of-Use (TOCTOU) race condition exists in the teardown path between the
asynchronous remove() sequence and completing TFMs. When the device is
unbound, the remove() function evaluates the active tfm_count and decides
whether to wait or proceed with resource deallocation. However, if the
final active TFM finishes its crypto operation and invokes the client free
function immediately after remove() performs its reference check but before
it can sleep, the completion signal is fired into a clearing state. The
unbind thread then misinterprets the zeroed counter, skips the
synchronization barrier entirely, and instantly deallocates the per-device
private structures. This leaves the final TFM worker thread executing code
inside a completely freed memory area, triggering an immediate UAF kernel
panic. Note, simply calling the kpp unregister here won't clean up the
situation in the context of having a setup with external hardware on a slow
bus.
Address this by implementing an independent subsystem reference counter
kpp refcnt protected by a dedicated mutex to ensure the static global kpp
algorithm structure is registered exactly once by the first probing device
instance. In multi-device scenarios, or when extending the resource
management support of the i2c_client_list to all atmel-i2c based device
drivers, such scenarios can become realistic. The particular algorithm is
registered only once. Each i2c client (i.e. each probing device driver) is
added as client to the i2c_client_list. This guarantee that only the first
probe will register the algorithm. The list is populated for further calls
to probe, and subsequent calls to the client alloc function.
Concurrently, decouple list mutations from registration by moving the
global list eviction to the absolute top of the remove lifecycle. This
keeps the quick execution of the list allocation loop intact, ensures that
unbinding hardware is instantly blind to the rest of the system, and
completely bypasses the recursive deadlock condition previously triggered
by synchronous crypto API self-tests.
Fixes: 11105693fa05 ("crypto: atmel-ecc - introduce Microchip / Atmel ECC driver")
Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
Assisted-by: Gemini:1.5-Pro [google]
---
RFC: feedback and probably architectural decision needed
The current atmel-ecc driver contains instabilities which should be fixed.
At least the situation with the i2c_client_list and the kpp registration.
Ideally we should have one algorithm registration, but one or multiple
device instances on the i2c list and ensure this to happen as originally
also designed by providing this i2c_client_list approach, which I highly
appreciate. The problematic remove() situation is another known topic here.
Probably more theoretically, but it was commented already before. As also
teardown synchronization might affect probe(), this is a round-trip to open
issues at the i2c list and kpp registration.
While my patch adresses and attempts to fix the above mentioned problems.
The following dilemma is popping up, getting flagged in both cases by
sashiko.
A) Applying unbound wait
Using wait_for_completion() assures waiting for all active TFMs to clear.
Nevertheless, it carries the risk of waiting infinitely.
B) Timed wait
Using wait_for_completion_timeout() avoids infinite waits. Nevertheless, it
introduces the risk of a UAF. In case of an aborting probe() or remove(),
any TFM in progress being cut off devres memory.
Questions:
1. First, please review the current state of the fixes elaborated with
sashiko feedbacks. Do you agree to the approach taken? Do you disagree and
why? Please, let me know what you think.
2. Initially I tried to separately only present a (kind of) fix to problem
1 (v1). Since everything seems to be somehow intertwined, I've put them
together, which increases complexity leading to a huge commit message.
Shall I split or shall I leave it together?
3. Do you see an alternative? If you agree, then which direction you would
like me to take here, A or B? The alternative, I can see here is, we also
could move away from `devm_` memory resources to active
allocation/deallocation in probe here to avoid the UAF.
v5 -> v6:
- RFC
- going back to using timeouts as in v4
- removing redundant code
v4 -> v5:
- sashiko warning: revert wait_for_completion_timeout() by
wait_for_completion() when former instance still active at probe()
- change return type of atmel_ecc_wait_for_tfms() to void
v3 -> v4:
- sashiko warning: replace wait_for_completion() by
wait_for_completion_timeout() in remove; decision is a kind of dilemma
- move redundant code of this fix out into a separate function
- make also use of the wait_for_completion_timeout() function at probe for
convenience
v2 -> v3:
- sashiko warning: fix missing init_completion() for remove_done
- add comment naming all three related main problem situations
v1 -> v2:
- remove the initial approach with "ready" state bool, replace it by
this be a more comprehensive approach
drivers/crypto/atmel-ecc.c | 134 +++++++++++++++++++++++++++++--------
drivers/crypto/atmel-i2c.h | 3 +
2 files changed, 108 insertions(+), 29 deletions(-)
diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c
index 0ca02995a1de..702d988a6547 100644
--- a/drivers/crypto/atmel-ecc.c
+++ b/drivers/crypto/atmel-ecc.c
@@ -23,6 +23,11 @@
#include <crypto/kpp.h>
#include "atmel-i2c.h"
+static DEFINE_MUTEX(atmel_ecc_kpp_lock);
+static int atmel_ecc_kpp_refcnt;
+DECLARE_COMPLETION(atmel_ecc_unreg_done);
+static bool atmel_ecc_unreg_active;
+
static struct atmel_ecc_driver_data driver_data;
/**
@@ -241,7 +246,10 @@ static void atmel_ecc_i2c_client_free(struct i2c_client *client)
{
struct atmel_i2c_client_priv *i2c_priv = i2c_get_clientdata(client);
- atomic_dec(&i2c_priv->tfm_count);
+ spin_lock(&driver_data.i2c_list_lock);
+ if (atomic_dec_and_test(&i2c_priv->tfm_count) && i2c_priv->unbinding)
+ complete(&i2c_priv->remove_done);
+ spin_unlock(&driver_data.i2c_list_lock);
}
static int atmel_ecdh_init_tfm(struct crypto_kpp *tfm)
@@ -276,7 +284,8 @@ static void atmel_ecdh_exit_tfm(struct crypto_kpp *tfm)
struct atmel_ecdh_ctx *ctx = kpp_tfm_ctx(tfm);
kfree(ctx->public_key);
- crypto_free_kpp(ctx->fallback);
+ if (ctx->fallback)
+ crypto_free_kpp(ctx->fallback);
atmel_ecc_i2c_client_free(ctx->client);
}
@@ -295,6 +304,26 @@ static unsigned int atmel_ecdh_max_size(struct crypto_kpp *tfm)
return ATMEL_ECC_PUBKEY_SIZE;
}
+static int atmel_ecc_wait_for_tfms(struct atmel_i2c_client_priv *i2c_priv,
+ unsigned long timeout)
+{
+ spin_lock(&driver_data.i2c_list_lock);
+ list_del(&i2c_priv->i2c_client_list_node);
+ i2c_priv->unbinding = true;
+ reinit_completion(&i2c_priv->remove_done);
+ if (!atomic_read(&i2c_priv->tfm_count)) {
+ spin_unlock(&driver_data.i2c_list_lock);
+ return 0;
+ }
+ spin_unlock(&driver_data.i2c_list_lock);
+
+ if (!wait_for_completion_timeout(&i2c_priv->remove_done,
+ msecs_to_jiffies(timeout)))
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
static struct kpp_alg atmel_ecdh_nist_p256 = {
.set_secret = atmel_ecdh_set_secret,
.generate_public_key = atmel_ecdh_generate_public_key,
@@ -315,6 +344,7 @@ static struct kpp_alg atmel_ecdh_nist_p256 = {
static int atmel_ecc_probe(struct i2c_client *client)
{
struct atmel_i2c_client_priv *i2c_priv;
+ unsigned long timeout;
int ret;
ret = atmel_i2c_probe(client);
@@ -323,49 +353,95 @@ static int atmel_ecc_probe(struct i2c_client *client)
i2c_priv = i2c_get_clientdata(client);
+ init_completion(&i2c_priv->remove_done);
+ i2c_priv->unbinding = false;
+
spin_lock(&driver_data.i2c_list_lock);
list_add_tail(&i2c_priv->i2c_client_list_node,
&driver_data.i2c_client_list);
spin_unlock(&driver_data.i2c_list_lock);
- ret = crypto_register_kpp(&atmel_ecdh_nist_p256);
- if (ret) {
- spin_lock(&driver_data.i2c_list_lock);
- list_del(&i2c_priv->i2c_client_list_node);
- spin_unlock(&driver_data.i2c_list_lock);
+ mutex_lock(&atmel_ecc_kpp_lock);
+ /*
+ * For cases where the same/last such device is still in unregistering,
+ * and now re-registering (refcnt is 0, but completion still exists).
+ * Safely capture the pointer, drop the lock and sleep until it
+ * terminates upon completion or retry limit reached.
+ */
+ while (atmel_ecc_unreg_active) {
+ mutex_unlock(&atmel_ecc_kpp_lock);
+ timeout = wait_for_completion_timeout(&atmel_ecc_unreg_done,
+ msecs_to_jiffies(2000));
+ mutex_lock(&atmel_ecc_kpp_lock);
+ if (timeout == 0) {
+ mutex_unlock(&atmel_ecc_kpp_lock);
+ /*
+ * FIXME / RFC: If we time out here, returning -ETIMEDOUT
+ * triggers devres cleanup, causing a UAF for any lagging TFMs.
+ * Should this be changed to an unbounded wait_for_completion()
+ * to prioritize memory safety over thread liveness?
+ */
+ if (atmel_ecc_wait_for_tfms(i2c_priv, 2000))
+ dev_emerg(&client->dev,
+ "Probe abort timed out! Active TFMs leaked, memory corruption imminent.\n");
+ else
+ dev_err(&client->dev,
+ "Probe timed out waiting for former instance unregistration\n");
+
+ return -ETIMEDOUT;
+ }
+ }
+ if (atmel_ecc_kpp_refcnt == 0) {
+ ret = crypto_register_kpp(&atmel_ecdh_nist_p256);
+ if (ret) {
+ mutex_unlock(&atmel_ecc_kpp_lock);
+
+ atmel_ecc_wait_for_tfms(i2c_priv, 2000);
+ dev_err(&client->dev,
+ "%s alg registration failed\n",
+ atmel_ecdh_nist_p256.base.cra_driver_name);
- dev_err(&client->dev, "%s alg registration failed\n",
- atmel_ecdh_nist_p256.base.cra_driver_name);
- } else {
- dev_info(&client->dev, "atmel ecc algorithms registered in /proc/crypto\n");
+ return ret;
+ }
}
+ atmel_ecc_kpp_refcnt++;
+ mutex_unlock(&atmel_ecc_kpp_lock);
+ dev_info(&client->dev, "atmel ecc algorithms registered in /proc/crypto\n");
return ret;
}
static void atmel_ecc_remove(struct i2c_client *client)
{
struct atmel_i2c_client_priv *i2c_priv = i2c_get_clientdata(client);
+ bool trigger_unreg = false;
- /* Return EBUSY if i2c client already allocated. */
- if (atomic_read(&i2c_priv->tfm_count)) {
- /*
- * After we return here, the memory backing the device is freed.
- * That happens no matter what the return value of this function
- * is because in the Linux device model there is no error
- * handling for unbinding a driver.
- * If there is still some action pending, it probably involves
- * accessing the freed memory.
- */
- dev_emerg(&client->dev, "Device is busy, expect memory corruption.\n");
- return;
+ /*
+ * FIXME / RFC: The timeout prevents a permanent hang,
+ * but since remove() returns void, devres will instantly
+ * free i2c_priv anyway. Memory corruption is imminent
+ * when the active TFM eventually closes.
+ */
+ if (atmel_ecc_wait_for_tfms(i2c_priv, 5000))
+ dev_emerg(&client->dev,
+ "Teardown timed out! Active TFMs leak, memory corruption imminent.\n");
+
+ mutex_lock(&atmel_ecc_kpp_lock);
+ atmel_ecc_kpp_refcnt--;
+ if (atmel_ecc_kpp_refcnt == 0) {
+ trigger_unreg = true;
+ atmel_ecc_unreg_active = true;
+ reinit_completion(&atmel_ecc_unreg_done);
+ }
+ mutex_unlock(&atmel_ecc_kpp_lock);
+
+ if (trigger_unreg) {
+ crypto_unregister_kpp(&atmel_ecdh_nist_p256);
+ mutex_lock(&atmel_ecc_kpp_lock);
+ atmel_ecc_unreg_active = false;
+ complete_all(&atmel_ecc_unreg_done);
+ mutex_unlock(&atmel_ecc_kpp_lock);
}
-
- crypto_unregister_kpp(&atmel_ecdh_nist_p256);
-
- spin_lock(&driver_data.i2c_list_lock);
- list_del(&i2c_priv->i2c_client_list_node);
- spin_unlock(&driver_data.i2c_list_lock);
}
static const struct of_device_id atmel_ecc_dt_ids[] = {
diff --git a/drivers/crypto/atmel-i2c.h b/drivers/crypto/atmel-i2c.h
index 72f04c15682f..8e6617422191 100644
--- a/drivers/crypto/atmel-i2c.h
+++ b/drivers/crypto/atmel-i2c.h
@@ -129,6 +129,7 @@ struct atmel_ecc_driver_data {
* @wake_token_sz : size in bytes of the wake_token
* @tfm_count : number of active crypto transformations on i2c client
* @hwrng : hold the hardware generated rng
+ * @unbinding : unbinding handshake
*
* Reads and writes from/to the i2c client are sequential. The first byte
* transmitted to the device is treated as the byte size. Any attempt to send
@@ -145,6 +146,8 @@ struct atmel_i2c_client_priv {
size_t wake_token_sz;
atomic_t tfm_count ____cacheline_aligned;
struct hwrng hwrng;
+ struct completion remove_done;
+ bool unbinding;
};
/**
base-commit: 79bbe453e5bfa6e1c6aa2e8329bfc8f152b81c9b
--
2.53.0
^ permalink raw reply related
* [PATCH RESEND v2 1/1] crypto: atmel-sha204a - fix heap info leak on I2C transfer failure
From: Lothar Rubusch @ 2026-06-09 9:47 UTC (permalink / raw)
To: thorsten.blum, herbert, davem, nicolas.ferre, alexandre.belloni,
claudiu.beznea, ardb, krzk+dt
Cc: linux-crypto, linux-arm-kernel, linux-kernel, l.rubusch
The nonblocking RNG path allocates a work_data structure to track the
state of an in-flight asynchronous I2C request. This pointer is stored
in rng->priv and later consumed by the read path once the transaction
completes.
If the underlying I2C transfer fails, the completion callback is invoked
with a non-zero status. In this case, the allocated work_data is not
usable for producing RNG output and must not remain associated with the
hwrng state.
Previously, the failure path only logged a warning but left the pointer
state uncleared, which can result in subsequent read attempts observing
stale state and interpreting it as valid completion data.
Fix this by freeing the pending work_data and clearing rng->priv when
the I2C transaction reports an error. This ensures that failed requests
do not leave residual state behind that could be interpreted as valid
RNG data on later reads.
The explicit clearing of rng->priv in the error path is retained as a
defensive measure. While it may overlap with existing state handling in the
read path, the ownership and lifecycle across asynchronous completion,
read, and teardown paths is not fully localised. Clearing the pointer
ensures no stale state remains after a failed transaction.
Fixes: da001fb651b0 ("crypto: atmel-i2c - add support for SHA204A random number generator")
Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
Assisted-by: Gemini:1.5 Pro [google]
Reviewed-by: Thorsten Blum <thorsten.blum@linux.dev>
---
drivers/crypto/atmel-sha204a.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c
index 4c9af737b33a..20cd915ea8a3 100644
--- a/drivers/crypto/atmel-sha204a.c
+++ b/drivers/crypto/atmel-sha204a.c
@@ -31,10 +31,15 @@ static void atmel_sha204a_rng_done(struct atmel_i2c_work_data *work_data,
struct atmel_i2c_client_priv *i2c_priv = work_data->ctx;
struct hwrng *rng = areq;
- if (status)
+ if (status) {
dev_warn_ratelimited(&i2c_priv->client->dev,
"i2c transaction failed (%d)\n",
status);
+ kfree(work_data);
+ rng->priv = 0;
+ atomic_dec(&i2c_priv->tfm_count);
+ return;
+ }
rng->priv = (unsigned long)work_data;
atomic_dec(&i2c_priv->tfm_count);
base-commit: 79bbe453e5bfa6e1c6aa2e8329bfc8f152b81c9b
--
2.53.0
^ permalink raw reply related
* [PATCH v2 1/2] crypto: atmel-i2c - improve comment in atmel_i2c_init_ecdh_cmd
From: Thorsten Blum @ 2026-06-09 10:05 UTC (permalink / raw)
To: Herbert Xu, David S. Miller, Nicolas Ferre, Alexandre Belloni,
Claudiu Beznea
Cc: Thorsten Blum, linux-crypto, linux-arm-kernel, linux-kernel
Clarify that a P-256 public key is encoded as two 32-byte coordinates.
Signed-off-by: Thorsten Blum <thorsten.blum@linux.dev>
---
No changes in patch 1/2.
---
drivers/crypto/atmel-i2c.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/crypto/atmel-i2c.c b/drivers/crypto/atmel-i2c.c
index ff19857894d0..24bded47a32b 100644
--- a/drivers/crypto/atmel-i2c.c
+++ b/drivers/crypto/atmel-i2c.c
@@ -138,9 +138,8 @@ int atmel_i2c_init_ecdh_cmd(struct atmel_i2c_cmd *cmd,
cmd->param2 = cpu_to_le16(DATA_SLOT_2);
/*
- * The device only supports NIST P256 ECC keys. The public key size will
- * always be the same. Use a macro for the key size to avoid unnecessary
- * computations.
+ * The device only supports P-256. Its public key is encoded as
+ * two 32-byte coordinates.
*/
copied = sg_copy_to_buffer(pubkey,
sg_nents_for_len(pubkey,
base-commit: 79bbe453e5bfa6e1c6aa2e8329bfc8f152b81c9b
^ permalink raw reply related
* [PATCH v2 2/2] crypto: atmel-ecc - clean up and improve ECDH comments
From: Thorsten Blum @ 2026-06-09 10:05 UTC (permalink / raw)
To: Thorsten Blum, Herbert Xu, David S. Miller, Nicolas Ferre,
Alexandre Belloni, Claudiu Beznea
Cc: linux-crypto, linux-arm-kernel, linux-kernel
In-Reply-To: <20260609100552.233494-3-thorsten.blum@linux.dev>
Improve the kerneldoc for struct atmel_ecdh_ctx by removing the stale
"unsupported curves" wording, since the device only supports a single
curve (P-256), and move the set_secret() constraint to the description.
In atmel_ecdh_set_secret(), clarify that the device generates the
private key, and drop the redundant "only supports NIST P256" comment.
In atmel_ecdh_done() and atmel_ecdh_generate_public_key(), clarify the
truncation comments. Also note that a P-256 public key consists of two
32-byte coordinates in atmel_ecdh_compute_shared_secret(), and remove
the unnecessary fall-through comment and other redundant comments.
Signed-off-by: Thorsten Blum <thorsten.blum@linux.dev>
---
Changes in v2:
- Adjust atmel_ecdh_ctx kerneldoc formatting/indentation according to:
https://www.kernel.org/doc/html/latest/doc-guide/kernel-doc.html#members
- v1: https://lore.kernel.org/r/20260603192708.1237715-4-thorsten.blum@linux.dev/
---
drivers/crypto/atmel-ecc.c | 38 ++++++++++++++------------------------
1 file changed, 14 insertions(+), 24 deletions(-)
diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c
index 0ca02995a1de..cd33d3f132cc 100644
--- a/drivers/crypto/atmel-ecc.c
+++ b/drivers/crypto/atmel-ecc.c
@@ -27,15 +27,14 @@ static struct atmel_ecc_driver_data driver_data;
/**
* struct atmel_ecdh_ctx - transformation context
- * @client : pointer to i2c client device
- * @fallback : used for unsupported curves or when user wants to use its own
- * private key.
- * @public_key : generated when calling set_secret(). It's the responsibility
- * of the user to not call set_secret() while
- * generate_public_key() or compute_shared_secret() are in flight.
- * @curve_id : elliptic curve id
- * @do_fallback: true when the device doesn't support the curve or when the user
- * wants to use its own private key.
+ * @client: I2C client device
+ * @fallback: ECDH fallback used for caller-provided private keys
+ * @public_key: cached public key for the device-generated private key
+ * @curve_id: elliptic curve id
+ * @do_fallback: true when ECDH operations should use @fallback
+ *
+ * The caller must not invoke set_secret() while generate_public_key()
+ * or compute_shared_secret() are in flight.
*/
struct atmel_ecdh_ctx {
struct i2c_client *client;
@@ -55,7 +54,7 @@ static void atmel_ecdh_done(struct atmel_i2c_work_data *work_data, void *areq,
if (status)
goto free_work_data;
- /* might want less than we've got */
+ /* copy only as much as requested, capped at 32 bytes */
n_sz = min(ATMEL_ECC_NIST_P256_N_SIZE, req->dst_len);
/* copy the shared secret */
@@ -64,15 +63,15 @@ static void atmel_ecdh_done(struct atmel_i2c_work_data *work_data, void *areq,
if (copied != n_sz)
status = -EINVAL;
- /* fall through */
free_work_data:
kfree_sensitive(work_data);
kpp_request_complete(req, status);
}
/*
- * A random private key is generated and stored in the device. The device
- * returns the pair public key.
+ * If no private key is provided, generate one in the device and cache
+ * the corresponding public key. The generated private key never leaves
+ * the device.
*/
static int atmel_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf,
unsigned int len)
@@ -83,9 +82,7 @@ static int atmel_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf,
struct ecdh params;
int ret = -ENOMEM;
- /* free the old public key, if any */
kfree(ctx->public_key);
- /* make sure you don't free the old public key twice */
ctx->public_key = NULL;
if (crypto_ecdh_decode_key(buf, len, ¶ms) < 0) {
@@ -94,7 +91,6 @@ static int atmel_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf,
}
if (params.key_size) {
- /* fallback to ecdh software implementation */
ctx->do_fallback = true;
return crypto_kpp_set_secret(ctx->fallback, buf, len);
}
@@ -103,11 +99,6 @@ static int atmel_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf,
if (!cmd)
return -ENOMEM;
- /*
- * The device only supports NIST P256 ECC keys. The public key size will
- * always be the same. Use a macro for the key size to avoid unnecessary
- * computations.
- */
public_key = kmalloc(ATMEL_ECC_PUBKEY_SIZE, GFP_KERNEL);
if (!public_key)
goto free_cmd;
@@ -120,7 +111,6 @@ static int atmel_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf,
if (ret)
goto free_public_key;
- /* save the public key */
memcpy(public_key, &cmd->data[RSP_DATA_IDX], ATMEL_ECC_PUBKEY_SIZE);
ctx->public_key = public_key;
@@ -149,7 +139,7 @@ static int atmel_ecdh_generate_public_key(struct kpp_request *req)
if (!ctx->public_key)
return -EINVAL;
- /* might want less than we've got */
+ /* copy only as much as requested, capped at 64 bytes */
nbytes = min(ATMEL_ECC_PUBKEY_SIZE, req->dst_len);
/* public key was saved at private key generation */
@@ -175,7 +165,7 @@ static int atmel_ecdh_compute_shared_secret(struct kpp_request *req)
return crypto_kpp_compute_shared_secret(req);
}
- /* must have exactly two points to be on the curve */
+ /* A P-256 public key must contain two 32-byte coordinates */
if (req->src_len != ATMEL_ECC_PUBKEY_SIZE)
return -EINVAL;
^ permalink raw reply related
* [PATCH v4 2/2] hwrng: starfive: rework clk/reset teardown order for JHB100
From: lianfeng.ouyang @ 2026-06-09 9:57 UTC (permalink / raw)
To: Olivia Mackall, Herbert Xu, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Philipp Zabel
Cc: linux-crypto, devicetree, linux-kernel, Lianfeng Ouyang
In-Reply-To: <20260609095726.160559-1-lianfeng.ouyang@starfivetech.com>
From: Lianfeng Ouyang <lianfeng.ouyang@starfivetech.com>
Rework the StarFive TRNG driver to address hardware-specific requirements
for JHB100 SoC. To avoid reset-domain crossing glitches, the driver now
ensures clocks are gated before asserting reset during teardown for
JHB100, while JH7110 retains the original reset-first sequence.
Fixes RPM handling by marking the device as RPM_ACTIVE after clocks and
reset are deasserted but before pm_runtime_enable(), allowing the usage
count to drop to zero and enabling autosuspend.
Balances pm_runtime_get/put calls in init, read, and cleanup paths,
and moves low-level disable/reset operations into a devm
action (starfive_trng_release()) for correct error-path unwind
ordering.
Improvements include proper mutex protection for TRNG command sequences,
enhanced clock enable error handling.
Signed-off-by: Lianfeng Ouyang <lianfeng.ouyang@starfivetech.com>
---
MAINTAINERS | 2 +-
drivers/char/hw_random/jh7110-trng.c | 223 +++++++++++++++++++++------
2 files changed, 176 insertions(+), 49 deletions(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index d3a6b3f6b6a0..729b20ecc697 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -25280,7 +25280,7 @@ F: Documentation/devicetree/bindings/perf/starfive,jh8100-starlink-pmu.yaml
F: drivers/perf/starfive_starlink_pmu.c
STARFIVE TRNG DRIVER
-M: Jia Jie Ho <jiajie.ho@starfivetech.com>
+M: Lianfeng Ouyang <lianfeng.ouyang@starfivetech.com>
S: Supported
F: Documentation/devicetree/bindings/rng/starfive*
F: drivers/char/hw_random/jh7110-trng.c
diff --git a/drivers/char/hw_random/jh7110-trng.c b/drivers/char/hw_random/jh7110-trng.c
index 9776f4daa044..cafc873b9ebf 100644
--- a/drivers/char/hw_random/jh7110-trng.c
+++ b/drivers/char/hw_random/jh7110-trng.c
@@ -92,20 +92,36 @@ enum mode {
PRNG_256BIT,
};
+/*
+ * For JHB100, assert reset after disabling clocks to avoid
+ * reset-domain crossing (RDC) induced glitches that can affect
+ * downstream IPs.
+ */
+enum seq_rst_clk {
+ SEQ_RST_FIRST,
+ SEQ_CLK_FIRST,
+};
+
+struct starfive_trng_data {
+ enum seq_rst_clk seq_rst_clk;
+};
+
struct starfive_trng {
- struct device *dev;
- void __iomem *base;
- struct clk *hclk;
- struct clk *ahb;
- struct reset_control *rst;
- struct hwrng rng;
- struct completion random_done;
- struct completion reseed_done;
- u32 mode;
- u32 mission;
- u32 reseed;
- /* protects against concurrent write to ctrl register */
- spinlock_t write_lock;
+ struct device *dev;
+ void __iomem *base;
+ int irq;
+ struct clk *hclk;
+ struct clk *ahb;
+ struct reset_control *rst;
+ struct hwrng rng;
+ struct completion random_done;
+ struct completion reseed_done;
+ const struct starfive_trng_data *data;
+ u32 mode;
+ u32 mission;
+ u32 reseed;
+ struct mutex lock; /* protect trng cmd seq */
+ spinlock_t write_lock; /* protects register access seq */
};
static u16 autoreq;
@@ -130,7 +146,7 @@ static inline int starfive_trng_wait_idle(struct starfive_trng *trng)
10, 100000);
}
-static inline void starfive_trng_irq_mask_clear(struct starfive_trng *trng)
+static inline void starfive_trng_irq_clear(struct starfive_trng *trng)
{
/* clear register: ISTAT */
u32 data = readl(trng->base + STARFIVE_ISTAT);
@@ -138,6 +154,31 @@ static inline void starfive_trng_irq_mask_clear(struct starfive_trng *trng)
writel(data, trng->base + STARFIVE_ISTAT);
}
+static void starfive_trng_release(void *data)
+{
+ struct starfive_trng *trng = data;
+
+ if (!pm_runtime_status_suspended(trng->dev)) {
+ writel(0, trng->base + STARFIVE_IE);
+ starfive_trng_irq_clear(trng);
+
+ if (trng->irq >= 0)
+ synchronize_irq(trng->irq);
+
+ if (trng->data->seq_rst_clk == SEQ_RST_FIRST)
+ reset_control_assert(trng->rst);
+
+ clk_disable_unprepare(trng->ahb);
+ clk_disable_unprepare(trng->hclk);
+
+ if (trng->data->seq_rst_clk == SEQ_CLK_FIRST)
+ reset_control_assert(trng->rst);
+ }
+
+ pm_runtime_dont_use_autosuspend(trng->dev);
+ pm_runtime_disable(trng->dev);
+}
+
static int starfive_trng_cmd(struct starfive_trng *trng, u32 cmd, bool wait)
{
int wait_time = 1000;
@@ -174,13 +215,22 @@ static int starfive_trng_init(struct hwrng *rng)
{
struct starfive_trng *trng = to_trng(rng);
u32 mode, intr = 0;
+ int ret;
+
+ ret = pm_runtime_resume_and_get(trng->dev);
+ if (ret < 0) {
+ dev_warn(trng->dev, "Failed to wake device for init: %d\n", ret);
+ return ret;
+ }
+
+ mutex_lock(&trng->lock);
/* setup Auto Request/Age register */
writel(autoage, trng->base + STARFIVE_AUTO_AGE);
writel(autoreq, trng->base + STARFIVE_AUTO_RQSTS);
/* clear register: ISTAT */
- starfive_trng_irq_mask_clear(trng);
+ starfive_trng_irq_clear(trng);
intr |= STARFIVE_IE_ALL;
writel(intr, trng->base + STARFIVE_IE);
@@ -201,24 +251,33 @@ static int starfive_trng_init(struct hwrng *rng)
writel(mode, trng->base + STARFIVE_MODE);
- return starfive_trng_cmd(trng, STARFIVE_CTRL_EXEC_RANDRESEED, 1);
+ ret = starfive_trng_cmd(trng, STARFIVE_CTRL_EXEC_RANDRESEED, 1);
+
+ mutex_unlock(&trng->lock);
+
+ pm_runtime_put_autosuspend(trng->dev);
+
+ return ret;
}
static irqreturn_t starfive_trng_irq(int irq, void *priv)
{
+ int ret;
u32 status;
struct starfive_trng *trng = (struct starfive_trng *)priv;
+ ret = pm_runtime_get_if_active(trng->dev);
+ if (ret <= 0) {
+ dev_err_ratelimited(trng->dev, "pm is inactive in irq\n");
+ return IRQ_NONE;
+ }
+
status = readl(trng->base + STARFIVE_ISTAT);
- if (status & STARFIVE_ISTAT_RAND_RDY) {
+ if (status & STARFIVE_ISTAT_RAND_RDY)
writel(STARFIVE_ISTAT_RAND_RDY, trng->base + STARFIVE_ISTAT);
- complete(&trng->random_done);
- }
- if (status & STARFIVE_ISTAT_SEED_DONE) {
+ if (status & STARFIVE_ISTAT_SEED_DONE)
writel(STARFIVE_ISTAT_SEED_DONE, trng->base + STARFIVE_ISTAT);
- complete(&trng->reseed_done);
- }
if (status & STARFIVE_ISTAT_LFSR_LOCKUP) {
writel(STARFIVE_ISTAT_LFSR_LOCKUP, trng->base + STARFIVE_ISTAT);
@@ -228,18 +287,37 @@ static irqreturn_t starfive_trng_irq(int irq, void *priv)
spin_unlock(&trng->write_lock);
}
+ if (status & STARFIVE_ISTAT_RAND_RDY)
+ complete(&trng->random_done);
+
+ if (status & STARFIVE_ISTAT_SEED_DONE)
+ complete(&trng->reseed_done);
+
+ pm_runtime_put_noidle(trng->dev);
+
return IRQ_HANDLED;
}
static void starfive_trng_cleanup(struct hwrng *rng)
{
struct starfive_trng *trng = to_trng(rng);
+ int ret;
+
+ ret = pm_runtime_resume_and_get(trng->dev);
+ if (ret < 0) {
+ dev_warn(trng->dev, "Failed to wake device for cleanup: %d\n", ret);
+ return;
+ }
+
+ writel(0, trng->base + STARFIVE_IE);
+ starfive_trng_irq_clear(trng);
+
+ if (trng->irq >= 0)
+ synchronize_irq(trng->irq);
writel(0, trng->base + STARFIVE_CTRL);
- reset_control_assert(trng->rst);
- clk_disable_unprepare(trng->hclk);
- clk_disable_unprepare(trng->ahb);
+ pm_runtime_put_sync(trng->dev);
}
static int starfive_trng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
@@ -247,7 +325,13 @@ static int starfive_trng_read(struct hwrng *rng, void *buf, size_t max, bool wai
struct starfive_trng *trng = to_trng(rng);
int ret;
- pm_runtime_get_sync(trng->dev);
+ ret = pm_runtime_resume_and_get(trng->dev);
+ if (ret < 0) {
+ dev_warn(trng->dev, "Failed to wake device for read: %d\n", ret);
+ return ret;
+ }
+
+ mutex_lock(&trng->lock);
if (trng->mode == PRNG_256BIT)
max = min_t(size_t, max, (STARFIVE_RAND_LEN * 8));
@@ -257,24 +341,28 @@ static int starfive_trng_read(struct hwrng *rng, void *buf, size_t max, bool wai
if (wait) {
ret = starfive_trng_wait_idle(trng);
if (ret)
- return -ETIMEDOUT;
+ goto end;
}
ret = starfive_trng_cmd(trng, STARFIVE_CTRL_GENE_RANDNUM, wait);
if (ret)
- return ret;
+ goto end;
memcpy_fromio(buf, trng->base + STARFIVE_RAND0, max);
- pm_runtime_put_sync_autosuspend(trng->dev);
+ ret = max;
+
+end:
+ mutex_unlock(&trng->lock);
- return max;
+ pm_runtime_put_autosuspend(trng->dev);
+
+ return ret;
}
static int starfive_trng_probe(struct platform_device *pdev)
{
int ret;
- int irq;
struct starfive_trng *trng;
trng = devm_kzalloc(&pdev->dev, sizeof(*trng), GFP_KERNEL);
@@ -282,22 +370,32 @@ static int starfive_trng_probe(struct platform_device *pdev)
return -ENOMEM;
platform_set_drvdata(pdev, trng);
+
trng->dev = &pdev->dev;
+ trng->data = of_device_get_match_data(&pdev->dev);
+ if (!trng->data)
+ return -EINVAL;
+
+ if (trng->data->seq_rst_clk != SEQ_RST_FIRST && trng->data->seq_rst_clk != SEQ_CLK_FIRST) {
+ dev_err(&pdev->dev, "Unknown seq_rst_clk value\n");
+ return -EINVAL;
+ }
trng->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(trng->base))
return dev_err_probe(&pdev->dev, PTR_ERR(trng->base),
"Error remapping memory for platform device.\n");
- irq = platform_get_irq(pdev, 0);
- if (irq < 0)
- return irq;
+ trng->irq = platform_get_irq(pdev, 0);
+ if (trng->irq < 0)
+ return trng->irq;
init_completion(&trng->random_done);
init_completion(&trng->reseed_done);
+ mutex_init(&trng->lock);
spin_lock_init(&trng->write_lock);
- ret = devm_request_irq(&pdev->dev, irq, starfive_trng_irq, 0, pdev->name,
+ ret = devm_request_irq(&pdev->dev, trng->irq, starfive_trng_irq, 0, pdev->name,
(void *)trng);
if (ret)
return dev_err_probe(&pdev->dev, ret,
@@ -318,8 +416,19 @@ static int starfive_trng_probe(struct platform_device *pdev)
return dev_err_probe(&pdev->dev, PTR_ERR(trng->rst),
"Error getting hardware reset line\n");
- clk_prepare_enable(trng->hclk);
- clk_prepare_enable(trng->ahb);
+ ret = clk_prepare_enable(trng->hclk);
+ if (ret) {
+ dev_err(&pdev->dev, "hclk clk_enable failed: %d\n", ret);
+ return ret;
+ }
+
+ ret = clk_prepare_enable(trng->ahb);
+ if (ret) {
+ clk_disable_unprepare(trng->hclk);
+ dev_err(&pdev->dev, "ahb clk_enable failed: %d\n", ret);
+ return ret;
+ }
+
reset_control_deassert(trng->rst);
trng->rng.name = dev_driver_string(&pdev->dev);
@@ -333,18 +442,16 @@ static int starfive_trng_probe(struct platform_device *pdev)
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, 100);
+ pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
- ret = devm_hwrng_register(&pdev->dev, &trng->rng);
- if (ret) {
- pm_runtime_disable(&pdev->dev);
-
- reset_control_assert(trng->rst);
- clk_disable_unprepare(trng->ahb);
- clk_disable_unprepare(trng->hclk);
+ ret = devm_add_action_or_reset(&pdev->dev, starfive_trng_release, trng);
+ if (ret)
+ return ret;
+ ret = devm_hwrng_register(&pdev->dev, &trng->rng);
+ if (ret)
return dev_err_probe(&pdev->dev, ret, "Failed to register hwrng\n");
- }
return 0;
}
@@ -361,10 +468,21 @@ static int __maybe_unused starfive_trng_suspend(struct device *dev)
static int __maybe_unused starfive_trng_resume(struct device *dev)
{
+ int ret;
struct starfive_trng *trng = dev_get_drvdata(dev);
- clk_prepare_enable(trng->hclk);
- clk_prepare_enable(trng->ahb);
+ ret = clk_prepare_enable(trng->hclk);
+ if (ret) {
+ dev_err(trng->dev, "hclk clk_enable failed: %d\n", ret);
+ return ret;
+ }
+
+ ret = clk_prepare_enable(trng->ahb);
+ if (ret) {
+ clk_disable_unprepare(trng->hclk);
+ dev_err(trng->dev, "ahb clk_enable failed: %d\n", ret);
+ return ret;
+ }
return 0;
}
@@ -376,8 +494,17 @@ static const struct dev_pm_ops starfive_trng_pm_ops = {
starfive_trng_resume, NULL)
};
+static const struct starfive_trng_data jh7110_data = {
+ .seq_rst_clk = SEQ_RST_FIRST,
+};
+
+static const struct starfive_trng_data jhb100_data = {
+ .seq_rst_clk = SEQ_CLK_FIRST,
+};
+
static const struct of_device_id trng_dt_ids[] __maybe_unused = {
- { .compatible = "starfive,jh7110-trng" },
+ { .compatible = "starfive,jh7110-trng", .data = &jh7110_data },
+ { .compatible = "starfive,jhb100-trng", .data = &jhb100_data },
{ }
};
MODULE_DEVICE_TABLE(of, trng_dt_ids);
--
2.43.0
^ permalink raw reply related
* [PATCH v4 1/2] dt-bindings: rng: starfive,jh7110-trng: add jhb100, drop jh8100
From: lianfeng.ouyang @ 2026-06-09 9:57 UTC (permalink / raw)
To: Olivia Mackall, Herbert Xu, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Philipp Zabel
Cc: linux-crypto, devicetree, linux-kernel, Lianfeng Ouyang
In-Reply-To: <20260609095726.160559-1-lianfeng.ouyang@starfivetech.com>
From: Lianfeng Ouyang <lianfeng.ouyang@starfivetech.com>
Update the StarFive TRNG DT bindings to reflect current SoC support.
The obsolete "starfive,jh8100-trng" compatible string is removed since
JH8100 SoC is no longer supported. A new "starfive,jhb100-trng"
compatible string is added for JHB100 SoC TRNG support.
The maintainer entry is also updated to reflect current ownership as the
previous maintainer has resigned.
Signed-off-by: Lianfeng Ouyang <lianfeng.ouyang@starfivetech.com>
---
.../devicetree/bindings/rng/starfive,jh7110-trng.yaml | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/Documentation/devicetree/bindings/rng/starfive,jh7110-trng.yaml b/Documentation/devicetree/bindings/rng/starfive,jh7110-trng.yaml
index 4639247e9e51..d21769b7d54e 100644
--- a/Documentation/devicetree/bindings/rng/starfive,jh7110-trng.yaml
+++ b/Documentation/devicetree/bindings/rng/starfive,jh7110-trng.yaml
@@ -7,15 +7,13 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: StarFive SoC TRNG Module
maintainers:
- - Jia Jie Ho <jiajie.ho@starfivetech.com>
+ - Lianfeng Ouyang <lianfeng.ouyang@starfivetech.com>
properties:
compatible:
- oneOf:
- - items:
- - const: starfive,jh8100-trng
- - const: starfive,jh7110-trng
- - const: starfive,jh7110-trng
+ enum:
+ - starfive,jh7110-trng
+ - starfive,jhb100-trng
reg:
maxItems: 1
--
2.43.0
^ permalink raw reply related
* [PATCH v4 0/2] hwrng: starfive: updates for jh7110-trng DT binding and rework clk/reset teardown
From: lianfeng.ouyang @ 2026-06-09 9:57 UTC (permalink / raw)
To: Olivia Mackall, Herbert Xu, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Philipp Zabel
Cc: linux-crypto, devicetree, linux-kernel, Lianfeng Ouyang
From: Lianfeng Ouyang <lianfeng.ouyang@starfivetech.com>
This patch series adds support for the JHB100 SoC TRNG and fixes
clock/reset teardown ordering issues.
The first patch updates the device tree bindings by removing the
obsolete JH8100 compatible string and adding JHB100 support
while updating the maintainer.
The second patch reworks the driver to ensure proper clock gating
before reset assertion for JHB100 to avoid reset-domain crossing
glitches, fixes RPM usage count handling, and improves error
path cleanup through devm actions.
Lianfeng Ouyang (2):
dt-bindings: rng: starfive,jh7110-trng: add jhb100, drop jh8100
hwrng: starfive: rework clk/reset teardown order for JHB100
.../bindings/rng/starfive,jh7110-trng.yaml | 10 +-
MAINTAINERS | 2 +-
drivers/char/hw_random/jh7110-trng.c | 223 ++++++++++++++----
3 files changed, 180 insertions(+), 55 deletions(-)
--
2.43.0
^ permalink raw reply
* Re: [PATCH v4] crypto/ccp: Introduce SNP_VERIFY_MITIGATION command
From: Tom Lendacky @ 2026-06-09 16:06 UTC (permalink / raw)
To: Pratik R. Sampat, ashish.kalra, john.allen, herbert, davem
Cc: linux-crypto, linux-kernel, aik, tycho, nikunj, michael.roth
In-Reply-To: <4957b07dbb4029a4c59bb3cf35f068c36284aa48.1780693665.git.prsampat@amd.com>
On 6/8/26 15:58, Pratik R. Sampat wrote:
> The SEV-SNP firmware provides the SNP_VERIFY_MITIGATION command, which
> can be used to query the status of currently supported vulnerability
> mitigations and to initiate mitigations within the firmware.
>
> This command is an explicit mechanism to ascertain if a firmware
> mitigation is applied without needing a full RMP re-build, which is most
> useful in a live firmware update scenario.
>
> The firmware supports two subcommands: STATUS and VERIFY. The STATUS
> subcommand is used to query the supported and verified mitigation bits.
> The VERIFY subcommand initiates the mitigation process within the FW for
> the specified vulnerability. Expose a userspace interface under:
> /sys/firmware/sev/vulnerabilities/
> - supported_mitigations (read-only): supported mitigation vector mask
> - verified_mitigations (read/write): current verified mask; write a
> vector to request VERIFY for that bit
>
> The behavior of SNP_VERIFY_MITIGATION and the pre-requisites for using
> it are bug-specific. Information about supported mitigations and its
> corresponding vector is to be published as part of the AMD Security
> Bulletin.
>
> See SEV-SNP Firmware ABI specifications 1.58, SNP_VERIFY_MITIGATION for
> more details.
>
> Signed-off-by: Pratik R. Sampat <prsampat@amd.com>
Just a few minor comments below, but in general...
Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
> ---
> v4:
> * Split interface definitions in documentation - Kernel Test Bot
> * Wrap snp_verify_mitigation() under #ifdef CONFIG_SYSFS - Tom
> * Remove check for snp initialized and feature info active for
> registering mitigigation interface - Tom
> * Since init vs init races should not be possible anymore[1], remove the
> sysfs mutex guard as sysfs' own synchornization suffices - Tom, Tycho
> * Dropping the reviewed-by since the patch has changed in a meaningful
> way
>
> v3: https://lore.kernel.org/linux-crypto/a043a82c-f3dd-4f29-86fb-60638eaddc9b@amd.com/
> * Remove failed_status interface and report failure via dev_err - Tycho
> * Make vulnerability interfaces root only accessible - Sashiko
> * Move /sys/firmware/vulnerabilities/ to
> /sys/firmware/sev/vulnerabilities/ to be platform specific - Sashiko
> * Guard sysfs creation under a new mutex to avoid racing during
> creation and using the sev_cmd_mutex which would race with
> vulnerability operations - Sashiko
>
> v2: https://lore.kernel.org/linux-crypto/20260501152051.17469-1-prsampat@amd.com/
> * Intrdouce /sys/firmware/vulnerabilities sysfs interface instead of
> an ioctl interface - Boris
> * Reword commit message to focus on need for a userspace interface - Sean
> * Since download_firmware_ex is the primary usecase of this feature,
> posting this patch in parallel to those discussions[2].
> RFC: https://lore.kernel.org/linux-crypto/20250630202319.56331-1-prsampat@amd.com/
>
> [1]: https://lore.kernel.org/all/20260504165147.1615643-5-tycho@kernel.org/
> [2]: https://lore.kernel.org/linux-crypto/20260430160716.1120553-1-tycho@kernel.org/
>
> Patch based on cryptodev-2.6
> ---
> .../sysfs-firmware-sev-vulnerabilities | 19 ++
> drivers/crypto/ccp/sev-dev.c | 171 ++++++++++++++++++
> drivers/crypto/ccp/sev-dev.h | 3 +
> include/linux/psp-sev.h | 51 ++++++
> 4 files changed, 244 insertions(+)
> create mode 100644 Documentation/ABI/testing/sysfs-firmware-sev-vulnerabilities
>
> diff --git a/Documentation/ABI/testing/sysfs-firmware-sev-vulnerabilities b/Documentation/ABI/testing/sysfs-firmware-sev-vulnerabilities
> new file mode 100644
> index 000000000000..964362558bb2
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-firmware-sev-vulnerabilities
> @@ -0,0 +1,19 @@
> +What: /sys/firmware/sev/vulnerabilities/supported_mitigations
> +Date: June 2026
> +Contact: linux-crypto@vger.kernel.org
> +Description:
> + Read-only interface that reports the vector of SEV-SNP
> + firmware vulnerability mitigations supported by the firmware.
> +
> +What: /sys/firmware/sev/vulnerabilities/verified_mitigations
> +Date: June 2026
> +Contact: linux-crypto@vger.kernel.org
> +Description:
> + Read/write interface that reports the vector of SEV-SNP
> + firmware vulnerability mitigations already verified by the
> + firmware. Writing a vector value requests the firmware to
> + VERIFY the corresponding mitigation bit(s).
> +
> + The list of supported mitigations and the meaning of each
> + vector bit are both platform- and bug-specific and are
> + published as part of the AMD Security Bulletin.
> diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c
> index 068b901034cb..251cc7540f51 100644
> --- a/drivers/crypto/ccp/sev-dev.c
> +++ b/drivers/crypto/ccp/sev-dev.c
> @@ -245,6 +245,7 @@ static int sev_cmd_buffer_len(int cmd)
> case SEV_CMD_SNP_LAUNCH_FINISH: return sizeof(struct sev_data_snp_launch_finish);
> case SEV_CMD_SNP_DBG_DECRYPT: return sizeof(struct sev_data_snp_dbg);
> case SEV_CMD_SNP_DBG_ENCRYPT: return sizeof(struct sev_data_snp_dbg);
> + case SEV_CMD_SNP_VERIFY_MITIGATION: return sizeof(struct sev_data_snp_verify_mitigation);
> case SEV_CMD_SNP_PAGE_UNSMASH: return sizeof(struct sev_data_snp_page_unsmash);
> case SEV_CMD_SNP_PLATFORM_STATUS: return sizeof(struct sev_data_snp_addr);
> case SEV_CMD_SNP_GUEST_REQUEST: return sizeof(struct sev_data_snp_guest_request);
> @@ -1352,6 +1353,156 @@ static int snp_filter_reserved_mem_regions(struct resource *rs, void *arg)
> return 0;
> }
>
> +#ifdef CONFIG_SYSFS
> +static int snp_verify_mitigation(u16 command, u64 vector,
> + struct sev_data_snp_verify_mitigation_dst *dst)
> +{
> + struct sev_data_snp_verify_mitigation_dst *mit_dst = NULL;
> + struct sev_data_snp_verify_mitigation data = {0};
> + struct sev_device *sev = psp_master->sev_data;
> + int ret, error = 0;
> +
> + mit_dst = snp_alloc_firmware_page(GFP_KERNEL | __GFP_ZERO);
> + if (!mit_dst)
> + return -ENOMEM;
> +
> + data.length = sizeof(data);
> + data.subcommand = command;
> + data.vector = vector;
> + data.dst_paddr = __psp_pa(mit_dst);
> + data.dst_paddr_en = true;
> +
> + ret = sev_do_cmd(SEV_CMD_SNP_VERIFY_MITIGATION, &data, &error);
> + if (!ret)
> + memcpy(dst, mit_dst, sizeof(*mit_dst));
> + else
> + dev_err(sev->dev, "SNP_VERIFY_MITIGATION command failed, ret = %d, error = %#x\n",
> + ret, error);
> +
> + snp_free_firmware_page(mit_dst);
> +
> + return ret;
> +}
> +
> +static ssize_t supported_mitigations_show(struct kobject *kobj,
> + struct kobj_attribute *attr, char *buf)
> +{
> + struct sev_data_snp_verify_mitigation_dst dst;
> + int ret;
> +
> + ret = snp_verify_mitigation(SNP_MIT_SUBCMD_REQ_STATUS, 0, &dst);
> + if (ret)
> + return ret;
> +
> + return sysfs_emit(buf, "0x%llx\n", dst.mit_supported_vector);
> +}
> +
> +static struct kobj_attribute supported_attr =
> + __ATTR_RO_MODE(supported_mitigations, 0400);
> +
> +static ssize_t verified_mitigations_show(struct kobject *kobj,
> + struct kobj_attribute *attr, char *buf)
> +{
> + struct sev_data_snp_verify_mitigation_dst dst;
> + int ret;
> +
> + ret = snp_verify_mitigation(SNP_MIT_SUBCMD_REQ_STATUS, 0, &dst);
> + if (ret)
> + return ret;
> +
> + return sysfs_emit(buf, "0x%llx\n", dst.mit_verified_vector);
> +}
> +
> +static ssize_t verified_mitigations_store(struct kobject *kobj,
> + struct kobj_attribute *attr,
> + const char *buf, size_t count)
> +{
> + struct sev_data_snp_verify_mitigation_dst dst;
> + struct sev_device *sev = psp_master->sev_data;
> + u64 vector;
> + int ret;
> +
> + ret = kstrtoull(buf, 0, &vector);
> + if (ret)
> + return ret;
Should we save some time and check for vector having multiple bits set
before sending it to the firmware?
> +
> + ret = snp_verify_mitigation(SNP_MIT_SUBCMD_REQ_VERIFY, vector, &dst);
> + if (ret)
> + return ret;
> +
> + if (dst.mit_failure_status) {
> + dev_err(sev->dev, "Verify Mitigation - failure status: 0x%x\n",
> + dst.mit_failure_status);
> + return -EIO;
> + }
> +
> + return count;
> +}
> +
> +static struct kobj_attribute verified_attr =
> + __ATTR_RW_MODE(verified_mitigations, 0600);
> +
> +static struct attribute *mitigation_attrs[] = {
> + &supported_attr.attr,
> + &verified_attr.attr,
> + NULL
> +};
> +
> +static const struct attribute_group mit_attr_group = {
> + .attrs = mitigation_attrs,
> +};
> +
> +static void sev_snp_register_verify_mitigation(struct sev_device *sev)
> +{
> + int rc;
> +
> + if (!(sev->snp_feat_info_0.ecx & SNP_VERIFY_MITIGATION_SUPPORTED) ||
> + sev->verify_mit)
> + return;
> +
> + if (!sev->sev_kobj) {
> + sev->sev_kobj = kobject_create_and_add("sev", firmware_kobj);
> + if (!sev->sev_kobj)
> + return;
> + }
> +
> + sev->verify_mit = kobject_create_and_add("vulnerabilities", sev->sev_kobj);
> + if (!sev->verify_mit)
> + goto err_sev_kobj;
> +
> + rc = sysfs_create_group(sev->verify_mit, &mit_attr_group);
> + if (rc)
> + goto err_verify_mit;
> +
> + return;
> +
> +err_verify_mit:
> + kobject_put(sev->verify_mit);
> + sev->verify_mit = NULL;
> +err_sev_kobj:
> + kobject_put(sev->sev_kobj);
> + sev->sev_kobj = NULL;
> +
Extra blank line.
> +}
> +
> +static void sev_snp_unregister_verify_mitigation(struct sev_device *sev)
> +{
> + if (sev->verify_mit) {
> + sysfs_remove_group(sev->verify_mit, &mit_attr_group);
> + kobject_put(sev->verify_mit);
> + sev->verify_mit = NULL;
> + }
> +
> + if (sev->sev_kobj) {
> + kobject_put(sev->sev_kobj);
> + sev->sev_kobj = NULL;
> + }
> +}
> +#else
Just add the CONFIG option to the else and endif, e.g.:
#else // CONFIG_SYSFS
...
#endif // CONFIG_SYSFS
> +static void sev_snp_register_verify_mitigation(struct sev_device *sev) { }
> +static void sev_snp_unregister_verify_mitigation(struct sev_device *sev) { }
> +#endif
> +
> static int __sev_snp_init_locked(int *error, unsigned int max_snp_asid)
> {
> struct sev_data_range_list *snp_range_list __free(kfree) = NULL;
> @@ -1673,6 +1824,17 @@ int sev_platform_init(struct sev_platform_init_args *args)
> rc = _sev_platform_init_locked(args);
> mutex_unlock(&sev_cmd_mutex);
>
> + /*
> + * Register the sysfs interface outside the sev_cmd_mutex. The
> + * _show()/_store() handlers issue SEV commands that acquire the
> + * sev_cmd_mutex, so creating (and on the shutdown path, removing) the
> + * sysfs group must stay outside that lock. sysfs provides its own
> + * synchronization between group creation/removal and concurrent
> + * attribute access.
> + */
> + if (!rc)
> + sev_snp_register_verify_mitigation(psp_master->sev_data);
> +
> return rc;
> }
> EXPORT_SYMBOL_GPL(sev_platform_init);
> @@ -2752,6 +2914,15 @@ static void sev_firmware_shutdown(struct sev_device *sev)
> if (sev->tio_status)
> sev_tsm_uninit(sev);
>
> + /*
> + * Remove the sysfs interface before taking the sev_cmd_mutex.
> + * sysfs_remove_group() waits for in-flight _show()/_store() handlers
> + * to drain, and those handlers issue SNP_VERIFY_MITIGATION via
> + * sev_do_cmd() which acquires the sev_cmd_mutex. Removing the group
> + * while holding the mutex would therefore deadlock.
s/would/could/
Thanks,
Tom
> + */
> + sev_snp_unregister_verify_mitigation(sev);
> +
> mutex_lock(&sev_cmd_mutex);
>
> __sev_firmware_shutdown(sev, false);
> diff --git a/drivers/crypto/ccp/sev-dev.h b/drivers/crypto/ccp/sev-dev.h
> index b1cd556bbbf6..d5e596606def 100644
> --- a/drivers/crypto/ccp/sev-dev.h
> +++ b/drivers/crypto/ccp/sev-dev.h
> @@ -59,6 +59,9 @@ struct sev_device {
>
> bool snp_initialized;
>
> + struct kobject *sev_kobj;
> + struct kobject *verify_mit;
> +
> struct sev_user_data_status sev_plat_status;
>
> struct sev_user_data_snp_status snp_plat_status;
> diff --git a/include/linux/psp-sev.h b/include/linux/psp-sev.h
> index d5099a2baca5..98666c5a6f79 100644
> --- a/include/linux/psp-sev.h
> +++ b/include/linux/psp-sev.h
> @@ -129,6 +129,7 @@ enum sev_cmd {
> SEV_CMD_SNP_LAUNCH_FINISH = 0x0A2,
> SEV_CMD_SNP_DBG_DECRYPT = 0x0B0,
> SEV_CMD_SNP_DBG_ENCRYPT = 0x0B1,
> + SEV_CMD_SNP_VERIFY_MITIGATION = 0x0B2,
> SEV_CMD_SNP_PAGE_SWAP_OUT = 0x0C0,
> SEV_CMD_SNP_PAGE_SWAP_IN = 0x0C1,
> SEV_CMD_SNP_PAGE_MOVE = 0x0C2,
> @@ -898,10 +899,60 @@ struct snp_feature_info {
> #define SNP_CIPHER_TEXT_HIDING_SUPPORTED BIT(3)
> #define SNP_AES_256_XTS_POLICY_SUPPORTED BIT(4)
> #define SNP_CXL_ALLOW_POLICY_SUPPORTED BIT(5)
> +#define SNP_VERIFY_MITIGATION_SUPPORTED BIT(13)
>
> /* Feature bits in EBX */
> #define SNP_SEV_TIO_SUPPORTED BIT(1)
>
> +#define SNP_MIT_SUBCMD_REQ_STATUS 0x0
> +#define SNP_MIT_SUBCMD_REQ_VERIFY 0x1
> +
> +/**
> + * struct sev_data_snp_verify_mitigation - SNP_VERIFY_MITIGATION command params
> + *
> + * @length: Length of the command buffer read by the PSP
> + * @subcommand: Mitigation sub-command for the firmware to execute.
> + * REQ_STATUS: 0x0 - Request status about currently supported and
> + * verified mitigations
> + * REQ_VERIFY: 0x1 - Request to initiate verification mitigation
> + * operation on a specific mitigation
> + * @rsvd: Reserved
> + * @vector: Bit specifying the vulnerability mitigation to process
> + * @dst_paddr_en: Destination paddr enabled
> + * @src_paddr_en: Source paddr enabled
> + * @rsvd1: Reserved
> + * @rsvd2: Reserved
> + * @src_paddr: Source address for optional input data
> + * @dst_paddr: Destination address to write the result
> + * @rsvd3: Reserved
> + */
> +struct sev_data_snp_verify_mitigation {
> + u32 length;
> + u16 subcommand;
> + u16 rsvd;
> + u64 vector;
> + u32 dst_paddr_en : 1,
> + src_paddr_en : 1,
> + rsvd1 : 30;
> + u8 rsvd2[4];
> + u64 src_paddr;
> + u64 dst_paddr;
> + u8 rsvd3[24];
> +} __packed;
> +
> +/**
> + * struct sev_data_snp_verify_mitigation_dst - mitigation result vectors
> + *
> + * @mit_verified_vector: Bit vector of vulnerability mitigations verified
> + * @mit_supported_vector: Bit vector of vulnerability mitigations supported
> + * @mit_failure_status: Status of the verification operation
> + */
> +struct sev_data_snp_verify_mitigation_dst {
> + u64 mit_verified_vector; /* OUT */
> + u64 mit_supported_vector; /* OUT */
> + u32 mit_failure_status; /* OUT */
> +} __packed;
> +
> #ifdef CONFIG_CRYPTO_DEV_SP_PSP
>
> /**
^ permalink raw reply
* Re: [PATCH net-next v2 0/5] Consolidate FCrypt and PCBC code into net/rxrpc/
From: Paolo Abeni @ 2026-06-09 16:11 UTC (permalink / raw)
To: David Howells, Herbert Xu
Cc: Marc Dionne, netdev, linux-afs, linux-crypto, linux-kernel,
David S . Miller, Eric Dumazet, Jakub Kicinski, Simon Horman,
Eric Biggers
In-Reply-To: <764077.1780985938@warthog.procyon.org.uk>
Hi,
On 6/9/26 8:18 AM, David Howells wrote:
> Eric Biggers <ebiggers@kernel.org> wrote:
>
>>> If there's no more feedback, could this be applied to net-next?
>>
>> Any update on this?
>
> It's fine by me, but I'm not sure what I need to do with it - shouldn't it
> already be in the netdev queue, or do I need to post it?
This slipped under my radar, sorry. I just revived it in PW. Also, I
think we need an explicit ack from Herbert.
Link to ML post:
https://lore.kernel.org/all/20260522050740.84561-1-ebiggers@kernel.org/
Thanks,
Paolo
^ permalink raw reply
* Re: [PATCH v4 1/2] dt-bindings: rng: starfive,jh7110-trng: add jhb100, drop jh8100
From: Conor Dooley @ 2026-06-09 16:13 UTC (permalink / raw)
To: lianfeng.ouyang
Cc: Olivia Mackall, Herbert Xu, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Philipp Zabel, linux-crypto, devicetree,
linux-kernel
In-Reply-To: <20260609095726.160559-2-lianfeng.ouyang@starfivetech.com>
[-- Attachment #1: Type: text/plain, Size: 75 bytes --]
Acked-by: Conor Dooley <conor.dooley@microchip.com>
pw-bot: not-applicable
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH v4] crypto/ccp: Introduce SNP_VERIFY_MITIGATION command
From: Pratik R. Sampat @ 2026-06-09 16:19 UTC (permalink / raw)
To: Tom Lendacky, ashish.kalra, john.allen, herbert, davem
Cc: linux-crypto, linux-kernel, aik, tycho, nikunj, michael.roth
In-Reply-To: <c00d4186-2a89-4c24-be02-6b6a05450fe5@amd.com>
On 6/9/26 12:06 PM, Tom Lendacky wrote:
> On 6/8/26 15:58, Pratik R. Sampat wrote:
>> The SEV-SNP firmware provides the SNP_VERIFY_MITIGATION command, which
>> can be used to query the status of currently supported vulnerability
>> mitigations and to initiate mitigations within the firmware.
>>
>> This command is an explicit mechanism to ascertain if a firmware
>> mitigation is applied without needing a full RMP re-build, which is most
>> useful in a live firmware update scenario.
>>
>> The firmware supports two subcommands: STATUS and VERIFY. The STATUS
>> subcommand is used to query the supported and verified mitigation bits.
>> The VERIFY subcommand initiates the mitigation process within the FW for
>> the specified vulnerability. Expose a userspace interface under:
>> /sys/firmware/sev/vulnerabilities/
>> - supported_mitigations (read-only): supported mitigation vector mask
>> - verified_mitigations (read/write): current verified mask; write a
>> vector to request VERIFY for that bit
>>
>> The behavior of SNP_VERIFY_MITIGATION and the pre-requisites for using
>> it are bug-specific. Information about supported mitigations and its
>> corresponding vector is to be published as part of the AMD Security
>> Bulletin.
>>
>> See SEV-SNP Firmware ABI specifications 1.58, SNP_VERIFY_MITIGATION for
>> more details.
>>
>> Signed-off-by: Pratik R. Sampat <prsampat@amd.com>
>
> Just a few minor comments below, but in general...
>
> Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
>
>> +static ssize_t verified_mitigations_store(struct kobject *kobj,
>> + struct kobj_attribute *attr,
>> + const char *buf, size_t count)
>> +{
>> + struct sev_data_snp_verify_mitigation_dst dst;
>> + struct sev_device *sev = psp_master->sev_data;
>> + u64 vector;
>> + int ret;
>> +
>> + ret = kstrtoull(buf, 0, &vector);
>> + if (ret)
>> + return ret;
>
> Should we save some time and check for vector having multiple bits set
> before sending it to the firmware?
>
Sure. This can be a quick sanity check and can save a FW call.
>> +err_verify_mit:
>> + kobject_put(sev->verify_mit);
>> + sev->verify_mit = NULL;
>> +err_sev_kobj:
>> + kobject_put(sev->sev_kobj);
>> + sev->sev_kobj = NULL;
>> +
>
> Extra blank line.
>
Ack.
>> +}
>> +
>> +static void sev_snp_unregister_verify_mitigation(struct sev_device *sev)
>> +{
>> + if (sev->verify_mit) {
>> + sysfs_remove_group(sev->verify_mit, &mit_attr_group);
>> + kobject_put(sev->verify_mit);
>> + sev->verify_mit = NULL;
>> + }
>> +
>> + if (sev->sev_kobj) {
>> + kobject_put(sev->sev_kobj);
>> + sev->sev_kobj = NULL;
>> + }
>> +}
>> +#else
>
> Just add the CONFIG option to the else and endif, e.g.:
>
> #else // CONFIG_SYSFS
>
> ...
>
> #endif // CONFIG_SYSFS
>
Ack.
>> +static void sev_snp_register_verify_mitigation(struct sev_device *sev) { }
>> +static void sev_snp_unregister_verify_mitigation(struct sev_device *sev) { }
>> +#endif
>> +
>> static int __sev_snp_init_locked(int *error, unsigned int max_snp_asid)
>> {
>> struct sev_data_range_list *snp_range_list __free(kfree) = NULL;
>> @@ -1673,6 +1824,17 @@ int sev_platform_init(struct sev_platform_init_args *args)
>> rc = _sev_platform_init_locked(args);
>> mutex_unlock(&sev_cmd_mutex);
>>
>> + /*
>> + * Register the sysfs interface outside the sev_cmd_mutex. The
>> + * _show()/_store() handlers issue SEV commands that acquire the
>> + * sev_cmd_mutex, so creating (and on the shutdown path, removing) the
>> + * sysfs group must stay outside that lock. sysfs provides its own
>> + * synchronization between group creation/removal and concurrent
>> + * attribute access.
>> + */
>> + if (!rc)
>> + sev_snp_register_verify_mitigation(psp_master->sev_data);
>> +
>> return rc;
>> }
>> EXPORT_SYMBOL_GPL(sev_platform_init);
>> @@ -2752,6 +2914,15 @@ static void sev_firmware_shutdown(struct sev_device *sev)
>> if (sev->tio_status)
>> sev_tsm_uninit(sev);
>>
>> + /*
>> + * Remove the sysfs interface before taking the sev_cmd_mutex.
>> + * sysfs_remove_group() waits for in-flight _show()/_store() handlers
>> + * to drain, and those handlers issue SNP_VERIFY_MITIGATION via
>> + * sev_do_cmd() which acquires the sev_cmd_mutex. Removing the group
>> + * while holding the mutex would therefore deadlock.
>
> s/would/could/
>
Will do and re-spin, thanks!
--Pratik
^ permalink raw reply
* Re: [PATCH] crypto: ecc - Optimize vli additive operations using compiler builtins
From: Stefan Berger @ 2026-06-09 18:58 UTC (permalink / raw)
To: Fabian Blatter, lukas, ignat, herbert, davem; +Cc: linux-crypto, linux-kernel
In-Reply-To: <20260607112435.42804-1-fabianblatter09@gmail.com>
On 6/7/26 7:24 AM, Fabian Blatter wrote:
> Replace the software carry flag emulation with compiler builtins.
>
> Even the newest compilers struggle with taking advantage of the
> hardware carry flag. Compiler builtins allow the compiler to
> much more easily achieve this while still remaining constant-time.
It looks like you made vli_usub and vli_uadd constant-time now because
otherwise the loops could be ended early once borrow == 0 or carry == 0
respectively. Are all the other functions that operate on the private
keys constant-time?
^ permalink raw reply
* Re: [RFC] ML-KEM (FIPS 203) implementation with reusable decapsulation pool
From: Eric Biggers @ 2026-06-09 19:25 UTC (permalink / raw)
To: kstzavertaylo; +Cc: linux-crypto, herbert
In-Reply-To: <CAMho2RfgwvNhWJidb_Xn3RRt71TFjQ2QBKP9Xt8ur22L-ZWP9A@mail.gmail.com>
On Tue, Jun 09, 2026 at 10:45:48AM +0300, kstzavertaylo wrote:
> Hello,
> I have been working on an ML-KEM (FIPS 203) implementation for the
> Linux kernel. This is an early RFC to solicit feedback on the overall
> design and architecture before further polishing.
>
> The implementation consists of two closely related variants sharing
> the same core cryptographic logic:
> 1. A userspace implementation accompanied by a set of validation
> programs, including NIST KAT vectors, timing-leakage testing (dudect),
> pool stress tests, and additional functional tests.
> 2. A Linux kernel module implementing the KPP interface and
> reusing the same core architecture where possible.
>
> Key features include:
> 1. Support for all three parameter sets: ML-KEM-512, ML-KEM-768,
> and ML-KEM-1024.
> 2. The implementation uses a reusable decapsulation pool consisting
> of preallocated slots associated with a key context. The goal of this
> design is to move memory allocation to key initialization and avoid
> per-decapsulation allocations.
> 3. Explicit zeroization of sensitive data and constant-time
> operations where required.
> 4. Portable C11 codebase with minimal differences between userspace
> and kernel versions.
>
> I am aware that some aspects (local SHA3/SHAKE implementation, coding
> style, etc.) will likely need adjustment to align with upstream
> expectations.
>
> At this stage, I would like to ask for feedback on the following points:
> 1. Is the general direction (KPP integration + reusable
> decapsulation pool) acceptable?
> 2. Are there any fundamental concerns with the pool-based architecture?
> 3. Would you prefer to reuse kernel crypto primitives for
> SHA3/SHAKE, or is the current embedded approach acceptable at this
> stage?
>
> The implementation is available at: repository - https://github.com/kstzv/ml-kem
>
> Documentation and implementation details are available in the repository.
>
> Any feedback, criticism or suggestions would be greatly appreciated.
There's already a kernel patchset for ML-KEM and X-Wing ready to go:
https://lore.kernel.org/linux-crypto/20260525184403.101818-1-ebiggers@kernel.org/T/#u
It's a high quality implementation that fully follows kernel conventions
already. There just hasn't been a reason to merge it yet, since there's
no user yet.
We could consider replacing my ML-KEM implementation (patch 1 of that
series) with a different one. But it would have to be a high-quality
implementation that brings something substantially new to the table.
I think only an integration of
https://github.com/pq-code-package/mlkem-native *might* have a chance at
passing that bar. However, it would be way more code than my
implementation, would have significant integration challenges, and would
need some fixing up to work in the kernel. The main benefit would be
getting the assembly code, but it's not clear that will be needed. So
those are some of the reasons I didn't reach for that initially.
I don't think integrating https://github.com/kstzv/ml-kem would be
beneficial, for a number of reasons.
Anyway, I suggest you review the pre-existing patchset
https://lore.kernel.org/linux-crypto/20260525184403.101818-1-ebiggers@kernel.org/
and give feedback on that, if you have any.
- Eric
^ permalink raw reply
* Re: [PATCH v4] crypto/ccp: Introduce SNP_VERIFY_MITIGATION command
From: Tycho Andersen @ 2026-06-09 19:48 UTC (permalink / raw)
To: Pratik R. Sampat
Cc: ashish.kalra, thomas.lendacky, john.allen, herbert, davem,
linux-crypto, linux-kernel, aik, nikunj, michael.roth
In-Reply-To: <4957b07dbb4029a4c59bb3cf35f068c36284aa48.1780693665.git.prsampat@amd.com>
Hi Pratik,
On Mon, Jun 08, 2026 at 08:58:01PM +0000, Pratik R. Sampat wrote:
> The SEV-SNP firmware provides the SNP_VERIFY_MITIGATION command, which
> can be used to query the status of currently supported vulnerability
> mitigations and to initiate mitigations within the firmware.
>
> This command is an explicit mechanism to ascertain if a firmware
> mitigation is applied without needing a full RMP re-build, which is most
> useful in a live firmware update scenario.
>
> The firmware supports two subcommands: STATUS and VERIFY. The STATUS
> subcommand is used to query the supported and verified mitigation bits.
> The VERIFY subcommand initiates the mitigation process within the FW for
> the specified vulnerability. Expose a userspace interface under:
> /sys/firmware/sev/vulnerabilities/
> - supported_mitigations (read-only): supported mitigation vector mask
> - verified_mitigations (read/write): current verified mask; write a
> vector to request VERIFY for that bit
>
> The behavior of SNP_VERIFY_MITIGATION and the pre-requisites for using
> it are bug-specific. Information about supported mitigations and its
> corresponding vector is to be published as part of the AMD Security
> Bulletin.
>
> See SEV-SNP Firmware ABI specifications 1.58, SNP_VERIFY_MITIGATION for
> more details.
>
> Signed-off-by: Pratik R. Sampat <prsampat@amd.com>
Reviewed-by: Tycho Andersen (AMD) <tycho@kernel.org>
> + if (dst.mit_failure_status) {
> + dev_err(sev->dev, "Verify Mitigation - failure status: 0x%x\n",
> + dst.mit_failure_status);
> + return -EIO;
Elsewhere the CCP uses EIO to represent a failure to communicate with
the PSP, but here things worked, it was just in an invalid state.
Maybe worth a different errno here, -EINVAL or so.
Tycho
^ permalink raw reply
* Re: [PATCH] crypto: ecc - Optimize vli additive operations using compiler builtins
From: Fabian @ 2026-06-09 20:51 UTC (permalink / raw)
To: Stefan Berger; +Cc: lukas, ignat, herbert, davem, linux-crypto, linux-kernel
In-Reply-To: <bd992448-8ded-46f8-bf91-97792b9a11ad@linux.ibm.com>
On Tue, 9 Jun 2026 at 20:58, Stefan Berger <stefanb@linux.ibm.com> wrote:
>
>
>
> On 6/7/26 7:24 AM, Fabian Blatter wrote:
> > Replace the software carry flag emulation with compiler builtins.
> >
> > Even the newest compilers struggle with taking advantage of the
> > hardware carry flag. Compiler builtins allow the compiler to
> > much more easily achieve this while still remaining constant-time.
>
> It looks like you made vli_usub and vli_uadd constant-time now because
> otherwise the loops could be ended early once borrow == 0 or carry == 0
> respectively. Are all the other functions that operate on the private
> keys constant-time?
>
Thanks for the reply,
My primary goal with this patch was performance optimization.
I did not add early exiting because the original version didn't either.
To answer your question: No, some other functions in ecc.c
are not constant-time. For example, vli_is_zero and vli_cmp both
contain early exits.
My patch does remove the branches in the inner loop,
however, the original ones were already constant-time in practice,
because the compiler replaces the branches with cmov's.
I am happy to make any changes to this patch if you like.
I could also look into making `vli_cmp` and `vli_is_zero`,
or others constant-time in a future patch.
^ permalink raw reply
* Re: [PATCH net-next v2 0/5] Consolidate FCrypt and PCBC code into net/rxrpc/
From: patchwork-bot+netdevbpf @ 2026-06-10 0:20 UTC (permalink / raw)
To: Eric Biggers
Cc: netdev, linux-afs, dhowells, marc.dionne, linux-crypto,
linux-kernel, davem, edumazet, kuba, pabeni, horms
In-Reply-To: <20260522050740.84561-1-ebiggers@kernel.org>
Hello:
This series was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Fri, 22 May 2026 00:07:31 -0500 you wrote:
> The FCrypt "block cipher" and the PCBC mode of operation are obsolete
> and insecure. Since their only user is net/rxrpc/, they belong there,
> not in the crypto API.
>
> Therefore, this series removes these algorithms from the crypto API and
> replaces them with local implementations in net/rxrpc/.
>
> [...]
Here is the summary with links:
- [net-next,v2,1/5] net/rxrpc: Add local FCrypt-PCBC implementation
https://git.kernel.org/netdev/net-next/c/f10e73dffd2a
- [net-next,v2,2/5] net/rxrpc: Use local FCrypt-PCBC implementation
https://git.kernel.org/netdev/net-next/c/97b768514a6e
- [net-next,v2,3/5] net/rxrpc: Reimplement DES-PCBC using DES library
https://git.kernel.org/netdev/net-next/c/432042e25e33
- [net-next,v2,4/5] crypto: fcrypt - Remove support for FCrypt block cipher
https://git.kernel.org/netdev/net-next/c/374efbdc85d0
- [net-next,v2,5/5] crypto: pcbc - Remove support for PCBC mode
https://git.kernel.org/netdev/net-next/c/1967bfaf7ba1
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply
* [PATCH] MAINTAINERS: update hisilicon zip driver maintainer
From: Chenghai Huang @ 2026-06-10 1:34 UTC (permalink / raw)
To: shenyang39, fanghao11, liulongfang, qianweili, wangzhou1, herbert,
davem
Cc: linux-kernel, linux-crypto
Add Chenghai Huang as the maintainer of the hisilicon zip driver,
replacing Yang Shen.
Signed-off-by: Chenghai Huang<huangchenghai2@huawei.com>
---
MAINTAINERS | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index 882214b0e7db..7c66740aeb3c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11714,7 +11714,7 @@ W: http://www.hisilicon.com
F: drivers/spi/spi-hisi-sfc-v3xx.c
HISILICON ZIP Controller DRIVER
-M: Yang Shen <shenyang39@huawei.com>
+M: Chenghai Huang<huangchenghai2@huawei.com>
M: Zhou Wang <wangzhou1@hisilicon.com>
L: linux-crypto@vger.kernel.org
S: Maintained
--
2.43.0
^ permalink raw reply related
* Re: [PATCH] MAINTAINERS: update hisilicon zip driver maintainer
From: liulongfang @ 2026-06-10 1:47 UTC (permalink / raw)
To: Chenghai Huang, shenyang39, fanghao11, qianweili, wangzhou1,
herbert, davem
Cc: linux-kernel, linux-crypto
In-Reply-To: <20260610013437.1354503-1-huangchenghai2@huawei.com>
On 2026/6/10 9:34, Chenghai Huang wrote:
> Add Chenghai Huang as the maintainer of the hisilicon zip driver,
> replacing Yang Shen.
>
> Signed-off-by: Chenghai Huang<huangchenghai2@huawei.com>
> ---
> MAINTAINERS | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 882214b0e7db..7c66740aeb3c 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -11714,7 +11714,7 @@ W: http://www.hisilicon.com
> F: drivers/spi/spi-hisi-sfc-v3xx.c
>
> HISILICON ZIP Controller DRIVER
> -M: Yang Shen <shenyang39@huawei.com>
> +M: Chenghai Huang<huangchenghai2@huawei.com>
> M: Zhou Wang <wangzhou1@hisilicon.com>
> L: linux-crypto@vger.kernel.org
> S: Maintained
>
Reviewed-by: Longfang Liu <liulongfang@huawei.com>
Longfang
Thanks.
^ permalink raw reply
* Re: [PATCH net-next v2 0/5] Consolidate FCrypt and PCBC code into net/rxrpc/
From: Herbert Xu @ 2026-06-10 2:38 UTC (permalink / raw)
To: Paolo Abeni
Cc: David Howells, Marc Dionne, netdev, linux-afs, linux-crypto,
linux-kernel, David S . Miller, Eric Dumazet, Jakub Kicinski,
Simon Horman, Eric Biggers
In-Reply-To: <a4091402-e7c0-415e-a2a4-67d2b509462f@redhat.com>
On Tue, Jun 09, 2026 at 06:11:31PM +0200, Paolo Abeni wrote:
> Hi,
>
> On 6/9/26 8:18 AM, David Howells wrote:
> > Eric Biggers <ebiggers@kernel.org> wrote:
> >
> >>> If there's no more feedback, could this be applied to net-next?
> >>
> >> Any update on this?
> >
> > It's fine by me, but I'm not sure what I need to do with it - shouldn't it
> > already be in the netdev queue, or do I need to post it?
>
> This slipped under my radar, sorry. I just revived it in PW. Also, I
> think we need an explicit ack from Herbert.
>
> Link to ML post:
>
> https://lore.kernel.org/all/20260522050740.84561-1-ebiggers@kernel.org/
Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
Thanks,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* Re: [PATCH] MAINTAINERS: update hisilicon zip driver maintainer
From: Zhou Wang @ 2026-06-10 3:08 UTC (permalink / raw)
To: Chenghai Huang, shenyang39, fanghao11, liulongfang, qianweili,
herbert, davem
Cc: linux-kernel, linux-crypto
In-Reply-To: <20260610013437.1354503-1-huangchenghai2@huawei.com>
On 2026/6/10 9:34, Chenghai Huang wrote:
> Add Chenghai Huang as the maintainer of the hisilicon zip driver,
> replacing Yang Shen.
Many thanks for the work from shenyang about maintaining this driver.
It is very pleasure to work with you in these years, may you have a nice
job in future!
Acked-by: Zhou Wang <wangzhou1@hisilicon.com>
>
> Signed-off-by: Chenghai Huang<huangchenghai2@huawei.com>
> ---
> MAINTAINERS | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 882214b0e7db..7c66740aeb3c 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -11714,7 +11714,7 @@ W: http://www.hisilicon.com
> F: drivers/spi/spi-hisi-sfc-v3xx.c
>
> HISILICON ZIP Controller DRIVER
> -M: Yang Shen <shenyang39@huawei.com>
> +M: Chenghai Huang<huangchenghai2@huawei.com>
> M: Zhou Wang <wangzhou1@hisilicon.com>
> L: linux-crypto@vger.kernel.org
> S: Maintained
^ permalink raw reply
* [PATCH 0/2] Fix Qualcomm Crypto engine self tests failures
From: Kuldeep Singh @ 2026-06-10 5:54 UTC (permalink / raw)
To: Thara Gopinath, Herbert Xu, David S. Miller, Bartosz Golaszewski,
Eric Biggers
Cc: Thara Gopinath, linux-crypto, linux-arm-msm, linux-kernel,
Kuldeep Singh
QCE currents fails with crypto_sefltests for below 2 ciphers.
xts-aes qce and ctr-aes-qce.
Failure log snippet:
[ 5.599170] alg: skcipher: xts-aes-qce setkey failed on test vector 0; expected_error=0, actual_error=-126, flags=0x1
[ 5.599184] alg: self-tests for xts(aes) using xts-aes-qce failed (rc=-126)
[ 5.599187] ------------[ cut here ]------------
[ 5.599189] alg: self-tests for xts(aes) using xts-aes-qce failed (rc=-126)
[ 5.599222] WARNING: crypto/testmgr.c:5804 at alg_test+0x2a0/0x3bc, CPU#3: cryptomgr_test/150
[ 5.606169] alg: skcipher: ctr-aes-qce encryption test failed (wrong output IV) on test vector 4, cfg="in-place (one sglist)"
[ 5.606176] 00000000: e7 82 1d b8 53 11 ac 47 e2 7d 18 d6 71 0c a7 61
[ 5.606192] alg: self-tests for ctr(aes) using ctr-aes-qce failed (rc=-22)
[ 5.606196] ------------[ cut here ]------------
[ 5.606198] alg: self-tests for ctr(aes) using ctr-aes-qce failed (rc=-22)
[ 5.606231] WARNING: crypto/testmgr.c:5804 at alg_test+0x2a0/0x3bc, CPU#3: cryptomgr_test/149
This patch series attempt to stabilize QCE and stabilize selftest
framework. The failures are common for all targets and is currently
validated on sm8750-mtp and qcs6490-rb3gen2 device.
Steps followed:
- Enable EXPERT and CRYPTO_SEFLTESTS config.
- Bootup validation and confirm selftests is triggered.
Signed-off-by: Kuldeep Singh <kuldeep.singh@oss.qualcomm.com>
---
Kuldeep Singh (2):
crypto: qce: Fix xts-aes-qce for weak keys
crypto: qce: Fix CTR-AES for partial block requests
drivers/crypto/qce/cipher.h | 1 +
drivers/crypto/qce/skcipher.c | 29 ++++++++++++++++++++++-------
2 files changed, 23 insertions(+), 7 deletions(-)
---
base-commit: 49e02880ec0a8c378e811bc9d85da188d7c6204c
change-id: 20260610-qce_selftest_fix-2e0b66148651
Best regards,
--
Kuldeep Singh <kuldeep.singh@oss.qualcomm.com>
^ permalink raw reply
* [PATCH 1/2] crypto: qce: Fix xts-aes-qce for weak keys
From: Kuldeep Singh @ 2026-06-10 5:54 UTC (permalink / raw)
To: Thara Gopinath, Herbert Xu, David S. Miller, Bartosz Golaszewski,
Eric Biggers
Cc: Thara Gopinath, linux-crypto, linux-arm-msm, linux-kernel,
Kuldeep Singh
In-Reply-To: <20260610-qce_selftest_fix-v1-0-1b0504783a46@oss.qualcomm.com>
The QCE hardware does not support AES XTS mode when key1 and key2 are
equal. The driver was handling this by unconditionally rejecting the
keys with -ENOKEY(-126), regardless of whether FIPS mode is active or
the FORBID_WEAK_KEYS flag is set.
[ 5.599170] alg: skcipher: xts-aes-qce setkey failed on test vector 0; expected_error=0, actual_error=-126, flags=0x1
[ 5.599184] alg: self-tests for xts(aes) using xts-aes-qce failed (rc=-126)
In general for weak keys,
- If FIPS mode is active or FORBID_WEAK_KEYS is set: return -EINVAL.
- In non-FIPS mode, Accept the key and encrypt successfully.
Since QCE was returning -ENOKEY for non-FIPS mode whereas the
expectation is to encrypt content and return success, the selftest saw a
mismatch and failed.
There are two problems in QCE behavior:
* -ENOKEY is returned instead of -EINVAL for the FIPS/weak-key
rejection case.
* key1 == key2 is rejected even in non-FIPS mode
Fix xts-aes-qce behavior by using generic helper xts_verify_key() to
reject keys early with -EINVAL for FIPS mode active(or FORBID_WEAK_KEYS
set). For non-FIPS mode, since QCE hardware cannot accept the keys, use
software fallback mechanism to encrypt the data.
Fixes: f0d078dd6c49 ("crypto: qce - Return unsupported if key1 and key 2 are same for AES XTS algorithm")
Signed-off-by: Kuldeep Singh <kuldeep.singh@oss.qualcomm.com>
---
drivers/crypto/qce/cipher.h | 1 +
drivers/crypto/qce/skcipher.c | 20 +++++++++++++-------
2 files changed, 14 insertions(+), 7 deletions(-)
diff --git a/drivers/crypto/qce/cipher.h b/drivers/crypto/qce/cipher.h
index 850f257d00f3..daea07551118 100644
--- a/drivers/crypto/qce/cipher.h
+++ b/drivers/crypto/qce/cipher.h
@@ -14,6 +14,7 @@
struct qce_cipher_ctx {
u8 enc_key[QCE_MAX_KEY_SIZE];
unsigned int enc_keylen;
+ bool use_fallback;
struct crypto_skcipher *fallback;
};
diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c
index db0b648a56eb..224693a831f5 100644
--- a/drivers/crypto/qce/skcipher.c
+++ b/drivers/crypto/qce/skcipher.c
@@ -13,6 +13,7 @@
#include <crypto/aes.h>
#include <crypto/internal/des.h>
#include <crypto/internal/skcipher.h>
+#include <crypto/xts.h>
#include "cipher.h"
@@ -180,14 +181,17 @@ static int qce_skcipher_setkey(struct crypto_skcipher *ablk, const u8 *key,
if (!key || !keylen)
return -EINVAL;
- /*
- * AES XTS key1 = key2 not supported by crypto engine.
- * Revisit to request a fallback cipher in this case.
- */
if (IS_XTS(flags)) {
+ ret = xts_verify_key(ablk, key, keylen);
+ if (ret)
+ return ret;
__keylen = keylen >> 1;
- if (!memcmp(key, key + __keylen, __keylen))
- return -ENOKEY;
+ /*
+ * QCE does not support key1 == key2 for XTS.
+ * Use fallback cipher in this case.
+ */
+ ctx->use_fallback = !crypto_memneq(key, key + __keylen,
+ __keylen);
} else {
__keylen = keylen;
}
@@ -287,12 +291,14 @@ static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt)
* AES-XTS request with len > QCE_SECTOR_SIZE and
* is not a multiple of it.(Revisit this condition to check if it is
* needed in all versions of CE)
+ * AES-XTS for weak keys in non-FIPS mode.
*/
if (IS_AES(rctx->flags) &&
((keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_256) ||
(IS_XTS(rctx->flags) && ((req->cryptlen <= aes_sw_max_len) ||
(req->cryptlen > QCE_SECTOR_SIZE &&
- req->cryptlen % QCE_SECTOR_SIZE))))) {
+ req->cryptlen % QCE_SECTOR_SIZE))) ||
+ (IS_XTS(rctx->flags) && ctx->use_fallback))) {
skcipher_request_set_tfm(&rctx->fallback_req, ctx->fallback);
skcipher_request_set_callback(&rctx->fallback_req,
req->base.flags,
--
2.34.1
^ permalink raw reply related
* [PATCH 2/2] crypto: qce: Fix CTR-AES for partial block requests
From: Kuldeep Singh @ 2026-06-10 5:54 UTC (permalink / raw)
To: Thara Gopinath, Herbert Xu, David S. Miller, Bartosz Golaszewski,
Eric Biggers
Cc: Thara Gopinath, linux-crypto, linux-arm-msm, linux-kernel,
Kuldeep Singh
In-Reply-To: <20260610-qce_selftest_fix-v1-0-1b0504783a46@oss.qualcomm.com>
In CTR mode, the IV acts as the initial counter block.
APer NIST SP 800-38A, after a CTR mode operation the next unused counter
value is:
IV_next = IV_in + ceil(cryptlen / AES_BLOCK_SIZE)
The skcipher requires req->iv to hold this updated counter on
completion, ensuring chained requests produce correct results.
Referring to Crypto6.0 documentation, Section 2.2.5 says:
"The count value increments automatically once per block of data (in
AES, a block is 16 bytes) based on the value in the
CRYPTO_ENCR_CNTR_MASK registers."
QCE increments internal counter register once per full 16-byte block(for
ctr-aes) is processed. In case of partial request length, the hardware
uses the current counter to generate keystreams but does not increment
the counter register afterwards. So the counter value written in
CRYPTO_ENCR_CNTRn_IVn later once read by software is one less than the
expected value.
Crypto selftest framework capture this scenario with test vector
4 comprising of a 499-byte payload (31 full blocks + 3 partial bytes).
Error:
[ 5.606169] alg: skcipher: ctr-aes-qce encryption test failed (wrong output IV) on test vector 4, cfg="in-place (one sglist)"
[ 5.606176] 00000000: e7 82 1d b8 53 11 ac 47 e2 7d 18 d6 71 0c a7 61
[ 5.606192] alg: self-tests for ctr(aes) using ctr-aes-qce failed (rc=-22)
Expected iv_out: 0x62 (iv_in + 32)
Obtained iv_out: 0x61 (iv_in + 31, partial block not counted)
To fix this, just increase the counter value for partial block requests
by 1 and for the full block size requests, don't take any action as
expected value is already returned by the hardware.
Signed-off-by: Kuldeep Singh <kuldeep.singh@oss.qualcomm.com>
---
drivers/crypto/qce/skcipher.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c
index 224693a831f5..b25e3b76b6c8 100644
--- a/drivers/crypto/qce/skcipher.c
+++ b/drivers/crypto/qce/skcipher.c
@@ -11,6 +11,7 @@
#include <linux/types.h>
#include <linux/errno.h>
#include <crypto/aes.h>
+#include <crypto/algapi.h>
#include <crypto/internal/des.h>
#include <crypto/internal/skcipher.h>
#include <crypto/xts.h>
@@ -59,6 +60,14 @@ static void qce_skcipher_done(void *data)
dev_dbg(qce->dev, "skcipher operation error (%x)\n", status);
memcpy(rctx->iv, result_buf->encr_cntr_iv, rctx->ivsize);
+ /*
+ * QCE hardware does not increment the counter for a partial final
+ * block. Increment it in software so that iv_out reflects the correct
+ * next counter value expected by the CTR mode.
+ */
+ if (IS_CTR(rctx->flags) &&
+ (rctx->cryptlen % crypto_skcipher_chunksize(crypto_skcipher_reqtfm(req))))
+ crypto_inc(rctx->iv, rctx->ivsize);
qce->async_req_done(tmpl->qce, error);
}
--
2.34.1
^ permalink raw reply related
* Re: [PATCH 0/3] Add support for qcrypto on shikra
From: Kuldeep Singh @ 2026-06-10 6:05 UTC (permalink / raw)
To: Bartosz Golaszewski, Eric Biggers
Cc: Dmitry Baryshkov, Thara Gopinath, Herbert Xu, David S. Miller,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
Konrad Dybcio, Vinod Koul, Frank Li, Andy Gross, linux-arm-msm,
linux-crypto, devicetree, linux-kernel, dmaengine,
Bartosz Golaszewski, Gaurav Kashyap, Neeraj Soni
In-Reply-To: <CAMRc=MfY-tmMCdw9FVBgfkX-FvB5Nx2X06S023GhASenSCQSNA@mail.gmail.com>
> On Thu, May 28, 2026 at 7:52 PM Eric Biggers <ebiggers@kernel.org> wrote:
>>
>> On Thu, May 28, 2026 at 11:13:47AM -0400, Bartosz Golaszewski wrote:
>>> On Thu, 28 May 2026 15:50:10 +0200, Dmitry Baryshkov
>>> <dmitry.baryshkov@oss.qualcomm.com> said:
>>>> On Thu, May 28, 2026 at 09:13:23AM -0400, Bartosz Golaszewski wrote:
>>>>> On Thu, 28 May 2026 13:54:51 +0200, Kuldeep Singh
>>>>> <kuldeep.singh@oss.qualcomm.com> said:
>>>>>>>> +Bartosz, Gaurav, Neeraj
>>>>>
>>>>> I know about the self-tests etc., I will address them next.
All, kindly help in reviewing selftests fixes for QCE.
https://lore.kernel.org/linux-arm-msm/20260610-qce_selftest_fix-v1-0-1b0504783a46@oss.qualcomm.com/
--
Regards
Kuldeep
^ permalink raw reply
* [PATCH v3] mfd: loongson-se: Add multi-node support
From: Qunqin Zhao @ 2026-06-10 15:13 UTC (permalink / raw)
To: lee; +Cc: chenhuacai, xry111, linux-kernel, loongarch, linux-crypto,
Qunqin Zhao
On the Loongson platform, each node is equipped with a security engine
device. However, due to a hardware flaw, only the device on node 0 can
trigger interrupts. Therefore, interrupts from other nodes are forwarded
by node 0. We need to check in the interrupt handler of node 0 whether
this interrupt is intended for other nodes, this can be accomplished via
shared interrupt handling.
Signed-off-by: Qunqin Zhao <zhaoqunqin@loongson.cn>
---
V3:
Using shared interrupts (IRQF_SHARED) instead of manually
iterating through all devices to check for interrupts.
Link to v2:
https://lore.kernel.org/all/20260427165133.23350-1-zhaoqunqin@loongson.cn/
drivers/mfd/loongson-se.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/mfd/loongson-se.c b/drivers/mfd/loongson-se.c
index 3902ba377d6..e63ea40d5db 100644
--- a/drivers/mfd/loongson-se.c
+++ b/drivers/mfd/loongson-se.c
@@ -219,7 +219,7 @@ static int loongson_se_probe(struct platform_device *pdev)
for (i = 0; i < nr_irq; i++) {
irq = platform_get_irq(pdev, i);
- err = devm_request_irq(dev, irq, se_irq_handler, 0, "loongson-se", se);
+ err = devm_request_irq(dev, irq, se_irq_handler, IRQF_SHARED, "loongson-se", se);
if (err)
dev_err(dev, "failed to request IRQ: %d\n", irq);
}
@@ -228,7 +228,7 @@ static int loongson_se_probe(struct platform_device *pdev)
if (err)
return err;
- return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, engines,
+ return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, engines,
ARRAY_SIZE(engines), NULL, 0, NULL);
}
base-commit: 254f49634ee16a731174d2ae34bc50bd5f45e731
--
2.47.2
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox