Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 894cba23 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "soc: qcom: Added support for virtualized FBE"

parents 88dc451d 26ce3040
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -432,6 +432,15 @@ config VIRTIO_BLK
	  This is the virtual block driver for virtio.  It can be used with
          QEMU based VMMs (like KVM or Xen).  Say Y or M.

config VIRTIO_BLK_QTI_CRYPTO
	tristate "Vendor specific VIRTIO Crypto Engine Support"
	depends on VIRTIO_BLK
	help
	 Enable storage inline crypto engine support for guest virtual machine.
	 Enabling this allows kernel to use crypto operations defined
	 and implemented by QTI.
	 Say Y or M.

config VIRTIO_BLK_SCSI
	bool "SCSI passthrough request for the Virtio block driver"
	depends on VIRTIO_BLK
+1 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ obj-$(CONFIG_BLK_DEV_SKD) += skd.o
obj-$(CONFIG_BLK_DEV_UMEM)	+= umem.o
obj-$(CONFIG_BLK_DEV_NBD)	+= nbd.o
obj-$(CONFIG_BLK_DEV_CRYPTOLOOP) += cryptoloop.o
obj-$(CONFIG_VIRTIO_BLK_QTI_CRYPTO) += virtio_blk_qti_crypto.o
obj-$(CONFIG_VIRTIO_BLK)	+= virtio_blk.o

obj-$(CONFIG_BLK_DEV_SX8)	+= sx8.o
+70 −4
Original line number Diff line number Diff line
@@ -16,11 +16,22 @@
#include <linux/blk-mq.h>
#include <linux/blk-mq-virtio.h>
#include <linux/numa.h>
#ifdef CONFIG_QTI_CRYPTO_VIRTUALIZATION
#include <linux/bio-crypt-ctx.h>
#include "virtio_blk_qti_crypto.h"
#endif

#define PART_BITS 4
#define VQ_NAME_LEN 16
#define MAX_DISCARD_SEGMENTS 256u

#ifdef CONFIG_QTI_CRYPTO_VIRTUALIZATION
/* Temporaryly declaring ice supported feature bit.
 * Will discard this macro once uapi chages are mainlined
 */
#define VIRTIO_BLK_F_ICE	23	/* support ice virtualization */
#endif

static int major;
static DEFINE_IDA(vd_index_ida);

@@ -71,6 +82,15 @@ struct virtio_blk {
	struct virtio_blk_vq *vqs;
};

#ifdef CONFIG_QTI_CRYPTO_VIRTUALIZATION
struct virtio_blk_ice_info {
	/*the key slot to use for inline crypto*/
	u8  ice_slot;
	u8  activate;
	u16 reserved;
} __packed;
#endif

