Re: [PATCH v1 02/11] soc: qcom: add crypto_virt backend for virtio-blk inline crypto
From: Linlin Zhang <hidden>
Date: 2026-09-01 09:40:10
Also in:
linux-arm-msm, linux-crypto, linux-devicetree, linux-scsi, lkml, virtualization
On 8/31/2026 2:56 PM, Krzysztof Kozlowski wrote:
On 27/08/2026 18:07, Linlin Zhang wrote:quoted
From: linlzhan <redacted> In a Qualcomm GVM environment the ICE hardware is controlled by theWhat is GVM?
GVM means Guest Virtual Machine. This is designed for the virtualization platform.
quoted
host, GVM has no direct access to it. So, key operation in GVM is done through SCM calls rather than direct register access. In this way the access to ICE registers are offloaded to Trust Zone. Add QCOM_CRYPTO_VIRT, which implements struct virtblk_crypto_variant_ops for the virtio_blk_crypto_ext dispatch layer. It maps keyslot program/evict to qcom_scm_ice_set_key() and qcom_scm_ice_invalidate_key(), and software-secret derivation to qcom_scm_derive_sw_secret(). Signed-off-by: linlzhan <redacted> --- drivers/soc/qcom/Kconfig | 12 +++++ drivers/soc/qcom/Makefile | 1 + drivers/soc/qcom/crypto_virt.c | 89 ++++++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+) create mode 100644 drivers/soc/qcom/crypto_virt.cdiff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 2b524154d9fb..6c632d114d45 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig@@ -298,6 +298,18 @@ config QCOM_INLINE_CRYPTO_ENGINE tristate select QCOM_SCM +config QCOM_CRYPTO_VIRT + tristate "Qualcomm Technologies, Inc. Crypto Virt driver" + depends on VIRTBLK_CRYPTO_VIRTUALIZATION + depends on QCOM_SCM + default VIRTBLK_CRYPTO_VIRTUALIZATION if ARCH_QCOM + help + GVM-side hardware-wrapped-key SCM operations exposed to + virtio_blk's inline crypto layer: per-slot key programming and + eviction, and key derive/generate/prepare/import. + Say Y here to compile the driver as a part of kernel or M to compile + as a module. + config QCOM_KRYO_L2_ACCESSORS bool depends on ARM64diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index 798643be3590..6d4b7546d1fb 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile@@ -39,5 +39,6 @@ obj-$(CONFIG_QCOM_KRYO_L2_ACCESSORS) += kryo-l2-accessors.o obj-$(CONFIG_QCOM_ICC_BWMON) += icc-bwmon.o qcom_ice-objs += ice.o obj-$(CONFIG_QCOM_INLINE_CRYPTO_ENGINE) += qcom_ice.o +obj-$(CONFIG_QCOM_CRYPTO_VIRT) += crypto_virt.o obj-$(CONFIG_QCOM_PBS) += qcom-pbs.o obj-$(CONFIG_QCOM_UBWC_CONFIG) += ubwc_config.odiff --git a/drivers/soc/qcom/crypto_virt.c b/drivers/soc/qcom/crypto_virt.c new file mode 100644 index 000000000000..4ee2a36af6c1 --- /dev/null +++ b/drivers/soc/qcom/crypto_virt.c@@ -0,0 +1,89 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include <linux/module.h> +#include <linux/types.h> +#include <linux/blk-crypto.h> +#include <linux/virtio_blk_crypto_ext.h> +#include <linux/firmware/qcom/qcom_scm.h> + +static int crypto_virt_program_key(const struct blk_crypto_key *key, + unsigned int slot) +{ + u32 dus_512_units; + int ret; + + if (!key || !key->size) { + pr_err("%s: invalid key\n", __func__); + return -EINVAL; + } + + /* Only AES-256-XTS has been tested so far. */ + if (key->crypto_cfg.crypto_mode != + BLK_ENCRYPTION_MODE_AES_256_XTS) { + pr_err_ratelimited("Unsupported crypto mode: %d\n", + key->crypto_cfg.crypto_mode); + return -EINVAL; + } + + /* qcom_scm_ice_set_key()'s data_unit_size is expressed in 512-byte units */ + dus_512_units = key->crypto_cfg.data_unit_size / 512; + + ret = qcom_scm_ice_set_key(slot, key->bytes, key->size, + QCOM_SCM_ICE_CIPHER_AES_256_XTS, dus_512_units); + if (ret) + pr_err("%s: slot=%u ret=%d\n", __func__, slot, ret); + + return ret; +} + +static int crypto_virt_invalidate_key(unsigned int slot) +{ + int ret; + + ret = qcom_scm_ice_invalidate_key(slot); + if (ret) + pr_err("%s: slot=%u ret=%d\n", __func__, slot, ret); + + return ret; +} + +static int crypto_virt_derive_sw_secret_key(const u8 *eph_key, size_t eph_key_size, + u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE]) +{ + int ret; + + ret = qcom_scm_derive_sw_secret(eph_key, eph_key_size, + sw_secret, BLK_CRYPTO_SW_SECRET_SIZE); + if (ret == -EIO || ret == -EINVAL) + ret = -EBADMSG; /* probably invalid key */ + + if (ret) + pr_err("%s: ret=%d\n", __func__, ret); + + return ret; +} + +static struct virtblk_crypto_variant_ops virtblk_crypto_qcom_vops = {Why is a crypto-handling code in drivers/soc/?
This driver is a Qualcomm vendor-specific driver, plays the similar role in the guest, like the ice driver in the host. so I place it in drivers/soc/.
quoted
+ .owner = THIS_MODULE, + .program_key = crypto_virt_program_key, + .evict_key = crypto_virt_invalidate_key, + .derive_sw_secret_key = crypto_virt_derive_sw_secret_key, +}; + +static int __init crypto_virt_init(void) +{ + virtblk_set_crypto_ops(&virtblk_crypto_qcom_vops); + return 0; +} +module_init(crypto_virt_init); + +#if IS_MODULE(CONFIG_QCOM_CRYPTO_VIRT) +static void __exit crypto_virt_exit(void) +{ + virtblk_set_crypto_ops(NULL); +} +module_exit(crypto_virt_exit); +#endifHow do you instantiate this driver exactly?
This driver is not instantiated per device. It acts as a provider of Qualcomm vendor-specific inline crypto operations, which is based on qcom_scm driver, and registers a global virtblk_crypto_ops instance during module initialization. So that, each blk_crypto_ll_ops from virtio block driver in common kernel can be sent via qcom_smc driver.
Best regards, Krzysztof