summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt1
-rw-r--r--drivers/char/adsprpc.c125
-rw-r--r--drivers/char/adsprpc_shared.h1
3 files changed, 119 insertions, 8 deletions
diff --git a/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt b/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt
index 376af82381f2..9a000510c97e 100644
--- a/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt
+++ b/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt
@@ -13,6 +13,7 @@ Optional properties:
- qcom,fastrpc-glink: Flag to use glink instead of smd for IPC
- qcom,fastrpc-vmid-heap-shared: Flag for Dynamic heap feature, to
share HLOS memory buffer to ADSP
+- qcom,secure-domains: FastRPC secure domain configuration
Optional subnodes:
- qcom,msm_fastrpc_compute_cb : Child nodes representing the compute context
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index 23b48dc6981b..d834b5b95db0 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -72,6 +72,16 @@
#define FASTRPC_CTX_MAGIC (0xbeeddeed)
#define FASTRPC_CTX_MAX (256)
#define FASTRPC_CTXID_MASK (0xFF0)
+#define NUM_DEVICES 2 /* adsprpc-smd, adsprpc-smd-secure */
+#define MINOR_NUM_DEV 0
+#define MINOR_NUM_SECURE_DEV 1
+#define NON_SECURE_CHANNEL 0
+#define SECURE_CHANNEL 1
+
+#define ADSP_DOMAIN_ID (0)
+#define MDSP_DOMAIN_ID (1)
+#define SDSP_DOMAIN_ID (2)
+#define CDSP_DOMAIN_ID (3)
#define IS_CACHE_ALIGNED(x) (((x) & ((L1_CACHE_BYTES)-1)) == 0)
@@ -245,6 +255,8 @@ struct fastrpc_channel_ctx {
int ramdumpenabled;
void *remoteheap_ramdump_dev;
struct fastrpc_glink_info link;
+ /* Indicates, if channel is restricted to secure node only */
+ int secure;
};
struct fastrpc_apps {
@@ -321,6 +333,8 @@ struct fastrpc_file {
struct dentry *debugfs_file;
struct mutex map_mutex;
char *debug_buf;
+ /* Identifies the device (MINOR_NUM_DEV / MINOR_NUM_SECURE_DEV) */
+ int dev_minor;
};
static struct fastrpc_apps gfa;
@@ -1683,7 +1697,11 @@ static void fastrpc_init(struct fastrpc_apps *me)
init_completion(&me->channel[i].work);
init_completion(&me->channel[i].workport);
me->channel[i].sesscount = 0;
+ /* All channels are secure by default except CDSP */
+ me->channel[i].secure = SECURE_CHANNEL;
}
+ /* Set CDSP channel to non secure */
+ me->channel[CDSP_DOMAIN_ID].secure = NON_SECURE_CHANNEL;
}
static int fastrpc_release_current_dsp_process(struct fastrpc_file *fl);
@@ -2725,6 +2743,9 @@ static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer,
len += scnprintf(fileinfo + len,
DEBUGFS_SIZE - len, "|%-9d",
chan->ssrcount);
+ len += scnprintf(fileinfo + len,
+ DEBUGFS_SIZE - len, "%s %d\n",
+ "secure:", chan->secure);
for (j = 0; j < chan->sesscount; j++) {
sess_used += chan->session[j].used;
}
@@ -2818,6 +2839,9 @@ static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer,
"0x%-20lX|0x%-20llX|0x%-20zu\n\n",
map->va, map->phys,
map->size);
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%s %d\n\n",
+ "DEV_MINOR:", fl->dev_minor);
}
len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
"%-20s|%-20s|%-20s|%-20s\n",
@@ -2974,6 +2998,19 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
char strpid[PID_SIZE];
int buf_size = 0;
+ /*
+ * Indicates the device node opened
+ * MINOR_NUM_DEV or MINOR_NUM_SECURE_DEV
+ */
+ int dev_minor = MINOR(inode->i_rdev);
+
+ VERIFY(err, ((dev_minor == MINOR_NUM_DEV) ||
+ (dev_minor == MINOR_NUM_SECURE_DEV)));
+ if (err) {
+ pr_err("adsprpc: Invalid dev minor num %d\n", dev_minor);
+ return err;
+ }
+
VERIFY(err, NULL != (fl = kzalloc(sizeof(*fl), GFP_KERNEL)));
if (err)
return err;
@@ -3000,6 +3037,7 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
fl->mode = FASTRPC_MODE_SERIAL;
fl->cid = -1;
fl->init_mem = NULL;
+ fl->dev_minor = dev_minor;
if (debugfs_file != NULL)
fl->debugfs_file = debugfs_file;
@@ -3025,6 +3063,23 @@ static int fastrpc_get_info(struct fastrpc_file *fl, uint32_t *info)
VERIFY(err, cid < NUM_CHANNELS);
if (err)
goto bail;
+ /* Check to see if the device node is non-secure */
+ if (fl->dev_minor == MINOR_NUM_DEV) {
+ /*
+ * For non secure device node check and make sure that
+ * the channel allows non-secure access
+ * If not, bail. Session will not start.
+ * cid will remain -1 and client will not be able to
+ * invoke any other methods without failure
+ */
+ if (fl->apps->channel[cid].secure == SECURE_CHANNEL) {
+ err = -EPERM;
+ pr_err("adsprpc: GetInfo failed dev %d, cid %d, secure %d\n",
+ fl->dev_minor, cid,
+ fl->apps->channel[cid].secure);
+ goto bail;
+ }
+ }
fl->cid = cid;
fl->ssrcount = fl->apps->channel[cid].ssrcount;
VERIFY(err, !fastrpc_session_alloc_locked(
@@ -3462,12 +3517,41 @@ bail:
return err;
}
+static void configure_secure_channels(uint32_t secure_domains)
+{
+ struct fastrpc_apps *me = &gfa;
+ int ii = 0;
+ /*
+ * secure_domains contains the bitmask of the secure channels
+ * Bit 0 - ADSP
+ * Bit 1 - MDSP
+ * Bit 2 - SLPI
+ * Bit 3 - CDSP
+ */
+ for (ii = ADSP_DOMAIN_ID; ii <= CDSP_DOMAIN_ID; ++ii) {
+ int secure = (secure_domains >> ii) & 0x01;
+
+ me->channel[ii].secure = secure;
+ }
+}
+
static int fastrpc_probe(struct platform_device *pdev)
{
int err = 0;
struct fastrpc_apps *me = &gfa;
struct device *dev = &pdev->dev;
-
+ uint32_t secure_domains;
+
+ if (of_get_property(dev->of_node,
+ "qcom,secure-domains", NULL) != NULL) {
+ VERIFY(err, !of_property_read_u32(dev->of_node,
+ "qcom,secure-domains",
+ &secure_domains));
+ if (!err)
+ configure_secure_channels(secure_domains);
+ else
+ pr_info("adsprpc: unable to read the domain configuration from dts\n");
+ }
if (of_device_is_compatible(dev->of_node,
"qcom,msm-fastrpc-compute-cb"))
return fastrpc_cb_probe(dev);
@@ -3543,6 +3627,7 @@ static int __init fastrpc_device_init(void)
{
struct fastrpc_apps *me = &gfa;
struct device *dev = NULL;
+ struct device *secure_dev = NULL;
int err = 0, i;
debugfs_root = debugfs_create_dir("adsprpc", NULL);
@@ -3559,7 +3644,7 @@ static int __init fastrpc_device_init(void)
cdev_init(&me->cdev, &fops);
me->cdev.owner = THIS_MODULE;
VERIFY(err, 0 == cdev_add(&me->cdev, MKDEV(MAJOR(me->dev_no), 0),
- 1));
+ NUM_DEVICES));
if (err)
goto cdev_init_bail;
me->class = class_create(THIS_MODULE, "fastrpc");
@@ -3567,14 +3652,29 @@ static int __init fastrpc_device_init(void)
if (err)
goto class_create_bail;
me->compat = (NULL == fops.compat_ioctl) ? 0 : 1;
+ /*
+ * Create devices and register with sysfs
+ * Create first device with minor number 0
+ */
dev = device_create(me->class, NULL,
- MKDEV(MAJOR(me->dev_no), 0),
- NULL, gcinfo[0].name);
+ MKDEV(MAJOR(me->dev_no), MINOR_NUM_DEV),
+ NULL, DEVICE_NAME);
VERIFY(err, !IS_ERR_OR_NULL(dev));
if (err)
goto device_create_bail;
+
+ /* Create secure device with minor number for secure device */
+ secure_dev = device_create(me->class, NULL,
+ MKDEV(MAJOR(me->dev_no), MINOR_NUM_SECURE_DEV),
+ NULL, DEVICE_NAME_SECURE);
+ VERIFY(err, !IS_ERR_OR_NULL(secure_dev));
+ if (err)
+ goto device_create_bail;
+
for (i = 0; i < NUM_CHANNELS; i++) {
- me->channel[i].dev = dev;
+ me->channel[i].dev = secure_dev;
+ if (i == CDSP_DOMAIN_ID)
+ me->channel[i].dev = dev;
me->channel[i].ssrcount = 0;
me->channel[i].prevssrcount = 0;
me->channel[i].issubsystemup = 1;
@@ -3598,7 +3698,11 @@ device_create_bail:
&me->channel[i].nb);
}
if (!IS_ERR_OR_NULL(dev))
- device_destroy(me->class, MKDEV(MAJOR(me->dev_no), 0));
+ device_destroy(me->class, MKDEV(MAJOR(me->dev_no),
+ MINOR_NUM_DEV));
+ if (!IS_ERR_OR_NULL(secure_dev))
+ device_destroy(me->class, MKDEV(MAJOR(me->dev_no),
+ MINOR_NUM_SECURE_DEV));
class_destroy(me->class);
class_create_bail:
cdev_del(&me->cdev);
@@ -3620,10 +3724,15 @@ static void __exit fastrpc_device_exit(void)
for (i = 0; i < NUM_CHANNELS; i++) {
if (!gcinfo[i].name)
continue;
- device_destroy(me->class, MKDEV(MAJOR(me->dev_no), i));
subsys_notif_unregister_notifier(me->channel[i].handle,
&me->channel[i].nb);
}
+
+ /* Destroy the secure and non secure devices */
+ device_destroy(me->class, MKDEV(MAJOR(me->dev_no), MINOR_NUM_DEV));
+ device_destroy(me->class, MKDEV(MAJOR(me->dev_no),
+ MINOR_NUM_SECURE_DEV));
+
class_destroy(me->class);
cdev_del(&me->cdev);
unregister_chrdev_region(me->dev_no, NUM_CHANNELS);
diff --git a/drivers/char/adsprpc_shared.h b/drivers/char/adsprpc_shared.h
index 4371bf6a2ae7..b79cc2230568 100644
--- a/drivers/char/adsprpc_shared.h
+++ b/drivers/char/adsprpc_shared.h
@@ -34,6 +34,7 @@
#define FASTRPC_GLINK_GUID "fastrpcglink-apps-dsp"
#define FASTRPC_SMD_GUID "fastrpcsmd-apps-dsp"
#define DEVICE_NAME "adsprpc-smd"
+#define DEVICE_NAME_SECURE "adsprpc-smd-secure"
/* Set for buffers that have no virtual mapping in userspace */
#define FASTRPC_ATTR_NOVA 0x1