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

Commit 27aa4d22 authored by Isaac J. Manjarres's avatar Isaac J. Manjarres
Browse files

soc: qcom: mem-buf: Add support for restricting memory transfers



The mem-buf driver follows a supplier and consumer model
to enforce what the instance of the driver on a particular
Virtual Machine (VM) can and cannot do. These roles are
conveyed through the qcom,mem-buf-capabilities property.

A driver on a VM that has the supplier capability is able
to lend and share memory to other VMs, but cannot request
memory from another VM.

In the other direction, a VM with consumer capability is
only capable of requesting memory from other VMs, but cannot
satisfy memory requests from other VMs.

Change-Id: I1d258bdaafbbdb020831afc85c47f44a5ec93940
Signed-off-by: default avatarIsaac J. Manjarres <isaacm@codeaurora.org>
parent 09451a33
Loading
Loading
Loading
Loading
+36 −7
Original line number Diff line number Diff line
@@ -31,6 +31,10 @@
#define MEM_BUF_TIMEOUT_MS 2000
#define to_rmt_msg(_work) container_of(_work, struct mem_buf_rmt_msg, work)

#define MEM_BUF_CAP_SUPPLIER	BIT(0)
#define MEM_BUF_CAP_CONSUMER	BIT(1)
#define MEM_BUF_CAP_DUAL (MEM_BUF_CAP_SUPPLIER | MEM_BUF_CAP_CONSUMER)

/* Data structures for requesting/maintaining memory from other VMs */
static dev_t mem_buf_dev_no;
static struct class *mem_buf_class;
@@ -48,6 +52,7 @@ static DEFINE_MUTEX(mem_buf_idr_mutex);
static DEFINE_IDR(mem_buf_txn_idr);
static struct task_struct *mem_buf_msgq_recv_thr;
static void *mem_buf_hh_msgq_hdl;
static unsigned char mem_buf_capability;

/**
 * enum mem_buf_msg_type: Message types used by the membuf driver for
@@ -747,7 +752,8 @@ static void mem_buf_process_msg(void *buf, size_t size)
		return;
	}

	if (hdr->msg_type == MEM_BUF_ALLOC_RESP) {
	if ((hdr->msg_type == MEM_BUF_ALLOC_RESP) &&
	    (mem_buf_capability & MEM_BUF_CAP_CONSUMER)) {
		mutex_lock(&mem_buf_idr_mutex);
		txn = idr_find(&mem_buf_txn_idr, hdr->txn_id);
		if (!txn) {
@@ -760,8 +766,9 @@ static void mem_buf_process_msg(void *buf, size_t size)
		}
		mutex_unlock(&mem_buf_idr_mutex);
		kfree(buf);
	} else if (hdr->msg_type == MEM_BUF_ALLOC_REQ ||
		   hdr->msg_type == MEM_BUF_ALLOC_RELINQUISH) {
	} else if ((hdr->msg_type == MEM_BUF_ALLOC_REQ ||
		    hdr->msg_type == MEM_BUF_ALLOC_RELINQUISH) &&
		   (mem_buf_capability & MEM_BUF_CAP_SUPPLIER)) {
		rmt_msg = kmalloc(sizeof(*rmt_msg), GFP_KERNEL);
		if (!rmt_msg) {
			kfree(buf);
@@ -1265,6 +1272,9 @@ void *mem_buf_alloc(struct mem_buf_allocation_data *alloc_data)
	struct file *filp;
	struct mem_buf_desc *membuf;

	if (!(mem_buf_capability & MEM_BUF_CAP_CONSUMER))
		return ERR_PTR(-ENOTSUPP);

	if (!alloc_data)
		return ERR_PTR(-EINVAL);

@@ -1517,6 +1527,9 @@ static long mem_buf_dev_ioctl(struct file *filp, unsigned int cmd,
	switch (cmd) {
	case MEM_BUF_IOC_ALLOC:
	{
		if (!(mem_buf_capability & MEM_BUF_CAP_CONSUMER))
			return -ENOTSUPP;

		fd = mem_buf_alloc_fd(&allocation);

		if (fd < 0)
@@ -1545,13 +1558,29 @@ static const struct file_operations mem_buf_dev_fops = {
static int mem_buf_probe(struct platform_device *pdev)
{
	int ret;
	struct device *dev = &pdev->dev;
	struct device *class_dev;

	if (of_property_match_string(dev->of_node, "qcom,mem-buf-capabilities",
				     "supplier") >= 0) {
		mem_buf_capability = MEM_BUF_CAP_SUPPLIER;
	} else if (of_property_match_string(dev->of_node,
					    "qcom,mem-buf-capabilities",
					    "consumer") >= 0) {
		mem_buf_capability = MEM_BUF_CAP_CONSUMER;
	} else if (of_property_match_string(dev->of_node,
					    "qcom,mem-buf-capabilities",
					    "dual") >= 0) {
		mem_buf_capability = MEM_BUF_CAP_DUAL;
	} else {
		dev_err(dev, "Transfer direction property not present or not valid\n");
		return -EINVAL;
	}

	mem_buf_msgq_recv_thr = kthread_create(mem_buf_msgq_recv_fn, NULL,
					       "mem_buf_rcvr");
	if (IS_ERR(mem_buf_msgq_recv_thr)) {
		dev_err(&pdev->dev,
			"Failed to create msgq receiver thread rc: %d\n",
		dev_err(dev, "Failed to create msgq receiver thread rc: %d\n",
			PTR_ERR(mem_buf_msgq_recv_thr));
		return PTR_ERR(mem_buf_msgq_recv_thr);
	}
@@ -1560,7 +1589,7 @@ static int mem_buf_probe(struct platform_device *pdev)
	if (IS_ERR(mem_buf_hh_msgq_hdl)) {
		ret = PTR_ERR(mem_buf_hh_msgq_hdl);
		if (ret != EPROBE_DEFER)
			dev_err(&pdev->dev,
			dev_err(dev,
				"Message queue registration failed: rc: %d\n",
				ret);
		goto err_msgq_register;
@@ -1571,7 +1600,7 @@ static int mem_buf_probe(struct platform_device *pdev)
	if (ret < 0)
		goto err_cdev_add;

	mem_buf_dev = &pdev->dev;
	mem_buf_dev = dev;
	class_dev = device_create(mem_buf_class, NULL, mem_buf_dev_no, NULL,
				  "membuf");
	if (IS_ERR(class_dev)) {