On Thu, Aug 27, 2026 at 09:07:14AM -0700, Linlin Zhang wrote: > From: linlzhan <[email protected]> > > For the virtio-blk inline encryption use case, the guest kernel goes > through the normal blk_crypto_key programming flow via SMC call in a > virtual slot format before I/O starts. It then requests the host to > handle that I/O with the key programmed into the corresponding physical > keyslot.
Just a note for other reviewers: This patch is specific to the out-of-band key slot programming approach taken in this series. We are discussing in-band key slot programming where this patch probably won't be necessary. I am skipping this patch for now. > > Introduce a "slot path" that lets a bio carry a pre-programmed physical > ICE keyslot index rather than a blk_crypto_key pointer. Add struct > blk_crypto_slot, containing the physical slot index (phy_slot) and > data_unit_size_bits, and embed it in struct bio_crypt_ctx alongside the > existing bc_key pointer. A NULL bc_key indicates the slot path. > > Provide bio_crypt_set_ctx_by_slot() as the caller-facing API for this > path. Update the internal consumers of bio_crypt_ctx to handle both > paths: > > - __bio_crypt_advance() and bio_crypt_dun_is_contiguous() use > bc_slot.data_unit_size_bits to update the DUN when bc_key is NULL. > - bio_crypt_ctx_compatible() compares phy_slot and data_unit_size_bits > when bc_key is NULL, preserving request-merging for slot-based bios. > - __blk_crypto_submit_bio() short-circuits for the slot path: if the > device exposes a crypto_profile the bio is passed through as-is; > otherwise it fails with BLK_STS_NOTSUPP. The software fallback is > not attempted since the guest has no key material. > - blk_crypto_rq_get_keyslot() skips kernel-side keyslot allocation > when bc_key is NULL. > > There is no functional change to the existing key-based path. > > Signed-off-by: linlzhan <[email protected]> > --- > block/blk-crypto-internal.h | 2 +- > block/blk-crypto.c | 57 ++++++++++++++++++++++++++++++++++--- > include/linux/blk-crypto.h | 25 ++++++++++++++++ > 3 files changed, 79 insertions(+), 5 deletions(-) > > diff --git a/block/blk-crypto-internal.h b/block/blk-crypto-internal.h > index 2c7a0446572a..04035d237f03 100644 > --- a/block/blk-crypto-internal.h > +++ b/block/blk-crypto-internal.h > @@ -176,7 +176,7 @@ static inline void bio_crypt_do_front_merge(struct > request *rq, > blk_status_t __blk_crypto_rq_get_keyslot(struct request *rq); > static inline blk_status_t blk_crypto_rq_get_keyslot(struct request *rq) > { > - if (blk_crypto_rq_is_encrypted(rq)) > + if (blk_crypto_rq_is_encrypted(rq) && rq->crypt_ctx->bc_key) > return __blk_crypto_rq_get_keyslot(rq); > return BLK_STS_OK; > } > diff --git a/block/blk-crypto.c b/block/blk-crypto.c > index bc3a9f59574b..2212d06d3c11 100644 > --- a/block/blk-crypto.c > +++ b/block/blk-crypto.c > @@ -113,11 +113,31 @@ void bio_crypt_set_ctx(struct bio *bio, const struct > blk_crypto_key *key, > > bc->bc_key = key; > memcpy(bc->bc_dun, dun, sizeof(bc->bc_dun)); > + memset(&bc->bc_slot, 0, sizeof(bc->bc_slot)); > > bio->bi_crypt_context = bc; > } > EXPORT_SYMBOL_GPL(bio_crypt_set_ctx); > > +void bio_crypt_set_ctx_by_slot(struct bio *bio, > + const struct blk_crypto_slot *slot, > + const u64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE], > + gfp_t gfp_mask) > +{ > + struct bio_crypt_ctx *bc; > + > + WARN_ON_ONCE(!(gfp_mask & __GFP_DIRECT_RECLAIM)); > + > + bc = mempool_alloc(bio_crypt_ctx_pool, gfp_mask); > + > + bc->bc_key = NULL; > + bc->bc_slot = *slot; > + memcpy(bc->bc_dun, dun, sizeof(bc->bc_dun)); > + > + bio->bi_crypt_context = bc; > +} > +EXPORT_SYMBOL_GPL(bio_crypt_set_ctx_by_slot); > + > void __bio_crypt_free_ctx(struct bio *bio) > { > mempool_free(bio->bi_crypt_context, bio_crypt_ctx_pool); > @@ -156,8 +176,12 @@ void __bio_crypt_advance(struct bio *bio, unsigned int > bytes) > { > struct bio_crypt_ctx *bc = bio->bi_crypt_context; > > - bio_crypt_dun_increment(bc->bc_dun, > - bytes >> bc->bc_key->data_unit_size_bits); > + if (bc->bc_key) > + bio_crypt_dun_increment(bc->bc_dun, > + bytes >> > bc->bc_key->data_unit_size_bits); > + else if (bc->bc_slot.data_unit_size_bits) > + bio_crypt_dun_increment(bc->bc_dun, > + bytes >> > bc->bc_slot.data_unit_size_bits); > } > > /* > @@ -169,7 +193,14 @@ bool bio_crypt_dun_is_contiguous(const struct > bio_crypt_ctx *bc, > const u64 next_dun[BLK_CRYPTO_DUN_ARRAY_SIZE]) > { > int i; > - unsigned int carry = bytes >> bc->bc_key->data_unit_size_bits; > + unsigned int carry; > + > + if (bc->bc_key) > + carry = bytes >> bc->bc_key->data_unit_size_bits; > + else if (bc->bc_slot.data_unit_size_bits) { > + carry = bytes >> bc->bc_slot.data_unit_size_bits; > + } else > + return false; > > for (i = 0; i < BLK_CRYPTO_DUN_ARRAY_SIZE; i++) { > if (bc->bc_dun[i] + carry != next_dun[i]) > @@ -198,7 +229,12 @@ static bool bio_crypt_ctx_compatible(struct > bio_crypt_ctx *bc1, > if (!bc1) > return !bc2; > > - return bc2 && bc1->bc_key == bc2->bc_key; > + if (bc1->bc_key) > + return bc2 && bc1->bc_key == bc2->bc_key; > + else > + return bc2 && !bc2->bc_key && > + bc1->bc_slot.phy_slot == bc2->bc_slot.phy_slot && > + bc1->bc_slot.data_unit_size_bits == > bc2->bc_slot.data_unit_size_bits; > } > > bool bio_crypt_rq_ctx_compatible(struct request *rq, struct bio *bio) > @@ -260,6 +296,19 @@ bool __blk_crypto_submit_bio(struct bio *bio) > return false; > } > > + if (!bc_key) { > + /* > + * Slot path: the ICE keyslot was pre-programmed by the > + * hypervisor. The target device must natively support inline > + * encryption; there is no fallback for slot-based crypto. > + */ > + if (!bdev_get_queue(bdev)->crypto_profile) { > + bio_endio_status(bio, BLK_STS_NOTSUPP); > + return false; > + } > + return true; > + } > + > /* > * If the device does not natively support the encryption context, try > to use > * the fallback if available. > diff --git a/include/linux/blk-crypto.h b/include/linux/blk-crypto.h > index 938ff536838c..33ae52b77522 100644 > --- a/include/linux/blk-crypto.h > +++ b/include/linux/blk-crypto.h > @@ -119,9 +119,28 @@ struct blk_crypto_key { > #define BLK_CRYPTO_MAX_IV_SIZE 32 > #define BLK_CRYPTO_DUN_ARRAY_SIZE (BLK_CRYPTO_MAX_IV_SIZE / sizeof(u64)) > > +/** > + * struct blk_crypto_slot - physical slot context for slot-based inline > crypto > + * @phy_slot: Physical ICE keyslot index (already resolved from > virt). > + * @data_unit_size_bits: log2 of the encryption data unit size; used by > + * __bio_crypt_advance() to increment the DUN correctly > + * when a bio is split. 0 means unknown/unset. > + * > + * Used when a bio carries inline crypto context by physical slot index > rather > + * than by a blk_crypto_key pointer (i.e. bc_key == NULL in bio_crypt_ctx). > + * Set by crypto_vblk when building the bio for a GVM > VIRTIO_BLK_T_CRYPTO_IN/OUT > + * request; left zeroed for all other bio types. > + */ > +struct blk_crypto_slot { > + unsigned int phy_slot; > + unsigned int data_unit_size_bits; > +}; > + > /** > * struct bio_crypt_ctx - an inline encryption context > * @bc_key: the key, algorithm, and data unit size to use > + * @bc_slot: physical slot + data_unit_size_bits for slot-based crypto > + * (used when bc_key == NULL) > * @bc_dun: the data unit number (starting IV) to use > * > * A bio_crypt_ctx specifies that the contents of the bio will be encrypted > (for > @@ -130,6 +149,7 @@ struct blk_crypto_key { > */ > struct bio_crypt_ctx { > const struct blk_crypto_key *bc_key; > + struct blk_crypto_slot bc_slot; > u64 bc_dun[BLK_CRYPTO_DUN_ARRAY_SIZE]; > }; > > @@ -152,6 +172,11 @@ void bio_crypt_set_ctx(struct bio *bio, const struct > blk_crypto_key *key, > const u64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE], > gfp_t gfp_mask); > > +void bio_crypt_set_ctx_by_slot(struct bio *bio, > + const struct blk_crypto_slot *slot, > + const u64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE], > + gfp_t gfp_mask); > + > bool bio_crypt_dun_is_contiguous(const struct bio_crypt_ctx *bc, > unsigned int bytes, > const u64 next_dun[BLK_CRYPTO_DUN_ARRAY_SIZE]); > -- > 2.34.1 >
signature.asc
Description: PGP signature

