crypto: cmh - add Rambus CryptoManager Hub core driver and AES
Subsystems (3)
v8 cover crypto: cmh - add Rambus CryptoManager Hub core driver and AES
The Rambus CryptoManager Hub (CMH) is a hardware cryptographic accelerator accessed through a mailbox-based VCQ (Virtual Command Queue) interface. This part, the first of the split posting (lineage and changelog below), adds the core platform driver, the shared key/datastore layer and the AES transforms, plus the device-tree binding and the MAINTAINERS entry. AES is the first and least-problematic algorithm family, so the core has a user and the VCQ/DMA/completion data path is reviewable end to end. Later parts add the remaining symmetric ciphers (SM4, ChaCha20-Poly1305) and the hwrng, the hashes and MACs, and finally the asymmetric and post-quantum algorithms together with the /dev/cmh_mgmt management interface.
The core driver binds the device, parses its device-tree description, sets up DMA, the mailbox queue interface and the transaction manager, and exposes sysfs/debugfs instrumentation. The key/datastore patch adds the raw-key handling and the datastore (SYS) command helpers that the AES driver in this series, and the algorithm drivers in the following series, build on.
The transaction manager runs as a kthread that packs VCQ entries and submits each request to the mailbox its core is bound to; completion is handled by per-mailbox threaded IRQs, or a watchdog poll without them. The data path is asynchronous: requests return -EINPROGRESS, and on a full queue a CRYPTO_TFM_REQ_MAY_BACKLOG request is backlogged (-EBUSY) while any other gets -ENOSPC.
The CMH eSW is loaded independently by the hardware before probe; the driver loads no firmware.
The CMH is a platform device matched via device tree (compatible "rambus,cmh-v1030"). Following the inside-secure,eip93 binding model and the DT maintainer's guidance, the schema requires a SoC-specific compatible ahead of the IP fallback and therefore carries no example.
Public hardware documentation:
Product overview: https://www.rambus.com/security/crypto-hub/
No public datasheets or downloadable briefs are currently available. The driver was developed against the Rambus CryptoManager Hub Hardware Reference Manual (Rambus Inc. confidential). Detailed hardware reference is available under NDA from Rambus Inc.; contact the maintainers listed in MAINTAINERS for access during review.
Developed against Herbert Xu's cryptodev tree. checkpatch.pl --strict, sparse (C=2) and a W=1 -Werror build are clean, and dtschema's dt-doc-validate accepts the binding. Exercised on riscv64 and arm64 -- QEMU with the CMH hardware model and a Xilinx VMK180 FPGA with the CMH IP -- under lockdep/PROVE_LOCKING, DEBUG_OBJECTS, KASAN/UBSAN/KMEMLEAK/KFENCE and (arm64) KCSAN with no findings; worst-case stack stays under 1 KB.
Changes in v8:
- dt-bindings: rambus,slot-stride-bytes is 512 or 1024; reword rambus,cores for cores that no mailbox lists.
- crypto: cmh: harden mailbox error recovery against concurrent interrupt and watchdog activity.
- crypto: cmh: close transaction-manager races in timeout arming, doorbell ringing and backlog promotion, and wake the manager for a backlogged request.
- crypto: cmh: never free memory the device may still write: DMA memory is freed or allocated only behind an acknowledged mailbox FLUSH, a mailbox that never acknowledges is retired with its buffers kept, and suspend is refused with -EBUSY instead of cancelling in-flight work.
- crypto: cmh: crypto API conformance: MAY_BACKLOG requests are never refused (unbounded backlog), others get -ENOSPC on a full queue, final completions run with BH disabled, CRYPTO_ALG_ALLOCATES_MEMORY is set, and sysfs bind/unbind is disabled.
- crypto: cmh: error codes: -EIO only for a device failure, -ECANCELED after recovery, -ENODEV on a retired mailbox, -EBADMSG for an AEAD tag mismatch.
- crypto: cmh: AES: drop cfb(aes); zero-length xts(aes) returns -EINVAL; out-of-place AEAD no longer writes the destination AAD; an oversized CCM payload returns -EOVERFLOW; the empty CCM tag uses the AES library; the second leg of a counter-wrap CTR request is backlogged.
- crypto: cmh: assorted small fixes and comment corrections.
- Documentation and patch split: each patch documents and adds only what it needs; the PQC command sizes moved to the PQC series.
- Rebased onto cryptodev-2.6 (7.4.0-rc1).
Changes in v7:
- Corrected the DCO sign-off chain so the co-developer attribution is immediately followed by that author's own sign-off and the submitting author signs last (the DCO point first raised on v3).
- crypto: cmh: close a debugfs force-drain vs teardown use-after-free -- the response-handler lock now also covers freeing the per-mailbox state on teardown, so a force-drain can no longer race it.
- crypto: cmh: reclaim abandoned mailbox scratch with a non-destructive flush ordered in the host command stream instead of a destructive per-mailbox MBX_COMMAND_FLUSH -- removing the cmh_tm_flush_mbx helper and its drain-wait -- so reclaiming scratch no longer cancels a crypto VCQ that shares the mailbox.
- Added the per-revision changelog and the prior-posting links below. The previous posting was sent untagged as "[PATCH 0/5]" and was the sixth revision (v6), so this is v7.
Changes in v6:
- Restructured the single v1-v5 series into smaller, independently reviewable per-maintainer chunks. This first series is the core driver, the shared key/datastore layer and AES; later series add the remaining algorithms and the management ioctl interface.
- dt-bindings: simplified the clock-names schema -- the oneOf collapses to a single items list (core, an optional core-div2 or rt, then rt,
minItems: 1) -- and bounded the per-mailbox queue reg to the hardware range (maximum: 63), following the v5 DT review.
- crypto: cmh: the response handler accumulates the IRQ status bits before clearing the pending flag and releases its mailbox IRQs on teardown even after a suspend; a wedged pinned mailbox now fails with -EIO instead of head-of-line blocking; a second probe is rejected; and debugfs ABORT injection and force-drain take the response-handler lock.
- crypto: cmh: AES-CMAC hardware-accelerates the one-shot .digest() only and forwards the incremental and virtual-address paths to a generic cmac(aes) transform the driver allocates in .init_tfm() (CRYPTO_ALG_NO_FALLBACK + CRYPTO_ALG_REQ_VIRT, as the generic cmac(aes) shash has no export_core and cannot back crypto_ahash_fb()).
- crypto: cmh: moved the datastore-type-to-core-id mapping into the management layer so the key/datastore code no longer depends on the management UAPI header; that header now lands with the ioctl implementation in a later series.
Changes in v5:
- dt-bindings: reworked the compatible and rambus,cores per DT review -- require a SoC-specific compatible ahead of the "rambus,cmh-v1030" IP fallback via the inside-secure,eip93 "not: {}" idiom (no example can validate until a real SoC is upstreamed), switch rambus,cores to a string-array of core names, and replace the positional clocks list with a count-bounded description.
- crypto: cmh: transaction-manager / response-handler race fixes -- FLUSH and drain instead of restarting the eSW into freed slots, serialise the mailbox TAIL doorbell, ABORT a sync timeout only at the mailbox HEAD, and reject an over-large num_vcqs.
Changes in v4:
- dt-bindings: renamed the per-mailbox child to queue@N and described its ring geometry as plain counts (rambus,num-slots / rambus,slot-stride- bytes) rather than log2; renamed the binding to rambus,cmh-v1030.yaml.
- crypto: cmh: convert to module_platform_driver() + dev_err_probe() and drop the single-instance guard; remove informational probe logging; and drop the production module parameters (built-in constants, with debug-only knobs under debugfs).
Changes in v3:
- dt-bindings: reworked the mailbox topology per DT review -- mailbox@N child nodes, with cores discovered from CORE_ENABLE rather than the DT -- and adopted the "rambus" vendor prefix with a device-specific "rambus,cmh-v1030" compatible (the IP revision).
Changes in v2:
- crypto: cmh: gate probe on both eSW readiness bits (MISSION and MISSION2) so an operation offloaded to the sidecar engine cannot race an engine that is not yet up.
The CMH driver was first posted as a single series; following
maintainer feedback it is now split into smaller, independently reviewable parts, numbered continuously across the split. Earlier postings:
v1: https://lore.kernel.org/linux-crypto/[email protected]/
v2: https://lore.kernel.org/linux-crypto/[email protected]/
v3: https://lore.kernel.org/linux-crypto/[email protected]/
v4: https://lore.kernel.org/linux-crypto/[email protected]/
v5: https://lore.kernel.org/linux-crypto/[email protected]/
v6: https://lore.kernel.org/linux-crypto/[email protected]/
v7: https://lore.kernel.org/linux-crypto/[email protected]/
---
Alex Ousherovitch (5):
dt-bindings: crypto: add Rambus CryptoManager Hub
crypto: cmh - add core platform driver
crypto: cmh - add key/datastore infrastructure
crypto: cmh - add AES skcipher/aead/cmac
MAINTAINERS: add Rambus CryptoManager Hub (CMH)
Documentation/ABI/testing/debugfs-driver-cmh | 145 ++ Documentation/ABI/testing/sysfs-driver-cmh | 62 + Documentation/crypto/device_drivers/cmh.rst | 308 +++ Documentation/crypto/device_drivers/index.rst | 1 + .../bindings/crypto/rambus,cmh-v1030.yaml | 145 ++ .../devicetree/bindings/vendor-prefixes.yaml | 2 + MAINTAINERS | 13 + drivers/crypto/Kconfig | 1 + drivers/crypto/Makefile | 1 + drivers/crypto/cmh/Kconfig | 48 + drivers/crypto/cmh/Makefile | 30 + drivers/crypto/cmh/cmh_aes.c | 705 ++++++ drivers/crypto/cmh/cmh_aes_aead.c | 934 ++++++++ drivers/crypto/cmh/cmh_aes_cmac.c | 459 ++++ drivers/crypto/cmh/cmh_config.c | 625 +++++ drivers/crypto/cmh/cmh_debugfs.c | 309 +++ drivers/crypto/cmh/cmh_dma.c | 354 +++ drivers/crypto/cmh/cmh_key.c | 138 ++ drivers/crypto/cmh/cmh_main.c | 413 ++++ drivers/crypto/cmh/cmh_mqi.c | 457 ++++ drivers/crypto/cmh/cmh_rh.c | 1434 +++++++++++ drivers/crypto/cmh/cmh_sys.c | 56 + drivers/crypto/cmh/cmh_sysfs.c | 108 + drivers/crypto/cmh/cmh_txn.c | 2531 ++++++++++++++++++++ drivers/crypto/cmh/include/cmh.h | 24 + drivers/crypto/cmh/include/cmh_aes.h | 24 + drivers/crypto/cmh/include/cmh_aes_abi.h | 98 + drivers/crypto/cmh/include/cmh_config.h | 110 + drivers/crypto/cmh/include/cmh_debugfs.h | 94 + drivers/crypto/cmh/include/cmh_dma.h | 195 ++ drivers/crypto/cmh/include/cmh_key.h | 76 + drivers/crypto/cmh/include/cmh_mqi.h | 59 + drivers/crypto/cmh/include/cmh_registers.h | 147 ++ drivers/crypto/cmh/include/cmh_rh.h | 98 + drivers/crypto/cmh/include/cmh_sys.h | 23 + drivers/crypto/cmh/include/cmh_sys_abi.h | 148 ++ drivers/crypto/cmh/include/cmh_sysfs.h | 14 + drivers/crypto/cmh/include/cmh_txn.h | 666 +++++ drivers/crypto/cmh/include/cmh_vcq.h | 203 ++ 39 files changed, 11258 insertions(+)
---
base-commit: 82e91fe19fb838f235f7c8829afc1eb389c93bdf
change-id: 20261110-cmh-b4-a-v8-a3d0d8a3687e
Best regards,
Signature · 1 line
Alex Ousherovitch <[email protected]>
PATCH v8 1/5 dt-bindings: crypto: add Rambus CryptoManager Hub
Add device tree binding schema for the Rambus CryptoManager Hub (CMH) hardware crypto accelerator. The binding describes the parent SoC-level node with its SIC register region and one queue@N child node per mailbox the host owns, each carrying a reg (mailbox instance index), an optional interrupt, VCQ ring geometry (rambus,num-slots / rambus,slot-stride-bytes) and a rambus,cores affinity list. Which crypto cores are present is discovered from the SIC CORE_ENABLE register at probe, not described in the device tree.
Register the 'rambus' vendor prefix for Rambus Inc.
--- .../bindings/crypto/rambus,cmh-v1030.yaml | 145 +++++++++++++++++++++ .../devicetree/bindings/vendor-prefixes.yaml | 2 + 2 files changed, 147 insertions(+)
Documentation/devicetree/bindings/crypto/rambus,cmh-v1030.yaml new file +145 -0
@@ -0,0 +1,145 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/crypto/rambus,cmh-v1030.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Rambus CryptoManager Hub (CMH) Hardware Crypto Accelerator + +maintainers: + - Alex Ousherovitch <[email protected]> + - Saravanakrishnan Krishnamoorthy <[email protected]> + - Joel Wittenauer <[email protected]> + +description: | + The Rambus CryptoManager Hub (CMH) is a hardware cryptographic accelerator + accessed via a mailbox-based VCQ (Virtual Command Queue) interface. The + host writes VCQ command sequences into per-mailbox DMA queue buffers and + rings a doorbell; the CMH eSW processes them and signals completion via + interrupt. + + The management host statically partitions the hardware mailboxes across + the SoC's host interfaces at integration time; the set of mailboxes a + given host owns is therefore fixed and not runtime-discoverable (a + mailbox locked to a host reads as unavailable in the SIC availability + register). Each owned mailbox is described by a child node. Which + crypto cores are present is a fixed silicon-build property indicated by + the SIC CORE_ENABLE register, so cores are not described in the device + tree. Clock and reset are owned by the management host; a node + describing a non-management host has no clock or reset provider of its + own, so clocks and reset-gpios are optional. + + CMH gates access to a locked mailbox by a hardware HOST ID presented on + the bus with every access, permitting only the owning host's ID. An + integration must present a single, stable HOST ID for all accesses to a + given mailbox, independent of the issuing CPU (relevant on SMP hosts + whose interconnect encodes the issuing CPU in the HOST ID). + +properties: + compatible: + items: + - not: {} + description: SoC-specific compatible, e.g. vendor,soc-cmh + - const: rambus,cmh-v1030 + + reg: + maxItems: 1 + description: + SIC (System Interface Controller) MMIO region. The registers of + mailbox instance N are at offset N * 0x1000 within this region. + + clocks: + minItems: 1 + maxItems: 3 + description: + The "core" functional clock, and optionally the half-rate "core-div2" + clock (present only on configurations with side-channel-protected + cores) and/or the "rt" real-time tick clock. See clock-names for the + valid combinations. + + clock-names: + minItems: 1 + items: + - const: core + - enum: [core-div2, rt] + - const: rt + + reset-gpios: + maxItems: 1 + description: + Host-controlled reset for the CryptoManager Hub. The hub has two + external, active-low reset inputs -- a power-on reset and a hard + reset; where a board routes one of them to a host GPIO, that line is + described here. + + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + +patternProperties: + "^queue@[0-9a-f]+$": + type: object + description: + One node per hardware mailbox (VCQ command queue) this host owns. + The set of owned mailboxes is fixed by the management host at + integration time and enumerated here. + properties: + reg: + items: + - maximum: 63 + description: + 0-based mailbox instance index (0..63). The instance's + registers are at reg * 0x1000 within the SIC region. + + interrupts: + maxItems: 1 + description: Completion/error interrupt for this mailbox. + + rambus,num-slots: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, + 16384, 32768] + default: 64 + description: + Number of VCQ ring slots for this mailbox's command queue in + host DMA memory. This is a per-board, per-mailbox host-memory + ring geometry -- boards built around the same SoC (hence the + same compatible) may use different ring sizes, so it is + described per mailbox rather than derived from the compatible. + + rambus,slot-stride-bytes: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [512, 1024] + default: 512 + description: + Stride in bytes between consecutive VCQ ring slots for this + mailbox's command queue. Like rambus,num-slots this is a + per-board host-memory ring geometry, not derived from the + compatible. A slot must hold a complete command sequence, + which needs at least 512 bytes. + + rambus,cores: + $ref: /schemas/types.yaml#/definitions/string-array + items: + enum: [hc, aes, sm4, sm3, hcq, qse, pke, ccp] + description: | + Core-affinity list: the crypto cores whose work is dispatched to + this mailbox. A core may appear on at most one mailbox. Work + for cores not listed on any mailbox may be dispatched through + any mailbox. Optional (default: none -- the mailbox only + serves unlisted cores). + + required: + - reg + + additionalProperties: false + +required: + - compatible + - reg + - "#address-cells" + - "#size-cells" + +additionalProperties: false
Documentation/devicetree/bindings/vendor-prefixes.yaml +2 -0
@@ -1411,6 +1411,8 @@ patternProperties: description: RaidSonic Technology GmbH "^ralink,.*": description: Mediatek/Ralink Technology Corp. + "^rambus,.*": + description: Rambus Inc. "^ramtron,.*": description: Ramtron International "^raspberrypi,.*":
Signature · 1 line
2.43.7
PATCH v8 2/5 crypto: cmh - add core platform driver
In reply to Alex OusherovitchAdd the core platform driver for the Rambus CryptoManager Hub (CMH). The CMH embedded software (eSW) executes commands that the host posts, as VCQs (Virtual Command Queues), to mailbox rings in DMA memory, and signals completion through the mailbox interrupt. This patch registers no algorithms; those follow in later patches.
- Probe/remove: map the device, wait for the eSW, discover the enabled cores and set up the mailboxes described in the Device Tree.
- Transaction manager: a kthread that writes each request's VCQs into a mailbox ring and rings the doorbell, with a backlog for CRYPTO_TFM_REQ_MAY_BACKLOG requests.
- Response handler: completes requests from the threaded mailbox interrupt, with a watchdog for missed interrupts, and recovers a mailbox after an error with RESTART or FLUSH.
- DMA: memory the device may still write is freed only once the device is known to be done with it.
- sysfs attributes (fw_version, hw_version, boot_status, mbx_available, mbx_count). With CONFIG_CRYPTO_DEV_CMH_DEBUG: debugfs counters and tunables, ABORT/drain fault injection, and bring-up module parameters that override the mailbox geometry or skip the eSW boot check.
- Documentation: the driver overview and the sysfs and debugfs ABI.
--- Documentation/ABI/testing/debugfs-driver-cmh | 145 ++ Documentation/ABI/testing/sysfs-driver-cmh | 62 + Documentation/crypto/device_drivers/cmh.rst | 282 +++ Documentation/crypto/device_drivers/index.rst | 1 + drivers/crypto/Kconfig | 1 + drivers/crypto/Makefile | 1 + drivers/crypto/cmh/Kconfig | 37 + drivers/crypto/cmh/Makefile | 25 + drivers/crypto/cmh/cmh_config.c | 625 ++++++ drivers/crypto/cmh/cmh_debugfs.c | 309 +++ drivers/crypto/cmh/cmh_dma.c | 354 ++++ drivers/crypto/cmh/cmh_main.c | 386 ++++ drivers/crypto/cmh/cmh_mqi.c | 457 +++++ drivers/crypto/cmh/cmh_rh.c | 1434 ++++++++++++++ drivers/crypto/cmh/cmh_sysfs.c | 108 ++ drivers/crypto/cmh/cmh_txn.c | 2531 +++++++++++++++++++++++++ drivers/crypto/cmh/include/cmh.h | 24 + drivers/crypto/cmh/include/cmh_config.h | 110 ++ drivers/crypto/cmh/include/cmh_debugfs.h | 94 + drivers/crypto/cmh/include/cmh_dma.h | 195 ++ drivers/crypto/cmh/include/cmh_mqi.h | 59 + drivers/crypto/cmh/include/cmh_registers.h | 147 ++ drivers/crypto/cmh/include/cmh_rh.h | 98 + drivers/crypto/cmh/include/cmh_sys_abi.h | 148 ++ drivers/crypto/cmh/include/cmh_sysfs.h | 14 + drivers/crypto/cmh/include/cmh_txn.h | 666 +++++++ drivers/crypto/cmh/include/cmh_vcq.h | 201 ++ 27 files changed, 8514 insertions(+)
Documentation/ABI/testing/debugfs-driver-cmh new file +145 -0
@@ -0,0 +1,145 @@ +What: /sys/kernel/debug/cmh/mbx<N>/vcqs_submitted +Date: November 2026 +Contact: [email protected] +Description: + (RO) Total number of VCQ command entries submitted to + mailbox N since the driver was loaded. + +What: /sys/kernel/debug/cmh/mbx<N>/vcqs_completed +Date: November 2026 +Contact: [email protected] +Description: + (RO) Total number of VCQ command completions received + from mailbox N. + +What: /sys/kernel/debug/cmh/mbx<N>/vcqs_errors +Date: November 2026 +Contact: [email protected] +Description: + (RO) Total number of error completions received from + mailbox N. + +What: /sys/kernel/debug/cmh/mbx<N>/queue_full_count +Date: November 2026 +Contact: [email protected] +Description: + (RO) Number of times the transaction manager skipped + mailbox N because its in-flight queue was full. + +What: /sys/kernel/debug/cmh/mbx<N>/max_queue_depth +Date: November 2026 +Contact: [email protected] +Description: + (RO) High-water mark of in-flight transactions on + mailbox N. + +What: /sys/kernel/debug/cmh/mbx<N>/inject_abort +Date: November 2026 +Contact: [email protected] +Description: + (WO) Write any value to inject an MBX_COMMAND_ABORT on + mailbox N. The abort triggers error-IRQ handling: the + aborted transaction completes with -EIO and + MBX_COMMAND_RESTART resumes the mailbox, or, if that + transaction spans several VCQs, the mailbox is flushed and, + once the eSW acknowledges the FLUSH, the transactions queued + behind it complete with -ECANCELED. + Only available when CONFIG_CRYPTO_DEV_CMH_DEBUG is enabled. + +What: /sys/kernel/debug/cmh/mbx<N>/force_drain +Date: November 2026 +Contact: [email protected] +Description: + (WO) Write any value to FLUSH mailbox N as a last-resort + recovery, including of a retired (wedged) mailbox. The + recovery state is reset, the mailbox is closed to new work + and MBX_COMMAND_FLUSH is issued. When the eSW acknowledges + it (the write waits up to one second), every pending + transaction completes with -ECANCELED and the mailbox + reopens; otherwise the watchdog keeps waiting for the + acknowledgment and retires the mailbox again if it never + comes. + Only available when CONFIG_CRYPTO_DEV_CMH_DEBUG is enabled. + +What: /sys/kernel/debug/cmh/tm/cmq_posts +Date: November 2026 +Contact: [email protected] +Description: + (RO) Total number of cmh_tm_post_command() calls (one + per crypto request submitted to the transaction manager). + +What: /sys/kernel/debug/cmh/tm/cmq_depth_max +Date: November 2026 +Contact: [email protected] +Description: + (RO) High-water mark of the command queue length. + +What: /sys/kernel/debug/cmh/tm/cmq_full_count +Date: November 2026 +Contact: [email protected] +Description: + (RO) Number of times the command queue was full and + returned -ENOSPC to the caller. + +What: /sys/kernel/debug/cmh/tm/backoff_count +Date: November 2026 +Contact: [email protected] +Description: + (RO) Number of times the transaction manager backed off + because all mailbox queues were full. + +What: /sys/kernel/debug/cmh/tm/async_timeout_count +Date: November 2026 +Contact: [email protected] +Description: + (RO) Number of async crypto requests that timed out + waiting for hardware completion. + +What: /sys/kernel/debug/cmh/config/async_timeout_ms +Date: November 2026 +Contact: [email protected] +Description: + (RW) Async request timeout in milliseconds. A request + that times out completes with -ETIMEDOUT once the device + has finished with it. If it is at the head of its mailbox + and the device does not finish, the watchdog issues + MBX_COMMAND_ABORT and then FLUSH. + +What: /sys/kernel/debug/cmh/config/vcq_timeout_ms +Date: November 2026 +Contact: [email protected] +Description: + (RW) Timeout in milliseconds for synchronous commands. On + expiry the driver issues MBX_COMMAND_ABORT if the command + is executing. + +What: /sys/kernel/debug/cmh/config/slow_op_timeout_ms +Date: November 2026 +Contact: [email protected] +Description: + (RW) Slow-operation timeout in milliseconds. Used for + operations known to take longer, such as key generation. + +What: /sys/kernel/debug/cmh/config/drain_timeout_ms +Date: November 2026 +Contact: [email protected] +Description: + (RW) Drain timeout in milliseconds. Maximum time suspend + waits for the transactions already on the device to + complete; if any is still running, the suspend is refused + with -EBUSY. + +What: /sys/kernel/debug/cmh/config/watchdog_ms +Date: November 2026 +Contact: [email protected] +Description: + (RW) Result-handler watchdog interval in milliseconds. + Detects missed IRQs, stuck mailboxes, and abort-stall + conditions. Clamped to a 10 ms minimum. + +What: /sys/kernel/debug/cmh/config/cmq_max_depth +Date: November 2026 +Contact: [email protected] +Description: + (RW) Maximum number of pending commands in the central + Command Message Queue.
Documentation/ABI/testing/sysfs-driver-cmh new file +62 -0
62 lines not on this page · raw message
Documentation/crypto/device_drivers/cmh.rst new file +282 -0
282 lines not on this page · raw message
Documentation/crypto/device_drivers/index.rst +1 -0
@@ -6,4 +6,5 @@ Hardware Device Driver Specific Documentation .. toctree:: :maxdepth: 1 + cmh octeontx2
drivers/crypto/Kconfig +1 -0
@@ -830,5 +830,6 @@ source "drivers/crypto/aspeed/Kconfig" source "drivers/crypto/starfive/Kconfig" source "drivers/crypto/inside-secure/eip93/Kconfig" source "drivers/crypto/ti/Kconfig" +source "drivers/crypto/cmh/Kconfig" endif # CRYPTO_HW
drivers/crypto/Makefile +1 -0
@@ -46,3 +46,4 @@ obj-y += intel/ obj-y += starfive/ obj-y += cavium/ obj-y += ti/ +obj-$(CONFIG_CRYPTO_DEV_CMH) += cmh/
drivers/crypto/cmh/Kconfig new file +37 -0
@@ -0,0 +1,37 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Rambus CryptoManager Hub (CMH) hardware crypto accelerator +# +# The VCQ command and DMA descriptor ABI uses native (host-endian) +# integer types and is only valid on little-endian hosts: the CMH block +# and its eSW are co-located on the same little-endian SoC and there is +# no big-endian deployment. Gate the driver on !CPU_BIG_ENDIAN rather +# than byte-swapping an ABI that would never be exercised. +# + +config CRYPTO_DEV_CMH + tristate "Rambus CryptoManager Hub (CMH) hardware crypto accelerator" + depends on CRYPTO && OF && HAS_IOMEM && (64BIT || COMPILE_TEST) + depends on !CPU_BIG_ENDIAN + help + Driver for the Rambus CryptoManager Hub (CMH) hardware crypto + accelerator. The device is accessed through a mailbox-based VCQ + (Virtual Command Queue) interface: the driver writes command + sequences into per-mailbox DMA queues and completes them from a + threaded interrupt, registering the algorithms the hardware + provides with the kernel crypto subsystem. See /proc/crypto for + the set on a running kernel. + + To compile this driver as a module, choose M here. + +config CRYPTO_DEV_CMH_DEBUG + bool "CMH debug instrumentation (debugfs counters)" + depends on CRYPTO_DEV_CMH && DEBUG_FS + help + Enable per-mailbox debugfs counters under + /sys/kernel/debug/cmh/ for the CMH driver. + Exposes VCQ submit/complete/error counts, queue depth + high-water marks, and transaction manager backoff statistics. + + Useful for bringup, validation, and performance analysis. + Not recommended for production.
drivers/crypto/cmh/Makefile new file +25 -0
@@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Makefile for the Rambus CryptoManager Hub (CMH) hardware crypto accelerator driver. +# + +obj-$(CONFIG_CRYPTO_DEV_CMH) += cmh.o + +cmh-y := \ + cmh_main.o \ + cmh_config.o \ + cmh_mqi.o \ + cmh_txn.o \ + cmh_rh.o \ + cmh_dma.o \ + cmh_sysfs.o + +ccflags-y += -I$(src)/include + +# Suppress -Woverride-init for the [0 ... N] = -1 range-initializer pattern +# (standard kernel idiom for sparse lookup tables with a default value). +CFLAGS_cmh_config.o += -Wno-override-init + +# Debug instrumentation: per-mailbox debugfs counters. +# cmh_debugfs.o is linked into the composite cmh.o (same tristate). +cmh-$(CONFIG_CRYPTO_DEV_CMH_DEBUG) += cmh_debugfs.o
drivers/crypto/cmh/cmh_config.c new file +625 -0
625 lines not on this page · raw message
drivers/crypto/cmh/cmh_debugfs.c new file +309 -0
309 lines not on this page · raw message
drivers/crypto/cmh/cmh_dma.c new file +354 -0
354 lines not on this page · raw message
drivers/crypto/cmh/cmh_main.c new file +386 -0
386 lines not on this page · raw message
drivers/crypto/cmh/cmh_mqi.c new file +457 -0
457 lines not on this page · raw message
drivers/crypto/cmh/cmh_rh.c new file +1434 -0
303 lines not on this page · raw message
drivers/crypto/cmh/cmh_sysfs.c new file +108 -0
108 lines not on this page · raw message
drivers/crypto/cmh/cmh_txn.c new file +2531 -0
2,531 lines not on this page · raw message
drivers/crypto/cmh/include/cmh.h new file +24 -0
Lines of this file are not shown. View the raw message.
drivers/crypto/cmh/include/cmh_config.h new file +110 -0
110 lines not on this page · raw message
drivers/crypto/cmh/include/cmh_debugfs.h new file +94 -0
94 lines not on this page · raw message
drivers/crypto/cmh/include/cmh_dma.h new file +195 -0
195 lines not on this page · raw message
drivers/crypto/cmh/include/cmh_mqi.h new file +59 -0
59 lines not on this page · raw message
drivers/crypto/cmh/include/cmh_registers.h new file +147 -0
147 lines not on this page · raw message
drivers/crypto/cmh/include/cmh_rh.h new file +98 -0
98 lines not on this page · raw message
drivers/crypto/cmh/include/cmh_sys_abi.h new file +148 -0
148 lines not on this page · raw message
drivers/crypto/cmh/include/cmh_sysfs.h new file +14 -0
Lines of this file are not shown. View the raw message.
drivers/crypto/cmh/include/cmh_txn.h new file +666 -0
666 lines not on this page · raw message
drivers/crypto/cmh/include/cmh_vcq.h new file +201 -0
201 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
Signature · 1 line
2.43.7
Part of the diff is not shown here. View the raw message.
PATCH v8 3/5 crypto: cmh - add key/datastore infrastructure
In reply to Alex OusherovitchAdd the CMH key and datastore (system object) layer shared by the algorithm drivers. cmh_key.c stages a raw key into a per-transform context and DMA-maps it for the lifetime of the transform; cmh_sys.c builds the SYS_WRITE datastore command that loads such a key into the per-mailbox temporary datastore slot (SYS_REF_TEMP) of a request's VCQ.
The AES driver that follows is the first user. Builders for the other SYS datastore commands are added together with the drivers that use them. No crypto API algorithm is registered by this patch.
--- drivers/crypto/cmh/Makefile | 4 +- drivers/crypto/cmh/cmh_key.c | 138 +++++++++++++++++++++++++++++++++++ drivers/crypto/cmh/cmh_sys.c | 56 ++++++++++++++ drivers/crypto/cmh/include/cmh_key.h | 76 +++++++++++++++++++ drivers/crypto/cmh/include/cmh_sys.h | 23 ++++++ 5 files changed, 296 insertions(+), 1 deletion(-)
drivers/crypto/cmh/Makefile +3 -1
@@ -12,7 +12,9 @@ cmh-y := \ cmh_txn.o \ cmh_rh.o \ cmh_dma.o \ - cmh_sysfs.o + cmh_sysfs.o \ + cmh_sys.o \ + cmh_key.o ccflags-y += -I$(src)/include
drivers/crypto/cmh/cmh_key.c new file +138 -0
138 lines not on this page · raw message
drivers/crypto/cmh/cmh_sys.c new file +56 -0
56 lines not on this page · raw message
drivers/crypto/cmh/include/cmh_key.h new file +76 -0
76 lines not on this page · raw message
drivers/crypto/cmh/include/cmh_sys.h new file +23 -0
@@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* Copyright (c) 2026 Cryptography Research, Inc. (CRI). +* CMH LKM -- SYS Core VCQ Builders +* +* VCQ builder functions for the SYS (datastore) core and the other +* cores whose commands are issued by more than one driver. Each builder +* populates one vcq_cmd slot with the appropriate magic, command ID, and +* payload. +* +* Callers combine these with vcq_set_header() + vcq_add_flush() +* and submit via cmh_tm_submit_sync(). +*/ + +#ifndef CMH_SYS_H +#define CMH_SYS_H + +#include "cmh_vcq.h" + +void vcq_add_sys_write (struct vcq_cmd *slot,u64 ref,u64 src_dma, +u64 wrap_key,u32 len,u32 sys_type); + +#endif /* CMH_SYS_H */
Signature · 1 line
2.43.7
PATCH v8 4/5 crypto: cmh - add AES skcipher/aead/cmac
In reply to Alex OusherovitchRegister AES algorithms on the CMH AES core:
- skcipher: ecb(aes), cbc(aes), ctr(aes), xts(aes)
- aead: gcm(aes), ccm(aes)
- ahash: cmac(aes)
The core does not cover everything the crypto API allows, so some requests take another path:
- CTR: the core increments only the low 64 bits of the counter. A request that would wrap them is split in two submissions, the second with the carry applied, so the result matches ctr(aes).
- CCM: the core rejects a 10-byte tag, so those requests go to a ccm(aes) software transform. With no AAD and no payload the tag is two block encryptions, computed on the host with the AES library; an empty GCM request runs one block encryption on the device and the tag is compared on the host.
- The core reports a GCM/CCM tag mismatch with the same error as its other failures, so a failed decrypt returns -EBADMSG.
- The hardware path linearises a request into one DMA buffer; skcipher requests over 32 MiB and AEAD requests over 1 MiB (AAD plus payload) get -EINVAL.
cmac(aes) runs the one-shot .digest() on the hardware, from a scatterlist or a virtual address. The incremental operations and export/import go to a generic cmac(aes) transform, because the hardware state cannot be exported in the crypto API format. The generic cmac(aes) has no export_core, so the core cannot install it as the crypto_ahash_fb() fallback; the driver sets CRYPTO_ALG_NO_FALLBACK and allocates the transform itself. The hashes and HMAC in a later series use crypto_ahash_fb() and do not set the flag.
The AES core command definitions (cmh_aes_abi.h) are added here.
--- Documentation/crypto/device_drivers/cmh.rst | 26 + drivers/crypto/cmh/Kconfig | 11 + drivers/crypto/cmh/Makefile | 5 +- drivers/crypto/cmh/cmh_aes.c | 705 +++++++++++++++++++++ drivers/crypto/cmh/cmh_aes_aead.c | 934 ++++++++++++++++++++++++++++ drivers/crypto/cmh/cmh_aes_cmac.c | 459 ++++++++++++++ drivers/crypto/cmh/cmh_main.c | 27 + drivers/crypto/cmh/include/cmh_aes.h | 24 + drivers/crypto/cmh/include/cmh_aes_abi.h | 98 +++ drivers/crypto/cmh/include/cmh_vcq.h | 2 + 10 files changed, 2290 insertions(+), 1 deletion(-)
Documentation/crypto/device_drivers/cmh.rst +26 -0
@@ -54,6 +54,11 @@ sizes, and curves within each family are those of the underlying CMH device; the CMH host-API documentation is authoritative for the supported set on a given CMH configuration. +AES + skcipher: ECB, CBC, CTR, XTS; + AEAD: GCM, CCM; + ahash: CMAC(AES) + All algorithm driver names use the ``rambus-cmh-`` prefix (e.g. ``rambus-cmh-ecb-aes``, ``rambus-cmh-gcm-aes``). Names generally follow the kernel's hyphenated template name; families that have no kernel
@@ -68,6 +73,10 @@ recently registered one is chosen, so the result depends on load order. Callers that require this hardware should allocate by driver name, and can check the driver name of an allocated transform. +AES-CCM registers at 301, so that a generic ``ccm_base`` instance built +from the driver's ``ctr(aes)`` and the AES library's CBC-MAC (both at +300) cannot shadow it. + Request model -------------
@@ -117,6 +126,10 @@ The final status is 0 or a negative errno: ``-ENOMEM`` A bounce buffer could not be allocated. +The AES core reports an authentication failure with the same error code +as its other failures, so an AES-GCM or AES-CCM decryption that fails in +the device for another reason also returns ``-EBADMSG``. + Driver Architecture ===================
@@ -270,6 +283,11 @@ with ``-EINVAL``; it is not passed to a software implementation. Below a cap a large request can still fail with ``-ENOMEM`` when the bounce buffers cannot be allocated, in particular for ``GFP_ATOMIC`` requests. +- AES skcipher: 32 MiB of data. +- AES-GCM and AES-CCM: 1 MiB of associated data plus payload. AES-CCM + with a 10-byte tag, which the hardware does not support, is passed + whole to the generic implementation and has no such limit. + MAC and hash algorithms offload the one-shot ``.digest()`` only. The hardware's intermediate state is a non-portable internal checkpoint, and the keyed MACs cannot save it at all, so the incremental operations
@@ -280,3 +298,11 @@ whole message into one DMA buffer and rejects an input larger than the software transform has no such limit. For keyed algorithms the key is programmed into both the hardware and the software transform on ``.setkey()``. + +``cmac(aes)`` cannot use the Crypto API's automatic fallback, because +the generic cmac ``crypto_shash`` does not implement ``export_core``: the +driver allocates and keys a generic software transform itself (and sets +``CRYPTO_ALG_NO_FALLBACK``). It accepts virtual-address requests +(``CRYPTO_ALG_REQ_VIRT``): ``.digest()`` offloads them like scatterlist +requests, and the incremental operations forward them to the software +transform.
drivers/crypto/cmh/Kconfig +11 -0
@@ -13,6 +13,17 @@ config CRYPTO_DEV_CMH tristate "Rambus CryptoManager Hub (CMH) hardware crypto accelerator" depends on CRYPTO && OF && HAS_IOMEM && (64BIT || COMPILE_TEST) depends on !CPU_BIG_ENDIAN + select CRYPTO_SKCIPHER + select CRYPTO_AEAD + select CRYPTO_HASH + # The AES library computes the empty-input CCM tag; the drivers + # allocate ccm(aes) for the CCM requests the hardware does not + # support, and cmac(aes) for the incremental (.update) and + # request-state export/import CMAC operations. + select CRYPTO_LIB_AES + select CRYPTO_AES + select CRYPTO_CCM + select CRYPTO_CMAC help Driver for the Rambus CryptoManager Hub (CMH) hardware crypto accelerator. The device is accessed through a mailbox-based VCQ
drivers/crypto/cmh/Makefile +4 -1
@@ -14,7 +14,10 @@ cmh-y := \ cmh_dma.o \ cmh_sysfs.o \ cmh_sys.o \ - cmh_key.o + cmh_key.o \ + cmh_aes.o \ + cmh_aes_aead.o \ + cmh_aes_cmac.o ccflags-y += -I$(src)/include
drivers/crypto/cmh/cmh_aes.c new file +705 -0
705 lines not on this page · raw message
drivers/crypto/cmh/cmh_aes_aead.c new file +934 -0
934 lines not on this page · raw message
drivers/crypto/cmh/cmh_aes_cmac.c new file +459 -0
459 lines not on this page · raw message
drivers/crypto/cmh/cmh_main.c +27 -0
@@ -32,6 +32,7 @@#include "cmh_mqi.h" #include "cmh_txn.h" #include "cmh_rh.h" +#include "cmh_aes.h" #include "cmh_registers.h" #include "cmh_debugfs.h" #include "cmh_sysfs.h"
@@ -228,10 +229,32 @@ static int cmh_probe(struct platform_device *pdev)if (ret) goto err_rh_init; +/* Register AES skcipher algorithms */ + ret =cmh_aes_register (); +if (ret) + goto err_aes_register; + +/* Register AES AEAD algorithms (GCM, CCM) */ + ret =cmh_aes_aead_register (); +if (ret) + goto err_aes_aead_register; + +/* Register AES CMAC algorithm */ + ret =cmh_aes_cmac_register (); +if (ret) + goto err_aes_cmac_register; +platform_set_drvdata (pdev, dev);return 0 ; +err_aes_cmac_register: +cmh_aes_aead_unregister (); +err_aes_aead_register: +cmh_aes_unregister (); +err_aes_register: +cmh_tm_stop (); +cmh_rh_cleanup (cfg); err_rh_init:cmh_tm_cleanup (); err_tm_init:
@@ -256,6 +279,10 @@ static void cmh_remove(struct platform_device *pdev) cfg = &dev->config; +cmh_aes_cmac_unregister (); +cmh_aes_aead_unregister (); +cmh_aes_unregister (); +/* * Stop the TM producer before the RH state it consults is freed; * in-flight work completes through the RH until cmh_rh_cleanup().
drivers/crypto/cmh/include/cmh_aes.h new file +24 -0
@@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* Copyright (c) 2026 Cryptography Research, Inc. (CRI). +* CMH LKM -- AES Crypto API Drivers +* +* Registers AES algorithms with the Linux crypto subsystem: +* skcipher: ecb/cbc/ctr/xts(aes) +* aead: gcm/ccm(aes) +* shash: cmac(aes) +*/ + +#ifndef CMH_AES_H +#define CMH_AES_H + +int cmh_aes_register (void ); +void cmh_aes_unregister (void ); + +int cmh_aes_aead_register (void ); +void cmh_aes_aead_unregister (void ); + +int cmh_aes_cmac_register (void ); +void cmh_aes_cmac_unregister (void ); + +#endif /* CMH_AES_H */
drivers/crypto/cmh/include/cmh_aes_abi.h new file +98 -0
98 lines not on this page · raw message
drivers/crypto/cmh/include/cmh_vcq.h +2 -0
@@ -26,6 +26,7 @@#include <linux/bits.h> #include "cmh_sys_abi.h" +#include "cmh_aes_abi.h" /* VCQ Magic Numbers */
@@ -150,6 +151,7 @@ struct dma_scattergather_item {union hwc_cmd {struct vcq_hdr hdr;union sys_cmd sys; +union aes_cmd aes; };/**
Signature · 1 line
2.43.7
PATCH v8 5/5 MAINTAINERS: add Rambus CryptoManager Hub (CMH)
In reply to Alex OusherovitchAdd MAINTAINERS entry for the Rambus CryptoManager Hub (CMH) hardware crypto accelerator driver under drivers/crypto/cmh/.
--- MAINTAINERS | 13 +++++++++++++ 1 file changed, 13 insertions(+)
MAINTAINERS +13 -0
@@ -23305,6 +23305,19 @@ L: [email protected] S: Maintained F: drivers/net/wireless/ralink/ +RAMBUS CRYPTOMANAGER HUB (CMH) HARDWARE CRYPTO ACCELERATOR +M: Alex Ousherovitch <[email protected]> +M: Saravanakrishnan Krishnamoorthy <[email protected]> +R: Joel Wittenauer <[email protected]> +R: Thi Nguyen <[email protected]> +L: [email protected] +S: Maintained +F: Documentation/ABI/testing/debugfs-driver-cmh +F: Documentation/ABI/testing/sysfs-driver-cmh +F: Documentation/crypto/device_drivers/cmh.rst +F: Documentation/devicetree/bindings/crypto/rambus,cmh-v1030.yaml +F: drivers/crypto/cmh/ + RAMDISK RAM BLOCK DEVICE DRIVER M: Jens Axboe <[email protected]> S: Maintained
Signature · 1 line
2.43.7
[email protected]
AI reviewRe: [PATCH v8 1/5] dt-bindings: crypto: add Rambus CryptoManager Hub
In reply to Alex OusherovitchThank you for your contribution! Sashiko AI review found 1 potential issue to consider: - [Medium] dt-bindings: crypto: rambus,cmh-v1030: invalid unit suffix and $ref on rambus,slot-stride-bytes --
Thank you for your contribution! Sashiko AI review found 1 potential issue to consider:
- [Medium] dt-bindings: crypto: rambus,cmh-v1030: invalid unit suffix and $ref on rambus,slot-stride-bytes
--
commit fe48437ab6a40e215371f9ad1c5f69cf88124d19
Author: Alex Ousherovitch <[email protected]>
dt-bindings: crypto: add Rambus CryptoManager Hub
This commit adds the device tree binding schema for the Rambus CryptoManager Hub hardware crypto accelerator and registers the rambus vendor prefix.
Quoted 6 lines
Documentation/devicetree/bindings/crypto/rambus,cmh-v1030.yaml new file +0
-0@@ -0,0 +1,145 @@
[ ... ]
Documentation/devicetree/bindings/crypto/rambus,cmh-v1030.yaml line 121
Quoted 10 lines
Documentation/devicetree/bindings/crypto/rambus,cmh-v1030.yaml new file +10
-0+ rambus,slot-stride-bytes: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [512, 1024] + default: 512 + description: + Stride in bytes between consecutive VCQ ring slots for this + mailbox's command queue. Like rambus,num-slots this is a + per-board host-memory ring geometry, not derived from the + compatible. A slot must hold a complete command sequence, + which needs at least 512 bytes.
[Severity: Medium]
Does rambus,slot-stride-bytes cause make dt_binding_check to fail?
In dtschema (meta-schemas/vendor-props.yaml), the -bytes unit suffix is deprecated and disallowed on vendor properties, and properties using a standard unit suffix already have their uint32 type assigned by the core schema and must not specify $ref: /schemas/types.yaml#/definitions/uint32.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
[email protected]
AI reviewRe: [PATCH v8 2/5] crypto: cmh - add core platform driver
In reply to Alex OusherovitchThank you for your contribution! Sashiko AI review found 13 potential issues to consider: - [High] crypto: cmh - race in cmh_tm_try_cancel_command() during CMQ backoff - [High] crypto: cmh…
Thank you for your contribution! Sashiko AI review found 13 potential issues to consider:
- [High] crypto: cmh - race in cmh_tm_try_cancel_command() during CMQ backoff
- [High] crypto: cmh - unaborted sync timeouts and missing watchdog escalation
- [Medium] crypto: cmh - stale new_head overwrites last_head after cmh_rh_process_mbx()
- [Medium] crypto: cmh - missing abort_stall_ticks reset and immediate flush on stall
- [Medium] crypto: cmh - missing wedged check in cmh_rh_thread() restarts wedged mailbox
- [Medium] crypto: cmh - missing tm.dma_live updates and sync timeout return value
- [Medium] crypto: cmh - unconditional RESTART on empty queue in cmh_rh_process_mbx()
- [Medium] crypto: cmh - missing FLUSH reissue in cmh_rh_flush_poll()
- [Medium] crypto: cmh - missing IRQ clear and tail poke in cmh_mbx_flush_wait()
- [Medium] crypto: cmh - cmh_tm_quiesce() ignores pending mailbox recovery on suspend
- [Medium] crypto: cmh - unmapped SG source free and stale quiescent state on quarantine
- [Medium] crypto: cmh: missing IRQ clear and tail poke in cmh_mbx_flush_wait()
- [Low] crypto: cmh - missing vcqs_completed update on pre-error retirement
--
commit 9211e09c64c4bde6e31810b1851caacec422996b
Author: Alex Ousherovitch <[email protected]>
crypto: cmh - add core platform driver
This commit adds the core platform driver for the Rambus CryptoManager Hub (CMH), including mailbox queue setup, the transaction manager kthread, the response handler, DMA quarantine tracking, sysfs/debugfs interfaces, and driver documentation.
Quoted 5 lines
drivers/crypto/cmh/cmh_mqi.c new file +0
-0
[ ... ]
Quoted 18 lines
drivers/crypto/cmh/cmh_mqi.c new file +18
-0+static bool cmh_mbx_flush_wait (struct cmh_mbx_config *mbx) +{ +void __iomem *base = mbx->reg_base; +ktime_t deadline; + +if (!base) { + mbx->fenced = true; +return true; + } +if (MBX_STATUS_CODE (cmh_reg_read32 (base,R_MBX_STATUS )) == +MBX_STATUS_OFFLINE ) + goto unfenced; + +cmh_reg_write32 (MBX_COMMAND_FLUSH , base,R_MBX_COMMAND ); + deadline =ktime_add_us (ktime_get (),MBX_FLUSH_TIMEOUT_US ); +for (;;) { +if (cmh_mbx_flush_acked (base)) { + mbx->fenced = true;
drivers/crypto/cmh/cmh_mqi.c line 274
Quoted 10 lines
drivers/crypto/cmh/cmh_mqi.c new file +10
-0+return true; + } +if (ktime_after (ktime_get (), deadline)) +break ; +/* Cleared by an earlier command's acknowledgment: reissue. */ +if (!cmh_reg_read32 (base,R_MBX_COMMAND )) +cmh_reg_write32 (MBX_COMMAND_FLUSH , base, +R_MBX_COMMAND ); +usleep_range (MBX_FLUSH_POLL_US ,2 *MBX_FLUSH_POLL_US ); + }
[Severity: Medium]
Does cmh_mbx_flush_wait() need to W1C-clear R_MBX_INTERRUPT and poke R_MBX_QUEUE_TAIL when issuing MBX_COMMAND_FLUSH, the way cmh_rh_issue_flush() does?
At probe, cmh_mqi_init() calls cmh_mbx_flush_wait() before cmh_mbx_setup_one() clears stale interrupt bits, and at teardown it runs after cmh_rh_cleanup() has stopped the response handler. If a mailbox was left in ERROR state with MBX_ERROR_IRQ asserted in R_MBX_INTERRUPT, writing R_MBX_COMMAND alone may not generate a new SIC interrupt edge to wake the eSW from WFI, causing probe to fail with -EBUSY or teardown to treat the mailbox as unfenced and leak its DMA buffers.
[ ... ]
Quoted 5 lines
drivers/crypto/cmh/cmh_rh.c new file +0
-0
[ ... ]
Quoted 11 lines
drivers/crypto/cmh/cmh_rh.c new file +11
-0+static void cmh_rh_flush_poll (u32 mbx_idx,bool tick) +{ +void __iomem *base = rh.cfg->mailboxes[mbx_idx].reg_base; +struct cmh_rh_mbx *m = &rh.mbx[mbx_idx]; + +if (cmh_rh_flush_acked (base)) { + m->flush_pending = false; + m->flush_count =0 ; +cmh_rh_drain_mbx (mbx_idx, -ECANCELED , false); +cmh_tm_mbx_admit (mbx_idx, true); +return ;
drivers/crypto/cmh/cmh_rh.c line 280
Quoted 10 lines
drivers/crypto/cmh/cmh_rh.c new file +10
-0+ } + +if (!tick) +return ; + +if (++m->flush_ticks <=CMH_RH_RESTART_MAX_RETRIES ) { +/* Re-poke TAIL in case the eSW missed the interrupt. */ +cmh_rh_poke_tail (base); +return ; + }
[Severity: Medium]
If an earlier command's acknowledgment clears R_MBX_COMMAND to 0 (MBX_COMMAND_RUN) before the eSW processes MBX_COMMAND_FLUSH, doesn't cmh_rh_flush_poll() poke R_MBX_QUEUE_TAIL for five ticks without reissuing MBX_COMMAND_FLUSH?
Unlike cmh_mbx_flush_wait(), which checks !cmh_reg_read32(base, R_MBX_COMMAND) and rewrites MBX_COMMAND_FLUSH, cmh_rh_flush_poll() leaves R_MBX_COMMAND at MBX_COMMAND_RUN while poking TAIL. That wakes the eSW to execute remaining VCQs in the ring, including surviving slots of a failed multi-VCQ transaction whose DMA buffers were already freed in cmh_rh_process_mbx().
[ ... ]
Quoted 9 lines
drivers/crypto/cmh/cmh_rh.c new file +9
-0+/* +* HEAD was sampled before the status: the eSW may have +* completed more VCQs and failed a later one in between. It +* does not move HEAD while stopped in ERROR, so re-read it now +* to pair the error with the VCQ it belongs to. +*/ + new_head =cmh_reg_read32 (base,R_MBX_QUEUE_HEAD ); + + error =cmh_rh_vcq_errno (mbx_idx, base, status);
[ ... ]
Quoted 4 lines
drivers/crypto/cmh/cmh_rh.c new file +4
-0+/* First: retire transactions completed before the error */ +while ((txn =cmh_tm_peek_transaction (mbx_idx)) !=NULL ) { +if ((s32)(new_head - txn->last_vcq_id) <=0 ) +break ;
drivers/crypto/cmh/cmh_rh.c line 624
Quoted 10 lines
drivers/crypto/cmh/cmh_rh.c new file +10
-0+ txn =cmh_tm_pop_transaction (mbx_idx); +if (!txn) +break ; +dev_dbg (cmh_dev (), +"rh: mbx[%u] pre-error complete vcq=%u..%u\n" , + mbx_idx, txn->first_vcq_id, + txn->last_vcq_id); +cmh_txn_finish (txn,0 , false); +cmh_tm_txq_completion_notify (); + }
[Severity: Low]
Should this pre-error retirement loop call cmh_rh_stat_add_completed() like the normal completion loop below does, so debugfs vcqs_completed does not undercount transactions completed before an error?
[ ... ]
Quoted 15 lines
drivers/crypto/cmh/cmh_rh.c new file +15
-0+/* Now pop and fail the transaction that actually errored */ + txn =cmh_tm_pop_transaction (mbx_idx); +if (txn) { +dev_dbg (cmh_dev (),"rh: mbx[%u] error-complete vcq=%u..%u\n" , + mbx_idx, txn->first_vcq_id, + txn->last_vcq_id); +cmh_txn_finish (txn, error, false); +cmh_tm_txq_completion_notify (); + }else { +u32 head_reg, tail_reg; + + head_reg =cmh_reg_read32 (base,R_MBX_QUEUE_HEAD ); + tail_reg =cmh_reg_read32 (base,R_MBX_QUEUE_TAIL ); + dev_warn_ratelimited(cmh_dev(), + "rh: mbx[%u] ERROR with empty txn queue (orphaned) status=0x%08x head=%u tail=%u core=%u ecode=%u cmd_idx=%u\n",
drivers/crypto/cmh/cmh_rh.c line 691
Quoted 10 lines
drivers/crypto/cmh/cmh_rh.c new file +10
-0+ mbx_idx, status, + head_reg, tail_reg, +MBX_STATUS_CORE_ID (status), +MBX_STATUS_ERROR_CODE (status), + MBX_STATUS_CMD_INDEX(status)); + } +cmh_rh_stat_inc_errors (mbx_idx); + +cmh_reg_write32 (MBX_IRQ_MASK , base,R_MBX_INTERRUPT ); +cmh_reg_write32 (MBX_COMMAND_RESTART , base,R_MBX_COMMAND );
[Severity: Medium]
When cmh_tm_pop_transaction() returns NULL here (for example after an abort lands just as the last in-flight VCQ completes, or via debugfs inject_abort), can issuing MBX_COMMAND_RESTART skip a newly submitted VCQ?
Mailbox admission is not closed, and submit_vcq() on the TM kthread does not take rh_process_lock:
CPU0 (cmh_rh_process_mbx) CPU1 (cmh_tm_thread)cmh_tm_pop_transaction() -> NULL
submit_vcq()
tail = read(R_MBX_QUEUE_TAIL) write VCQ to slot[tail] list_add_tail(&txn->list, &txq->head) write(tail + 1, R_MBX_QUEUE_TAIL)write(MBX_COMMAND_RESTART, ...)cmh_rh_poke_tail()
/* eSW advances HEAD + 1,
skipping slot[tail] */
On the next poll, cmh_rh_process_mbx() sees new_head > txn->last_vcq_id and completes the unexecuted transaction with error = 0, returning unwritten output buffers to the caller.
[ ... ]
Quoted 14 lines
drivers/crypto/cmh/cmh_rh.c new file +14
-0+static irqreturn_t cmh_rh_thread (int irq,void *data) +{ +struct cmh_config *cfg = data; +u32 i; +bool recheck; + + do { + recheck = false; + + for (i = 0; i < cfg->mbx_count; i++) { + u32 new_head, irq_bits; + + if (!READ_ONCE(rh.mbx[i].pending)) + continue;
[ ... ]
Quoted 11 lines
drivers/crypto/cmh/cmh_rh.c new file +11
-0+WRITE_ONCE (rh.mbx[i].pending, false); + irq_bits = (u32 )atomic_xchg (&rh.mbx[i].irq_bits,0 ); + +spin_lock_bh (&rh_process_lock); +if (rh.mbx[i].flush_pending) { +cmh_rh_flush_poll (i, false); +spin_unlock_bh (&rh_process_lock); +continue ; + } + new_head =cmh_reg_read32 (cfg->mailboxes[i].reg_base, +R_MBX_QUEUE_HEAD );
drivers/crypto/cmh/cmh_rh.c line 822
Quoted 10 lines
drivers/crypto/cmh/cmh_rh.c new file +10
-0+ +if (new_head == rh.mbx[i].last_head && !irq_bits) { +spin_unlock_bh (&rh_process_lock); +continue ; + } + +cmh_rh_process_mbx (i, new_head, irq_bits); + rh.mbx[i].last_head = new_head; +spin_unlock_bh (&rh_process_lock); + }
[Severity: Medium]
What happens if a wedged mailbox raises an interrupt?
When cmh_rh_flush_poll() marks a mailbox wedged, it clears flush_pending but leaves R_MBX_INTERRUPT_MASK enabled. Unlike the second loop in cmh_rh_thread() and cmh_rh_watchdog_fn(), this first loop (as well as cmh_rh_process_mbx() and cmh_rh_abort_mbx()) does not check rh.mbx[i].wedged. A delayed MBX_ERROR_IRQ or a debugfs inject_abort write will therefore run cmh_rh_process_mbx() on the wedged mailbox and issue MBX_COMMAND_RESTART, causing the eSW to advance HEAD and execute VCQ slots whose transactions were already drained with -ETIMEDOUT.
[ ... ]
drivers/crypto/cmh/cmh_rh.c line 888
Quoted 6 lines
drivers/crypto/cmh/cmh_rh.c new file +6
-0+if (new_head != rh.mbx[i].last_head || poll_irq_bits) { +cmh_rh_process_mbx (i, new_head, poll_irq_bits); + rh.mbx[i].last_head = new_head; + } +spin_unlock_bh (&rh_process_lock); + }
[Severity: Medium]
Does assigning rh.mbx[i].last_head = new_head in cmh_rh_thread() and cmh_rh_watchdog_fn() overwrite last_head with a stale value when cmh_rh_process_mbx() re-reads R_MBX_QUEUE_HEAD on an error?
In cmh_rh_process_mbx(), when MBX_STATUS_ERROR is observed, new_head is re-read into the local by-value parameter because the eSW may have completed more VCQs between the caller's initial R_MBX_QUEUE_HEAD read and the status check. cmh_rh_process_mbx() retires those pre-error transactions and sets restart_head to the updated head, but all three callers then overwrite rh.mbx[i].last_head with their old pre-status new_head. The next poll then falsely sees new_head != last_head, re-enters cmh_rh_process_mbx(), and resets abort_stall_ticks prematurely.
[ ... ]
Quoted 38 lines
drivers/crypto/cmh/cmh_rh.c new file +38
-0+if (new_head != rh.mbx[i].last_head || irq_bits) { +if (new_head != rh.mbx[i].last_head) +dev_dbg_ratelimited (cmh_dev (), +"rh: watchdog: mbx[%u] head %u->%u (missed IRQ recovery)\n" , + i, rh.mbx[i].last_head, + new_head); +cmh_rh_process_mbx (i, new_head, irq_bits); + rh.mbx[i].last_head = new_head; + rh.mbx[i].abort_stall_ticks =0 ; + } + +if (!READ_ONCE (rh.mbx[i].wedged) && + !READ_ONCE (rh.mbx[i].restart_pending) && + !rh.mbx[i].flush_pending) { +struct transaction_obj *head_txn; + + head_txn =cmh_tm_peek_transaction (i); +if (head_txn && +atomic_read (&head_txn->state) ==TXN_TIMED_OUT ) { +unsigned int stall_max; +void __iomem *base = + rh.cfg->mailboxes[i].reg_base; + + rh.mbx[i].abort_stall_ticks++; + +if (rh.mbx[i].abort_stall_ticks ==1 ) { +dev_warn (cmh_dev (), +"rh: watchdog: mbx[%u] head txn timed out, issuing ABORT\n" , + i); +cmh_reg_write32 (MBX_COMMAND_ABORT , + base, +R_MBX_COMMAND ); + } + + stall_max =DIV_ROUND_UP (CMH_RH_ABORT_STALL_MS , +max (watchdog_ms, +CMH_RH_WATCHDOG_MS_MIN )); + if (rh.mbx[i].abort_stall_ticks >=
drivers/crypto/cmh/cmh_rh.c line 1078
Quoted 10 lines
drivers/crypto/cmh/cmh_rh.c new file +10
-0+ stall_max) { +dev_err (cmh_dev (), +"rh: watchdog: mbx[%u] abort stall (%u ticks) -- FLUSH\n" , + i, rh.mbx[i].abort_stall_ticks); +cmh_rh_issue_flush (i); + } + }else { + rh.mbx[i].abort_stall_ticks =0 ; + } + }
[Severity: Medium]
Doesn't cmh_rh_thread() need to reset rh.mbx[i].abort_stall_ticks = 0 when it advances last_head or completes error recovery?
When the watchdog issues MBX_COMMAND_ABORT on tick 1 and cmh_rh_thread() processes the resulting MBX_ERROR_IRQ (or a normal completion) before the next watchdog tick, cmh_rh_thread() updates rh.mbx[i].last_head without resetting abort_stall_ticks. On the next watchdog tick, new_head == last_head, so if the next transaction at the head of the queue also timed out while waiting behind the first, abort_stall_ticks increments from 1 to 2, skipping MBX_COMMAND_ABORT for the new head transaction and counting straight toward a full mailbox FLUSH.
Also, when watchdog_ms >= CMH_RH_ABORT_STALL_MS, stall_max is 1, so tick 1 writes MBX_COMMAND_ABORT and immediately calls cmh_rh_issue_flush() in the same tick without giving the eSW any time to process the abort.
Quoted 5 lines
drivers/crypto/cmh/cmh_txn.c new file +0
-0
[ ... ]
Quoted 13 lines
drivers/crypto/cmh/cmh_txn.c new file +13
-0+static void cmh_req_dma_quarantine (struct cmh_req_dma *rd) +{ +unsigned int i; + +if (rd->sgm) +cmh_dma_quarantine_track (NULL ,0 ,0 ,DMA_NONE , rd->sgm); +for (i =0 ; i < rd->n; i++) { +struct cmh_req_dma_ent *e = &rd->ent[i]; + +if (e->mapped) +cmh_dma_quarantine_track (e->buf, e->dma, e->len, + e->dir,NULL ); +else if (e->sg_src && rd->sgm)
drivers/crypto/cmh/cmh_txn.c line 555
Quoted 10 lines
drivers/crypto/cmh/cmh_txn.c new file +10
-0+cmh_dma_quarantine_track (e->buf,0 ,0 ,DMA_NONE , +NULL ); + else if (e->sensitive) + kfree_sensitive(e->buf); + else + kfree(e->buf); + } + rd->n =0 ; + rd->sgm =NULL ; +}
[Severity: Medium]
In cmh_req_dma_quarantine(), what happens if the GFP_ATOMIC allocation in cmh_dma_quarantine_track() fails for rd->sgm, but succeeds for a subsequent e->sg_src entry?
rd->sgm is leaked with its source buffers still DMA-mapped, while the e->sg_src buffer is tracked with dir == DMA_NONE. When cmh_dma_quarantine_release(true) runs at module unload, cmh_dma_orphan_reap() sees dir == DMA_NONE and frees e->buf with kfree_sensitive() without cmh_dma_free_sg(rd->sgm) ever having unmapped its active streaming DMA mapping.
In addition, tm.dma_live is never reset in cmh_tm_init() or in cmh_tm_cleanup() after cmh_mqi_settle_all() succeeds.
[ ... ]
Quoted 25 lines
drivers/crypto/cmh/cmh_txn.c new file +25
-0+static void cmh_tm_requeue_wait (struct command_msg *msg) +{ +int gen =atomic_read (&txq_completion_gen); +unsigned long flags, tmo; + +spin_lock_irqsave (&tm.cmq_lock, flags); +list_add (&msg->list, &tm.cmq); + cmq_depth++; +spin_unlock_irqrestore (&tm.cmq_lock, flags); + + tmo =usecs_to_jiffies (CMH_TM_BACKOFF_MAX_US ); +wait_event_interruptible_timeout (tm.cmq_waitq, +kthread_should_stop () || +atomic_read (&txq_completion_gen) != gen, + tmo ?:1 ); +cmh_stat_inc_tm_backoff (); +} + +static int cmh_tm_thread (void *data) +{ +struct command_msg *msg; +unsigned long flags; +int mbx_idx, ret; + +while (!kthread_should_stop ()) {
[ ... ]
Quoted 7 lines
drivers/crypto/cmh/cmh_txn.c new file +7
-0+ msg = list_first_entry(&tm.cmq, struct command_msg, list); +list_del_init (&msg->list); + cmq_depth--; +spin_unlock_irqrestore (&tm.cmq_lock, flags); + +/* Select a mailbox: pinned or round-robin */ + mbx_idx =resolve_mbx (msg);
[ ... ]
drivers/crypto/cmh/cmh_txn.c line 1446
Quoted 5 lines
drivers/crypto/cmh/cmh_txn.c new file +5
-0+if (mbx_idx <0 ) { +/* Rings full or mailboxes recovering -- retry. */ +cmh_tm_requeue_wait (msg); +continue ; + }
[Severity: High]
Can cmh_tm_try_cancel_command() miss a command that is transiently off tm.cmq while cmh_tm_thread() checks resolve_mbx() or submit_vcq()?
CPU0 (cmh_tm_thread) CPU1 (cmh_tm_submit_sync_tmo)spin_lock_irqsave(&tm.cmq_lock)list_del_init(&msg->list)spin_unlock_irqrestore(&tm.cmq_lock)resolve_mbx(msg) -> -EAGAIN
/* wait_for_completion_timeout() expires */
cmh_tm_try_cancel_command(msg)
spin_lock_irqsave(&tm.cmq_lock)
!list_empty(&msg->list) -> false
spin_unlock_irqrestore(&tm.cmq_lock)cmh_tm_requeue_wait(msg)
list_add(&msg->list, &tm.cmq)
Because msg->actual_mbx is still -1, cmh_tm_submit_sync_tmo() issues no abort, and if the mailboxes stay busy or closed across the 5-second wait, it returns -ETIMEDOUT while msg is still queued in tm.cmq. cmh_tm_thread() can then dispatch the VCQ to hardware after the caller has unmapped and freed its input DMA buffers (DMA use-after-free). In cmh_tm_submit_sync_noabort(), this same race returns -EINPROGRESS instead of -EAGAIN for a command that was never dispatched.
[ ... ]
Quoted 15 lines
drivers/crypto/cmh/cmh_txn.c new file +15
-0+int cmh_tm_quiesce (void ) +{ +unsigned long deadline; +bool drained; +u32 i; + +cmh_tm_stop_and_drain_cmq (); + +/* Wait for in-flight TXQ transactions to complete via RH */ +if (!tm.txqs) +return 0 ; + + deadline = jiffies +msecs_to_jiffies (drain_timeout_ms); + do { + drained = true;
drivers/crypto/cmh/cmh_txn.c line 1745
Quoted 10 lines
drivers/crypto/cmh/cmh_txn.c new file +10
-0+for (i =0 ; i < tm.cfg->mbx_count; i++) { +if (READ_ONCE (tm.txqs[i].depth)) { + drained = false; +break ; + } + } +if (drained) +return 0 ; +usleep_range (1000 ,2000 ); + }while (time_before (jiffies, deadline));
[Severity: Medium]
Can cmh_tm_quiesce() return 0 while a mailbox FLUSH or RESTART recovery command is still in flight on the device?
In cmh_rh_process_mbx(), the failed transaction is popped from txq before cmh_rh_issue_flush() or MBX_COMMAND_RESTART is issued. If no other transactions were queued on that mailbox, tm.txqs[i].depth is already 0, so cmh_tm_quiesce() returns 0 immediately and cmh_rh_suspend() stops the watchdog and masks hardware interrupts before the eSW has acknowledged the recovery command or reopened the closed mailbox.
Also, debugfs handlers cmh_rh_force_drain_mbx() and cmh_rh_abort_mbx() do not check rh.active, so they can issue MMIO commands and close mailboxes while the device is suspended.
[ ... ]
Quoted 65 lines
drivers/crypto/cmh/cmh_txn.c new file +65
-0+ left =wait_for_completion_timeout (&sync->done, timeout_hz); +if (!left) { +dev_err (cmh_dev (), +"tm: submit_sync timeout (%lums) cmd=0x%08x\n" , + timeout_hz *1000 /HZ , msg->command_id); +if (cmh_tm_try_cancel_command (msg)) { +/* +* Msg was still queued -- TM never saw it. +* Drop the callback ref (no txn will fire it) +* and free msg directly (sole owner). +*/ +cmh_sync_ctx_put (sync);/* no txn -> drop cb ref */ +cmh_sync_ctx_put (sync);/* drop waiter ref */ +command_msg_put (msg);/* matches refcount_set(2) */ +command_msg_put (msg); + }else { +/* +* TM has dequeued msg and the VCQ is in-flight. +* Issue MBX_COMMAND_ABORT to force-stop the VCQ; +* the RH will fire MBX_ERROR_IRQ, complete the +* transaction with -EIO, and issue RESTART. +* +* cmh_rh_abort_mbx() serialises the write under +* rh_process_lock, preventing clobber of a +* concurrent RESTART/FLUSH from the watchdog. +*/ +s32 abrt_mbx =READ_ONCE (msg->actual_mbx); + +/* +* Only ABORT if our VCQ is the one currently at the +* mailbox HEAD. ABORT stops whatever executes at +* HEAD, so aborting while a different (older, +* possibly long-running) transaction is at HEAD would +* kill an unrelated request. If ours is queued behind +* it, the HW has not started ours yet -- leave it to +* the completion wait / watchdog rather than abort +* someone else. +*/ +if (abrt_mbx >=0 && + (u32 )abrt_mbx < tm.cfg->mbx_count && +cmh_rh_abort_mbx ((u32 )abrt_mbx, +READ_ONCE (msg->first_vcq_id))) +dev_warn (cmh_dev (), +"tm: aborted mbx[%d] cmd=0x%08x\n" , + abrt_mbx, msg->command_id); + +/* +* Wait for the RH completion (ABORT triggers +* MBX_ERROR_IRQ within microseconds). Fixed +* 5 s ceiling -- not configurable because if +* ABORT doesn't complete in this window the +* HW is wedged and more waiting won't help. +*/ + left =wait_for_completion_timeout (&sync->done, +5 *HZ ); +if (!left) { +/* +* ABORT did not complete within 5 s. Unlike +* cmh_tm_submit_sync_noabort, this path sets no +* orphan_cb, so the caller frees its DMA buffers +* on the -ETIMEDOUT below. This HW exposes no +* DMA-stop primitive, so where an ABORT cannot be +* issued or observed to complete the driver has +* no positive confirmation the engine has +* finished with those buffers.
drivers/crypto/cmh/cmh_txn.c line 2091
Quoted 10 lines
drivers/crypto/cmh/cmh_txn.c new file +10
-0+*/ +dev_err (cmh_dev (), +"tm: abort timeout (5s) cmd=0x%08x - HW wedged\n" , + msg->command_id); + } +cmh_sync_ctx_put (sync);/* drop waiter ref */ +command_msg_put (msg);/* drop waiter ref on msg */ + } +return -ETIMEDOUT ; + }
[Severity: High]
What happens when a synchronous submission in cmh_tm_submit_sync_tmo() times out while queued behind an older transaction at R_MBX_QUEUE_HEAD, or after HEAD has advanced to a later slot of a multi-VCQ submission?
cmh_rh_abort_mbx() only issues MBX_COMMAND_ABORT when R_MBX_QUEUE_HEAD equals first_vcq_id. Furthermore, neither cmh_tm_submit_sync_tmo() nor cmh_tm_submit_sync_noabort() sets msg->timeout_jiffies or transitions txn->state to TXN_TIMED_OUT, so the abort-stall detector in cmh_rh_watchdog_fn() (which checks atomic_read(&head_txn->state) == TXN_TIMED_OUT) never triggers for synchronous transactions. If the VCQ does not finish within 5 seconds, cmh_tm_submit_sync_tmo() returns -ETIMEDOUT while the VCQ remains active in the ring (allowing DMA access to input buffers the caller unmaps and frees on return), and a stalled synchronous VCQ at HEAD is never aborted or flushed by the watchdog, wedging the mailbox and blocking suspend with -EBUSY.
[Severity: Medium]
Does cmh_tm_dma_quiescent() stay accurate when synchronous operations time out or when a mailbox wedges with an empty transaction queue?
cmh_tm_dma_quiescent() only checks !READ_ONCE(tm.dma_live), which is only set in cmh_txn_quarantine() when draining non-empty txq entries. It is never set when the 5-second abort wait in cmh_tm_submit_sync_tmo() expires (!left), when buffers are quarantined via cmh_dma_quarantine_add() (from cmh_dma_free_out(), cmh_tm_dma_quarantine_buf(), or cmh_dma_orphan_free()), or when cmh_rh_flush_poll() marks a mailbox wedged after cmh_rh_process_mbx() already popped the last transaction from txq.
Conversely, cmh_tm_submit_sync_tmo() returns -ETIMEDOUT even when cmh_tm_try_cancel_command(msg) cancelled the command before dispatch or when the 5-second post-abort wait succeeded (left > 0), causing callers of cmh_dma_free_out() to quarantine output buffers that the device is known not to touch.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=2
[email protected]
AI reviewRe: [PATCH v8 4/5] crypto: cmh - add AES skcipher/aead/cmac
In reply to Alex OusherovitchThank you for your contribution! Sashiko AI review found 2 potential issues to consider: - [Critical] crypto: cmh: stack overflow in ahash_request_zero() via missing tfm->fb - [Medium] crypto: cmh…
Thank you for your contribution! Sashiko AI review found 2 potential issues to consider:
- [Critical] crypto: cmh: stack overflow in ahash_request_zero() via missing tfm->fb
- [Medium] crypto: cmh: missing CRYPTO_ALG_ASYNC mask in cmh_aes_aead_init_tfm()
--
commit 89559a30a0ea6b4fc4382fe41b13de31385e0958
Author: Alex Ousherovitch <[email protected]>
crypto: cmh - add AES skcipher/aead/cmac
This commit registers AES skcipher (ECB, CBC, CTR, XTS), AEAD (GCM, CCM), and ahash (CMAC) algorithms on the CMH AES core, along with the AES core ABI definitions.
Quoted 5 lines
drivers/crypto/cmh/cmh_aes_aead.c new file +0
-0
[ ... ]
Quoted 4 lines
drivers/crypto/cmh/cmh_aes_aead.c new file +4
-0+static int cmh_aes_aead_init_tfm (struct crypto_aead *tfm) +{ +struct cmh_aes_aead_tfm_ctx *tctx =crypto_aead_ctx (tfm); +const struct cmh_aes_aead_info *info =cmh_aes_aead_get_info (tfm);
drivers/crypto/cmh/cmh_aes_aead.c line 280
Quoted 10 lines
drivers/crypto/cmh/cmh_aes_aead.c new file +10
-0+ +memset (tctx,0 ,sizeof (*tctx)); + tctx->authsize = info->maxauthsize; + +if (info->type ==CMH_AES_AEAD_CCM ) { +struct crypto_aead *fb; + + tctx->ccm = true; + fb =crypto_alloc_aead ("ccm(aes)" ,0 , +CRYPTO_ALG_NEED_FALLBACK );
[Severity: Medium]
Does this fallback allocation need CRYPTO_ALG_ASYNC in the mask so that ccm(aes) does not wrap rambus-cmh-ctr-aes?
On architectures where ccm-aes-lib is not registered (such as arm64 and arm), allocating ccm(aes) instantiates the ccm template via crypto_ccm_create_common(), which grabs ctr(aes) using the passed mask. Because cmh_aes_register() has already registered rambus-cmh-ctr-aes at priority 300, the fallback ends up running CTR on the CMH hardware via bounce buffers and rejecting requests over 32 MiB with -EINVAL, rather than using a software implementation with no size limit as documented.
Quoted 5 lines
drivers/crypto/cmh/cmh_aes_cmac.c new file +0
-0
[ ... ]
Quoted 18 lines
drivers/crypto/cmh/cmh_aes_cmac.c new file +18
-0+static int cmh_aes_cmac_init_tfm (struct crypto_ahash *tfm) +{ +struct cmh_aes_cmac_tfm_ctx *tctx =crypto_ahash_ctx (tfm); +struct crypto_ahash *fb; + + tctx->key.mode =CMH_KEY_NONE ; + +/* +* The generic cmac(aes) shash has no export_core, so the crypto +* core cannot wrap it as crypto_ahash_fb(). Allocate it here +* instead; masking out CRYPTO_ALG_ASYNC excludes this (async) +* driver so the allocator picks the generic, synchronous transform, +* and its request is embedded after the reqctx. +*/ + fb =crypto_alloc_ahash (crypto_ahash_alg_name (tfm),0 , +CRYPTO_ALG_ASYNC ); +if (IS_ERR (fb)) +return PTR_ERR (fb);
drivers/crypto/cmh/cmh_aes_cmac.c line 372
Quoted 10 lines
drivers/crypto/cmh/cmh_aes_cmac.c new file +10
-0+ tctx->fb = fb; + +crypto_ahash_set_reqsize (tfm, +sizeof (struct cmh_aes_cmac_reqctx ) + +crypto_tfm_ctx_alignment () + +sizeof (struct ahash_request ) + +crypto_ahash_reqsize (fb)); +crypto_ahash_set_statesize (tfm,crypto_ahash_statesize (fb)); +return 0 ; +}
[Severity: Critical]
Can leaving crypto_ahash_tfm(tfm)->fb pointing to the async CMH transform overflow the kernel stack when a caller uses crypto_hash_digest() or HASH_FBREQ_ON_STACK()?
Because cmh_aes_cmac_alg sets CRYPTO_ALG_NO_FALLBACK, crypto_create_tfm_node() leaves tfm->fb pointing to tfm itself, while cmh_aes_cmac_init_tfm() sets tfm's reqsize to over 800 bytes above MAX_SYNC_HASH_REQSIZE:
crypto/ahash.c:crypto_hash_digest() {
HASH_REQUEST_ON_STACK(req, crypto_ahash_fb(tfm));
int err;
ahash_request_set_callback(req, 0, NULL, NULL);
ahash_request_set_virt(req, data, out, len);
err = crypto_ahash_digest(req);
ahash_request_zero(req);
return err;
}HASH_REQUEST_ON_STACK() reserves only sizeof(struct ahash_request) + MAX_SYNC_HASH_REQSIZE bytes on the stack and binds req to crypto_ahash_fb(tfm) (still the CMH tfm). crypto_ahash_digest() then returns -EAGAIN because an on-stack request is used with an async transform, and ahash_request_zero() zeroes sizeof(*req) + crypto_ahash_reqsize(tfm) bytes, writing over 800 bytes past the stack buffer.
Pointing crypto_ahash_tfm(tfm)->fb at crypto_ahash_tfm(fb) (and restoring it before freeing fb in cmh_aes_cmac_exit_tfm()) would direct stack requests to the synchronous fallback transform.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=4