struct virtblk_req {
#ifdef CONFIG_VIRTIO_BLK_SCSI
	struct scsi_request sreq;	/* for SCSI passthrough, must be first */
@@ -78,6 +98,9 @@ struct virtblk_req {
	struct virtio_scsi_inhdr in_hdr;
#endif
	struct virtio_blk_outhdr out_hdr;
#ifdef CONFIG_QTI_CRYPTO_VIRTUALIZATION
	struct virtio_blk_ice_info ice_info;
#endif
	u8 status;
	struct scatterlist sg[];
};
@@ -173,8 +196,14 @@ static int virtblk_add_req(struct virtqueue *vq, struct virtblk_req *vbr,
{
	struct scatterlist hdr, status, *sgs[3];
	unsigned int num_out = 0, num_in = 0;

#ifdef CONFIG_QTI_CRYPTO_VIRTUALIZATION
	size_t const hdr_size = virtio_has_feature(vq->vdev, VIRTIO_BLK_F_ICE) ?
				sizeof(vbr->out_hdr) + sizeof(vbr->ice_info) :
				sizeof(vbr->out_hdr);
	sg_init_one(&hdr, &vbr->out_hdr, hdr_size);
#else
	sg_init_one(&hdr, &vbr->out_hdr, sizeof(vbr->out_hdr));
#endif
	sgs[num_out++] = &hdr;

	if (have_data) {
@@ -284,6 +313,25 @@ static void virtio_commit_rqs(struct blk_mq_hw_ctx *hctx)
		virtqueue_notify(vq->vq);
}

#ifdef CONFIG_QTI_CRYPTO_VIRTUALIZATION
static void virtblk_get_ice_info(struct virtio_blk *vblk, struct request *req)
{
	/* whether or not the request needs inline crypto operations*/
	struct bio_crypt_ctx *bc;
	struct virtblk_req *vbr = blk_mq_rq_to_pdu(req);

	if (!bio_crypt_should_process(req)) {
		/* ice is not activated */
		vbr->ice_info.activate = false;
	} else {
		bc = req->bio->bi_crypt_context;
		/* ice is activated - successful flow */
		vbr->ice_info.ice_slot = bc->bc_keyslot;
		vbr->ice_info.activate = true;
	}
}
#endif

static blk_status_t virtio_queue_rq(struct blk_mq_hw_ctx *hctx,
			   const struct blk_mq_queue_data *bd)
{
@@ -333,7 +381,10 @@ static blk_status_t virtio_queue_rq(struct blk_mq_hw_ctx *hctx,
	vbr->out_hdr.sector = type ?
		0 : cpu_to_virtio64(vblk->vdev, blk_rq_pos(req));
	vbr->out_hdr.ioprio = cpu_to_virtio32(vblk->vdev, req_get_ioprio(req));

#ifdef CONFIG_QTI_CRYPTO_VIRTUALIZATION
	if (virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_ICE))
		virtblk_get_ice_info(vblk, req);
#endif
	blk_mq_start_request(req);

	if (type == VIRTIO_BLK_T_DISCARD || type == VIRTIO_BLK_T_WRITE_ZEROES) {
@@ -981,8 +1032,17 @@ static int virtblk_probe(struct virtio_device *vdev)
	}

	virtblk_update_capacity(vblk, false);
	virtio_device_ready(vdev);

#ifdef CONFIG_QTI_CRYPTO_VIRTUALIZATION
	if (virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_ICE)) {
		dev_notice(&vdev->dev, "%s\n", vblk->disk->disk_name);
		/* Initilaize supported crypto capabilities*/
		err = virtblk_init_crypto_qti_spec();
		if (!err)
			virtblk_crypto_qti_setup_rq_keyslot_manager(vblk->disk->queue);
	}
#endif
	virtio_device_ready(vdev);
	device_add_disk(&vdev->dev, vblk->disk, virtblk_attr_groups);
	return 0;

@@ -1007,7 +1067,10 @@ static void virtblk_remove(struct virtio_device *vdev)

	/* Make sure no work handler is accessing the device. */
	flush_work(&vblk->config_work);

#ifdef CONFIG_QTI_CRYPTO_VIRTUALIZATION
	if (virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_ICE))
		virtblk_crypto_qti_destroy_rq_keyslot_manager(vblk->disk->queue);
#endif
	del_gendisk(vblk->disk);
	blk_cleanup_queue(vblk->disk->queue);

@@ -1083,6 +1146,9 @@ static unsigned int features[] = {
	VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE,
	VIRTIO_BLK_F_FLUSH, VIRTIO_BLK_F_TOPOLOGY, VIRTIO_BLK_F_CONFIG_WCE,
	VIRTIO_BLK_F_MQ, VIRTIO_BLK_F_DISCARD, VIRTIO_BLK_F_WRITE_ZEROES,
#ifdef CONFIG_QTI_CRYPTO_VIRTUALIZATION
	VIRTIO_BLK_F_ICE,
#endif
};

static struct virtio_driver virtio_blk = {
+162 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * virtio block crypto ops QTI implementation.
 *
 * Copyright (c) 2021, Linux Foundation. All rights reserved.
 */

#include <linux/device.h>
#include <linux/module.h>
#include <linux/blkdev.h>
#include <linux/crypto_qti_virt.h>
#include <linux/keyslot-manager.h>

/*keyslot manager for vrtual IO*/
static struct keyslot_manager *virtio_ksm;
/*To get max ice slots for guest vm */
static uint32_t num_ice_slots;

void virtblk_crypto_qti_setup_rq_keyslot_manager(struct request_queue *q)
{
		q->ksm = virtio_ksm;
}
EXPORT_SYMBOL(virtblk_crypto_qti_setup_rq_keyslot_manager);

void virtblk_crypto_qti_destroy_rq_keyslot_manager(struct request_queue *q)
{
		keyslot_manager_destroy(virtio_ksm);
}
EXPORT_SYMBOL(virtblk_crypto_qti_destroy_rq_keyslot_manager);

static inline bool virtblk_keyslot_valid(unsigned int slot)
{
	/*
	 * slot numbers range from 0 to max available
	 * slots for vm.
	 */
	return slot < num_ice_slots;
}

static int virtblk_crypto_qti_keyslot_program(struct keyslot_manager *ksm,
						const struct blk_crypto_key *key,
						unsigned int slot)
{
	int err = 0;

	if (!virtblk_keyslot_valid(slot)) {
		pr_err("%s: key slot is not valid\n",
			__func__);
		return -EINVAL;
	}
	err = crypto_qti_virt_program_key(key, slot);
	if (err) {
		pr_err("%s: program key failed with error %d\n",
			__func__, err);
		err = crypto_qti_virt_invalidate_key(slot);
		if (err) {
			pr_err("%s: invalidate key failed with error %d\n",
				__func__, err);
			return err;
		}
	}
	return err;
}

static int virtblk_crypto_qti_keyslot_evict(struct keyslot_manager *ksm,
					const struct blk_crypto_key *key,
					unsigned int slot)
{
	int err = 0;

	if (!virtblk_keyslot_valid(slot)) {
		pr_err("%s: key slot is not valid\n",
			__func__);
		return -EINVAL;
	}
	err = crypto_qti_virt_invalidate_key(slot);
	if (err) {
		pr_err("%s: evict key failed with error %d\n",
			__func__, err);
		return err;
	}
	return err;
}

static int virtblk_crypto_qti_derive_raw_secret(struct keyslot_manager *ksm,
						const u8 *wrapped_key,
						unsigned int wrapped_key_size,
						u8 *secret,
						unsigned int secret_size)
{
	int err = 0;

	if (wrapped_key_size <= RAW_SECRET_SIZE) {
		pr_err("%s: Invalid wrapped_key_size: %u\n",
			__func__, wrapped_key_size);
		err = -EINVAL;
		return err;
	}
	if (secret_size != RAW_SECRET_SIZE) {
		pr_err("%s: Invalid secret size: %u\n",
			__func__, secret_size);
		err = -EINVAL;
		return err;
	}
	err = crypto_qti_virt_derive_raw_secret_platform(wrapped_key,
							 wrapped_key_size,
							 secret,
							 secret_size);
	return err;
}

static const struct keyslot_mgmt_ll_ops virtio_blk_crypto_qti_ksm_ops = {
	.keyslot_program        = virtblk_crypto_qti_keyslot_program,
	.keyslot_evict          = virtblk_crypto_qti_keyslot_evict,
	.derive_raw_secret      = virtblk_crypto_qti_derive_raw_secret,
};

int virtblk_init_crypto_qti_spec(void)
{
	int err = 0;
	int cap_idx = 0;
	unsigned int crypto_modes_supported[BLK_ENCRYPTION_MODE_MAX];

	/* Actual determination of capabilities for UFS/EMMC for different
	 * encryption modes are done in the back end in case of virtualization
	 * driver, so initializing this to 0xFFFFFFFF meaning it supports
	 * all crypto capabilities to please the keyslot manager. feeding
	 * as input parameter to the keyslot manager
	 */
	for (cap_idx = 0; cap_idx < BLK_ENCRYPTION_MODE_MAX; cap_idx++)
		crypto_modes_supported[cap_idx] = 0xFFFFFFFF;
	crypto_modes_supported[BLK_ENCRYPTION_MODE_INVALID] = 0;

	/* Get max number of ice  slots for guest vm */
	err = crypto_qti_virt_ice_get_info(&num_ice_slots);
	if (err) {
		pr_err("crypto_qti_virt_ice_get_info failed error = %d\n", err);
		return err;
	}
	/* Return from here inacse keyslot manger is already created */
	if (virtio_ksm)
		return 0;

	/* create keyslot manager and which will manage the keyslots for all
	 * virtual disks
	 */
	virtio_ksm = keyslot_manager_create(NULL,
					num_ice_slots,
					&virtio_blk_crypto_qti_ksm_ops,
					BLK_CRYPTO_FEATURE_STANDARD_KEYS |
					BLK_CRYPTO_FEATURE_WRAPPED_KEYS,
					crypto_modes_supported,
					NULL);

	if (!virtio_ksm)
		return  -ENOMEM;

	pr_info("%s: keyslot manager created\n", __func__);

	return err;
}
EXPORT_SYMBOL(virtblk_init_crypto_qti_spec);
+35 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2021, The Linux Foundation. All rights reserved.
 */

#ifndef _VIRTIO_BLK_QTI_CRYPTO_H
#define _VIRTIO_BLK_QTI_CRYPTO_H

#include <linux/device.h>
#include <linux/blkdev.h>

/**
 * This function intializes the supported crypto capabilities
 * and create keyslot manager to manage keyslots for virtual
 * disks.
 *
 * Return: zero on success, else a -errno value
 */
int virtblk_init_crypto_qti_spec(void);

/**
 * set up a keyslot manager in the virtual disks request_queue
 *
 * @request_queue: virtual disk request queue
 */
void virtblk_crypto_qti_setup_rq_keyslot_manager(struct request_queue *q);
/**
 * destroy keyslot manager
 *
 * @request_queue: virtual disk request queue
 */
void virtblk_crypto_qti_destroy_rq_keyslot_manager(struct request_queue *q);

#endif /* _VIRTIO_BLK_QTI_CRYPTO_H */
Loading