diff options
| -rw-r--r-- | Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt | 1 | ||||
| -rw-r--r-- | drivers/char/adsprpc.c | 125 | ||||
| -rw-r--r-- | drivers/char/adsprpc_shared.h | 1 |
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 |
